summaryrefslogtreecommitdiff
path: root/extra
diff options
context:
space:
mode:
authorunknown <svoj@mysql.com>2005-04-28 18:23:27 +0500
committerunknown <svoj@mysql.com>2005-04-28 18:23:27 +0500
commite28bf9ef5e6a4240755349a73094bc43806faa9f (patch)
treefaf48fd8da1c6b1e9b69a5e89ebff26bb440b34b /extra
parentb790a34805664e43c37d2b064722ff3ee7d79ad7 (diff)
downloadmariadb-git-e28bf9ef5e6a4240755349a73094bc43806faa9f.tar.gz
WL#2286 Compile MySQL w/YASSL support
yaSSL-0.9.7 library bundled. BUILD/Makefile.am: compile-pentium-debug-yassl added to distribution. Makefile.am: Added yassl_dir to SUBDIRS. It contains path to yassl distribution if --with-yassl specified. It is empty otherwise. configure.in: yaSSL CHECK-function call. extra/Makefile.am: yaSSL added to distribution. include/violite.h: YASSL_MYSQL_COMPATIBLE macro must be defined to make yassl headers compatible.
Diffstat (limited to 'extra')
-rw-r--r--extra/Makefile.am1
-rw-r--r--extra/yassl/AUTHORS0
-rw-r--r--extra/yassl/ChangeLog0
-rw-r--r--extra/yassl/INSTALL229
-rw-r--r--extra/yassl/Makefile.am2
-rw-r--r--extra/yassl/NEWS0
-rw-r--r--extra/yassl/README263
-rw-r--r--extra/yassl/include/buffer.hpp207
-rw-r--r--extra/yassl/include/cert_wrapper.hpp124
-rw-r--r--extra/yassl/include/crypto_wrapper.hpp418
-rw-r--r--extra/yassl/include/factory.hpp106
-rw-r--r--extra/yassl/include/handshake.hpp72
-rw-r--r--extra/yassl/include/lock.hpp90
-rw-r--r--extra/yassl/include/log.hpp58
-rw-r--r--extra/yassl/include/openssl/crypto.h13
-rw-r--r--extra/yassl/include/openssl/des.h1
-rw-r--r--extra/yassl/include/openssl/err.h8
-rw-r--r--extra/yassl/include/openssl/lhash.h2
-rw-r--r--extra/yassl/include/openssl/md5.h1
-rw-r--r--extra/yassl/include/openssl/opensslv.h12
-rw-r--r--extra/yassl/include/openssl/rand.h2
-rw-r--r--extra/yassl/include/openssl/rsa.h10
-rw-r--r--extra/yassl/include/openssl/ssl.h400
-rw-r--r--extra/yassl/include/socket_wrapper.hpp95
-rw-r--r--extra/yassl/include/timer.hpp43
-rw-r--r--extra/yassl/include/yassl_error.hpp78
-rw-r--r--extra/yassl/include/yassl_imp.hpp742
-rw-r--r--extra/yassl/include/yassl_int.hpp538
-rw-r--r--extra/yassl/include/yassl_types.hpp415
-rw-r--r--extra/yassl/mySTL/algorithm.hpp111
-rw-r--r--extra/yassl/mySTL/helpers.hpp94
-rw-r--r--extra/yassl/mySTL/list.hpp374
-rw-r--r--extra/yassl/mySTL/memory.hpp127
-rw-r--r--extra/yassl/mySTL/pair.hpp61
-rw-r--r--extra/yassl/mySTL/stdexcept.hpp72
-rw-r--r--extra/yassl/mySTL/vector.hpp154
-rw-r--r--extra/yassl/src/Makefile.am8
-rw-r--r--extra/yassl/src/buffer.cpp280
-rw-r--r--extra/yassl/src/cert_wrapper.cpp318
-rw-r--r--extra/yassl/src/crypto_wrapper.cpp970
-rw-r--r--extra/yassl/src/handshake.cpp1011
-rw-r--r--extra/yassl/src/lock.cpp90
-rw-r--r--extra/yassl/src/log.cpp148
-rw-r--r--extra/yassl/src/socket_wrapper.cpp168
-rw-r--r--extra/yassl/src/ssl.cpp1039
-rw-r--r--extra/yassl/src/timer.cpp82
-rw-r--r--extra/yassl/src/yassl_error.cpp53
-rw-r--r--extra/yassl/src/yassl_imp.cpp2093
-rw-r--r--extra/yassl/src/yassl_int.cpp1971
-rw-r--r--extra/yassl/taocrypt/Makefile.am2
-rw-r--r--extra/yassl/taocrypt/include/aes.hpp89
-rw-r--r--extra/yassl/taocrypt/include/algebra.hpp316
-rw-r--r--extra/yassl/taocrypt/include/arc4.hpp59
-rw-r--r--extra/yassl/taocrypt/include/asn.hpp327
-rw-r--r--extra/yassl/taocrypt/include/block.hpp211
-rw-r--r--extra/yassl/taocrypt/include/coding.hpp94
-rw-r--r--extra/yassl/taocrypt/include/des.hpp121
-rw-r--r--extra/yassl/taocrypt/include/dh.hpp89
-rw-r--r--extra/yassl/taocrypt/include/dsa.hpp129
-rw-r--r--extra/yassl/taocrypt/include/error.hpp86
-rw-r--r--extra/yassl/taocrypt/include/file.hpp124
-rw-r--r--extra/yassl/taocrypt/include/hash.hpp73
-rw-r--r--extra/yassl/taocrypt/include/hmac.hpp128
-rw-r--r--extra/yassl/taocrypt/include/integer.hpp320
-rw-r--r--extra/yassl/taocrypt/include/md2.hpp67
-rw-r--r--extra/yassl/taocrypt/include/md5.hpp63
-rw-r--r--extra/yassl/taocrypt/include/misc.hpp776
-rw-r--r--extra/yassl/taocrypt/include/modarith.hpp169
-rw-r--r--extra/yassl/taocrypt/include/modes.hpp133
-rw-r--r--extra/yassl/taocrypt/include/random.hpp87
-rw-r--r--extra/yassl/taocrypt/include/ripemd.hpp63
-rw-r--r--extra/yassl/taocrypt/include/rsa.hpp253
-rw-r--r--extra/yassl/taocrypt/include/runtime.hpp91
-rw-r--r--extra/yassl/taocrypt/include/sha.hpp65
-rw-r--r--extra/yassl/taocrypt/src/Makefile.am8
-rw-r--r--extra/yassl/taocrypt/src/aes.cpp401
-rw-r--r--extra/yassl/taocrypt/src/aestables.cpp724
-rw-r--r--extra/yassl/taocrypt/src/algebra.cpp354
-rw-r--r--extra/yassl/taocrypt/src/arc4.cpp93
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp1051
-rw-r--r--extra/yassl/taocrypt/src/coding.cpp250
-rw-r--r--extra/yassl/taocrypt/src/des.cpp435
-rw-r--r--extra/yassl/taocrypt/src/dh.cpp85
-rw-r--r--extra/yassl/taocrypt/src/dsa.cpp277
-rw-r--r--extra/yassl/taocrypt/src/file.cpp118
-rw-r--r--extra/yassl/taocrypt/src/hash.cpp88
-rw-r--r--extra/yassl/taocrypt/src/integer.cpp4174
-rw-r--r--extra/yassl/taocrypt/src/md2.cpp128
-rw-r--r--extra/yassl/taocrypt/src/md5.cpp169
-rw-r--r--extra/yassl/taocrypt/src/misc.cpp132
-rw-r--r--extra/yassl/taocrypt/src/random.cpp131
-rw-r--r--extra/yassl/taocrypt/src/ripemd.cpp289
-rw-r--r--extra/yassl/taocrypt/src/rsa.cpp215
-rw-r--r--extra/yassl/taocrypt/src/sha.cpp144
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsp260
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsw44
-rw-r--r--extra/yassl/yassl.dsp192
-rw-r--r--extra/yassl/yassl.dsw137
98 files changed, 26988 insertions, 0 deletions
diff --git a/extra/Makefile.am b/extra/Makefile.am
index dac6bf0fc0b..3aa4c531709 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -24,6 +24,7 @@ BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \
$(top_builddir)/include/mysqld_ername.h
pkginclude_HEADERS= $(BUILT_SOURCES)
CLEANFILES = $(BUILT_SOURCES)
+DIST_SUBDIRS= yassl
# This will build mysqld_error.h and sql_state.h
$(top_builddir)/include/mysqld_error.h: comp_err
diff --git a/extra/yassl/AUTHORS b/extra/yassl/AUTHORS
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/AUTHORS
diff --git a/extra/yassl/ChangeLog b/extra/yassl/ChangeLog
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/ChangeLog
diff --git a/extra/yassl/INSTALL b/extra/yassl/INSTALL
new file mode 100644
index 00000000000..54caf7c190f
--- /dev/null
+++ b/extra/yassl/INSTALL
@@ -0,0 +1,229 @@
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am
new file mode 100644
index 00000000000..7c1f2ea5acb
--- /dev/null
+++ b/extra/yassl/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = taocrypt src
+EXTRA_DIST = yassl.dsp yassl.dsw mySTL/*.hpp
diff --git a/extra/yassl/NEWS b/extra/yassl/NEWS
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/extra/yassl/NEWS
diff --git a/extra/yassl/README b/extra/yassl/README
new file mode 100644
index 00000000000..198a1031cb7
--- /dev/null
+++ b/extra/yassl/README
@@ -0,0 +1,263 @@
+yaSSL Release notes, version 0.9.6
+
+This release of yaSSL contains minor bug fixes, removal of STL support, and
+removal of exceptions and rtti so that the library can be linked without the
+std c++ library.
+
+--To build on Linux, Solaris, FreeBSD, Mac OS X, or Cygwin
+
+./configure
+make
+
+run testsuite from yaSSL-Home/testsuite to test the build
+
+
+--To build on Win32
+
+Choose (Re)Build All from the project workspace
+
+run Debug\testsuite.exe from yaSSL-Home\testsuite to test the build
+
+
+
+******************yaSSL Release notes, version 0.9.2
+
+This release of yaSSL contains minor bug fixes, expanded certificate
+verification and chaining, and improved documentation.
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.9.0
+
+This release of yaSSL contains minor bug fixes, client verification handling,
+hex and base64 encoing/decoding, and an improved test suite.
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.8.0
+
+This release of yaSSL contains minor bug fixes, and initial porting effort to
+64bit, BigEndian, and more UNIX systems.
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.6.0
+
+This release of yaSSL contains minor bug fixes, source cleanup, and binary beta
+(1) of the yaSSL libraries.
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.5.0
+
+This release of yaSSL contains minor bug fixes, full session resumption
+support, and initial testing suite support.
+
+
+
+Please see build instructions in release notes 0.3.0.
+
+
+
+******************yaSSL Release notes, version 0.4.0
+
+This release of yaSSL contains minor bug fixes, an optional memory tracker,
+an echo client and server with input/output redirection for load testing,
+and initial session caching support.
+
+
+Please see build instructions in release notes 0.3.0.
+
+
+******************yaSSL Release notes, version 0.3.5
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library including a full test suite.
+
+
+*******************yaSSL Release notes, version 0.3.0
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library including AES and an improved random number generator. GNU autoconf
+and automake are now used to simplify the build process on Linux.
+
+*** Linux Build process
+
+./configure
+make
+
+*** Windows Build process
+
+open the yassl workspace and build the project
+
+
+*******************yaSSL Release notes, version 0.2.9
+
+This release of yaSSL contains minor bug fixes and extensions to the crypto
+library.
+
+See the notes at the bottom of this page for build instructions.
+
+
+*******************yaSSL Release notes, version 0.2.5
+
+This release of yaSSL contains minor bug fixes and a beta binary of the yaSSL
+libraries for win32 and linux.
+
+See the notes at the bottom of this page for build instructions.
+
+
+
+*******************yaSSL Release notes, version 0.2.0
+
+This release of yaSSL contains minor bug fixes and initial alternate crypto
+functionality.
+
+*** Complete Build ***
+
+See the notes in Readme.txt for build instructions.
+
+*** Update Build ***
+
+If you have already done a complete build of yaSSL as described in the release
+0.0.1 - 0.1.0 notes and downloaded the update to 0.2.0, place the update file
+yassl-update-0.2.0.tar.gz in the yaSSL home directory and issue the command:
+
+gzip -cd yassl-update-0.2.0.tar.gz | tar xvf -
+
+to update the previous release.
+
+Then issue the make command on linux or rebuild the yaSSL project on Windows.
+
+*******************yaSSL Release notes, version 0.1.0
+
+This release of yaSSL contains minor bug fixes, full client and server TLSv1
+support including full ephemeral Diffie-Hellman support, SSL type RSA and DSS
+signing and verification, and initial stunnel 4.05 build support.
+
+
+
+*********************yaSSL Release notes, version 0.0.3
+
+The third release of yaSSL contains minor bug fixes, client certificate
+enhancements, and initial ephemeral Diffie-Hellman integration:
+
+
+
+*********************
+
+yaSSL Release notes, version 0.0.2
+
+The second release of yaSSL contains minor bug fixes, client certificate
+enhancements, session resumption, and improved TLS support including:
+
+- HMAC for MD5 and SHA-1
+- PRF (pseudo random function)
+- Master Secret and Key derivation routines
+- Record Authentication codes
+- Finish verify data check
+
+Once ephemeral RSA and DH are added yaSSL will be fully complaint with TLS.
+
+
+
+**********************
+
+yassl Release notes, version 0.0.1
+
+The first release of yassl supports normal RSA mode SSLv3 connections with
+support for SHA-1 and MD5 digests. Ciphers include DES, 3DES, and RC4.
+
+yassl uses the CryptoPP library for cryptography, the source is available at
+www.cryptopp.com .
+
+yassl uses CML (the Certificate Management Library) for x509 support. More
+features will be in future versions. The CML source is available for download
+from www.digitalnet.com/knowledge/cml_home.htm .
+
+The next release of yassl will support the 3 lesser-used SSL connection modes;
+HandShake resumption, Ephemeral RSA (or DH), and Client Authentication as well
+as full support for TLS. Backwards support for SSLv2 is not planned at this
+time.
+
+
+**********************
+
+Building yassl on linux:
+
+use the ./buildall script to build everything.
+
+buildall will configure and build CML, CryptoPP, and yassl. Testing was
+preformed with gcc version 3.3.2 on kernel 2.4.22.
+
+
+**********************
+
+Building yassl on Windows:
+
+Testing was preformed on Windows 2000 with Visual C++ 6 sp5.
+
+1) decompress esnacc_r16.tgz in place, see buildall for syntax if unsure
+
+2) decompress smp_r23.tgz in place
+
+3) unzip cryptopp51/crypto51.zip in place
+
+4) Build SNACC (part of CML) using snacc_builds.dsw in the SNACC directory
+
+5) Build SMP (part of CMP) using smp.dsw in the smp directory
+
+6) Build yassl using yassl.dsw
+
+
+**********************
+
+examples, server and client:
+
+Please see the server and client examples in both versions to see how to link
+to yassl and the support libraries. On linux do 'make server' and 'make
+client' to build them. On Windows you will find the example projects in the
+main workspace, yassl.dsw.
+
+The example server and client are compatible with openssl.
+
+
+**********************
+
+Building yassl into mysql on linux:
+
+Testing was done using mysql version 4.0.17.
+
+alter openssl_libs in the configure file, line 21056. Change '-lssl -lcrypto'
+to '-lyassl -lcryptopp -lcmapi -lcmlasn -lctil -lc++asn1'.
+
+see build/config_command for the configure command used to configure mysql
+please change /home/touska/ to the relevant directory of course.
+
+add yassl/lib to the LD_LIBRARY_PATH because libmysql/conf_to_src does not
+use the ssl lib directory though it does use the ssl libraries.
+
+make
+
+make install
+
+
+*********************
+
+License: yassl is currently under the GPL, please see license information
+in the source and include files.
+
+
+*********************
+
+Contact: please send comments or questions to Todd A Ouska at todd@yassl.com
+and/or Larry Stefonic at larry@yassl.com or 425-741-6858.
+
+
+
diff --git a/extra/yassl/include/buffer.hpp b/extra/yassl/include/buffer.hpp
new file mode 100644
index 00000000000..126bdbc19b7
--- /dev/null
+++ b/extra/yassl/include/buffer.hpp
@@ -0,0 +1,207 @@
+/* buffer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL buffer header defines input and output buffers to simulate streaming
+ * with SSL types and sockets
+ */
+
+#ifndef yaSSL_BUFFER_HPP
+#define yaSSL_BUFFER_HPP
+
+#include <cassert> // assert
+#include "yassl_error.hpp" // Error
+#include "memory.hpp" // mySTL::auto_ptr
+#include "algorithm.hpp" // mySTL::swap
+
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+
+namespace yaSSL {
+
+typedef unsigned char byte;
+typedef unsigned int uint;
+const uint AUTO = 0xFEEDBEEF;
+
+
+// Checking Policy should implement a check function that tests whether the
+// index is within the size limit of the array
+struct Check {
+ void check(uint i, uint limit);
+};
+
+
+struct NoCheck {
+ void check(uint, uint);
+};
+
+/* input_buffer operates like a smart c style array with a checking option,
+ * meant to be read from through [] with AUTO index or read().
+ * Should only write to at/near construction with assign() or raw (e.g., recv)
+ * followed by add_size with the number of elements added by raw write.
+ *
+ * Not using vector because need checked []access, offset, and the ability to
+ * write to the buffer bulk wise and have the correct size
+ */
+
+class input_buffer : public Check {
+ uint size_; // number of elements in buffer
+ uint current_; // current offset position in buffer
+ byte* buffer_; // storage for buffer
+ byte* end_; // end of storage marker
+public:
+ input_buffer();
+
+ explicit input_buffer(uint s);
+
+ // with assign
+ input_buffer(uint s, const byte* t, uint len);
+
+ ~input_buffer();
+
+ // users can pass defualt zero length buffer and then allocate
+ void allocate(uint s);
+
+ // for passing to raw writing functions at beginning, then use add_size
+ byte* get_buffer() const;
+
+ // after a raw write user can set new size
+ // if you know the size before the write use assign()
+ void add_size(uint i);
+
+ uint get_capacity() const;
+
+ uint get_current() const;
+
+ uint get_size() const;
+
+ uint get_remaining() const;
+
+ void set_current(uint i);
+
+ // read only access through [], advance current
+ // user passes in AUTO index for ease of use
+ const byte& operator[](uint i);
+
+ // end of input test
+ bool eof();
+
+ // peek ahead
+ byte peek() const;
+
+ // write function, should use at/near construction
+ void assign(const byte* t, uint s);
+
+ // use read to query input, adjusts current
+ void read(byte* dst, uint length);
+
+private:
+ input_buffer(const input_buffer&); // hide copy
+ input_buffer& operator=(const input_buffer&); // and assign
+};
+
+
+/* output_buffer operates like a smart c style array with a checking option.
+ * Meant to be written to through [] with AUTO index or write().
+ * Size (current) counter increases when written to. Can be constructed with
+ * zero length buffer but be sure to allocate before first use.
+ * Don't use add write for a couple bytes, use [] instead, way less overhead.
+ *
+ * Not using vector because need checked []access and the ability to
+ * write to the buffer bulk wise and retain correct size
+ */
+class output_buffer : public Check {
+ uint current_; // current offset and elements in buffer
+ byte* buffer_; // storage for buffer
+ byte* end_; // end of storage marker
+public:
+ // default
+ output_buffer();
+
+ // with allocate
+ explicit output_buffer(uint s);
+
+ // with assign
+ output_buffer(uint s, const byte* t, uint len);
+
+ ~output_buffer();
+
+ uint get_size() const;
+
+ uint get_capacity() const;
+
+ void set_current(uint c);
+
+ // users can pass defualt zero length buffer and then allocate
+ void allocate(uint s);
+
+ // for passing to reading functions when finished
+ const byte* get_buffer() const;
+
+ // allow write access through [], update current
+ // user passes in AUTO as index for ease of use
+ byte& operator[](uint i);
+
+ // end of output test
+ bool eof();
+
+ void write(const byte* t, uint s);
+
+private:
+ output_buffer(const output_buffer&); // hide copy
+ output_buffer& operator=(const output_buffer&); // and assign
+};
+
+
+
+
+// turn delete an incomplete type into comipler error instead of warning
+template <typename T>
+inline void checked_delete(T* p)
+{
+ typedef char complete_type[sizeof(T) ? 1 : -1];
+ (void)sizeof(complete_type);
+ delete p;
+}
+
+
+// checked delete functor increases effeciency, no indirection on function call
+// sets pointer to zero so safe for std conatiners
+struct del_ptr_zero
+{
+ template <typename T>
+ void operator()(T*& p) const
+ {
+ T* tmp = 0;
+ mySTL::swap(tmp, p);
+ checked_delete(tmp);
+ }
+};
+
+
+
+} // naemspace
+
+#endif // yaSSL_BUUFER_HPP
diff --git a/extra/yassl/include/cert_wrapper.hpp b/extra/yassl/include/cert_wrapper.hpp
new file mode 100644
index 00000000000..2381347c27e
--- /dev/null
+++ b/extra/yassl/include/cert_wrapper.hpp
@@ -0,0 +1,124 @@
+/* cert_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The certificate wrapper header defines certificate management functions
+ *
+ */
+
+
+#ifndef yaSSL_CERT_WRAPPER_HPP
+#define yaSSL_CERT_WRAPPER_HPP
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+
+#include "yassl_types.hpp" // SignatureAlgorithm
+#include "buffer.hpp" // input_buffer
+#include "asn.hpp" // SignerList
+#include "list.hpp" // mySTL::list
+#include "algorithm.hpp" // mySTL::for_each
+
+namespace yaSSL {
+
+typedef unsigned char opaque;
+class X509; // forward openSSL type
+
+using TaoCrypt::SignerList;
+
+// an x509 version 3 certificate
+class x509 {
+ uint length_;
+ opaque* buffer_;
+public:
+ explicit x509(uint sz);
+ ~x509();
+
+ uint get_length() const;
+ const opaque* get_buffer() const;
+ opaque* use_buffer();
+
+ x509(const x509&);
+ x509& operator=(const x509&);
+private:
+ void Swap(x509&);
+};
+
+
+// Certificate Manager keeps a list of the cert chain and public key
+class CertManager {
+ typedef mySTL::list<x509*> CertList;
+
+ CertList list_; // self
+ input_buffer privateKey_;
+
+ CertList peerList_; // peer
+ input_buffer peerPublicKey_;
+ X509* peerX509_; // peer's openSSL X509
+
+ SignatureAlgorithm keyType_; // self key type
+ SignatureAlgorithm peerKeyType_; // peer's key type
+
+ SignerList signers_; // decoded CA keys and names
+ // plus verified chained certs
+ bool verifyPeer_;
+ bool failNoCert_;
+ bool sendVerify_;
+public:
+ CertManager();
+ ~CertManager();
+
+ void AddPeerCert(x509* x); // take ownership
+ void CopySelfCert(const x509* x);
+ int CopyCaCert(const x509* x);
+ int Validate();
+
+ int SetPrivateKey(const x509&);
+
+ const x509* get_cert() const;
+ const opaque* get_peerKey() const;
+ const opaque* get_privateKey() const;
+ X509* get_peerX509() const;
+ SignatureAlgorithm get_keyType() const;
+ SignatureAlgorithm get_peerKeyType() const;
+
+ uint get_peerKeyLength() const;
+ uint get_privateKeyLength() const;
+
+ bool verifyPeer() const;
+ bool failNoCert() const;
+ bool sendVerify() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+ void setSendVerify();
+private:
+ CertManager(const CertManager&); // hide copy
+ CertManager& operator=(const CertManager&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_CERT_WRAPPER_HPP
diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp
new file mode 100644
index 00000000000..fa60c774cd9
--- /dev/null
+++ b/extra/yassl/include/crypto_wrapper.hpp
@@ -0,0 +1,418 @@
+/* crypto_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The crypto wrapper header is used to define policies for the cipher
+ * components used by SSL. There are 3 policies to consider:
+ *
+ * 1) MAC, the Message Authentication Code used for each Message
+ * 2) Bulk Cipher, the Cipher used to encrypt/decrypt each Message
+ * 3) Atuhentication, the Digitial Signing/Verifiaction scheme used
+ *
+ * This header doesn't rely on a specific crypto libraries internals,
+ * only the implementation should.
+ */
+
+
+#ifndef yaSSL_CRYPTO_WRAPPER_HPP
+#define yaSSL_CRYPTO_WRAPPER_HPP
+
+#include "yassl_types.hpp"
+
+
+namespace yaSSL {
+
+
+// Digest policy should implement a get_digest, update, and get sizes for pad and
+// digest
+struct Digest {
+ virtual void get_digest(byte*) = 0;
+ virtual void get_digest(byte*, const byte*, unsigned int) = 0;
+ virtual void update(const byte*, unsigned int) = 0;
+ virtual uint get_digestSize() const = 0;
+ virtual uint get_padSize() const = 0;
+ virtual ~Digest() {}
+};
+
+
+// For use with NULL Digests
+struct NO_MAC : public Digest {
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+};
+
+
+// MD5 Digest
+class MD5 : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ MD5();
+ ~MD5();
+ MD5(const MD5&);
+ MD5& operator=(const MD5&);
+private:
+ struct MD5Impl;
+ MD5Impl* pimpl_;
+};
+
+
+// SHA-1 Digest
+class SHA : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ SHA();
+ ~SHA();
+ SHA(const SHA&);
+ SHA& operator=(const SHA&);
+private:
+ struct SHAImpl;
+ SHAImpl* pimpl_;
+
+};
+
+
+// RIPEMD-160 Digest
+class RMD : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ RMD();
+ ~RMD();
+ RMD(const RMD&);
+ RMD& operator=(const RMD&);
+private:
+ struct RMDImpl;
+ RMDImpl* pimpl_;
+
+};
+
+
+// HMAC_MD5
+class HMAC_MD5 : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_MD5(const byte*, unsigned int);
+ ~HMAC_MD5();
+private:
+ struct HMAC_MD5Impl;
+ HMAC_MD5Impl* pimpl_;
+
+ HMAC_MD5(const HMAC_MD5&);
+ HMAC_MD5& operator=(const HMAC_MD5&);
+};
+
+
+// HMAC_SHA-1
+class HMAC_SHA : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_SHA(const byte*, unsigned int);
+ ~HMAC_SHA();
+private:
+ struct HMAC_SHAImpl;
+ HMAC_SHAImpl* pimpl_;
+
+ HMAC_SHA(const HMAC_SHA&);
+ HMAC_SHA& operator=(const HMAC_SHA&);
+};
+
+
+// HMAC_RMD
+class HMAC_RMD : public Digest {
+public:
+ void get_digest(byte*);
+ void get_digest(byte*, const byte*, unsigned int);
+ void update(const byte*, unsigned int);
+ uint get_digestSize() const;
+ uint get_padSize() const;
+ HMAC_RMD(const byte*, unsigned int);
+ ~HMAC_RMD();
+private:
+ struct HMAC_RMDImpl;
+ HMAC_RMDImpl* pimpl_;
+
+ HMAC_RMD(const HMAC_RMD&);
+ HMAC_RMD& operator=(const HMAC_RMD&);
+};
+
+
+// BulkCipher policy should implement encrypt, decrypt, get block size,
+// and set keys for encrypt and decrypt
+struct BulkCipher {
+ virtual void encrypt(byte*, const byte*, unsigned int) = 0;
+ virtual void decrypt(byte*, const byte*, unsigned int) = 0;
+ virtual void set_encryptKey(const byte*, const byte* = 0) = 0;
+ virtual void set_decryptKey(const byte*, const byte* = 0) = 0;
+ virtual uint get_blockSize() const = 0;
+ virtual int get_keySize() const = 0;
+ virtual int get_ivSize() const = 0;
+ virtual ~BulkCipher() {}
+};
+
+
+// For use with NULL Ciphers
+struct NO_Cipher : public BulkCipher {
+ void encrypt(byte*, const byte*, unsigned int) {}
+ void decrypt(byte*, const byte*, unsigned int) {}
+ void set_encryptKey(const byte*, const byte*) {}
+ void set_decryptKey(const byte*, const byte*) {}
+ uint get_blockSize() const { return 0; }
+ int get_keySize() const { return 0; }
+ int get_ivSize() const { return 0; }
+};
+
+
+// SSLv3 and TLSv1 always use DES in CBC mode so IV is required
+class DES : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return DES_BLOCK; }
+ int get_keySize() const { return DES_KEY_SZ; }
+ int get_ivSize() const { return DES_IV_SZ; }
+ DES();
+ ~DES();
+private:
+ struct DESImpl;
+ DESImpl* pimpl_;
+
+ DES(const DES&); // hide copy
+ DES& operator=(const DES&); // & assign
+};
+
+
+// 3DES Encrypt-Decrypt-Encrypt in CBC mode
+class DES_EDE : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return DES_BLOCK; }
+ int get_keySize() const { return DES_EDE_KEY_SZ; }
+ int get_ivSize() const { return DES_IV_SZ; }
+ DES_EDE();
+ ~DES_EDE();
+private:
+ struct DES_EDEImpl;
+ DES_EDEImpl* pimpl_;
+
+ DES_EDE(const DES_EDE&); // hide copy
+ DES_EDE& operator=(const DES_EDE&); // & assign
+};
+
+
+// Alledged RC4
+class RC4 : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return 0; }
+ int get_keySize() const { return RC4_KEY_SZ; }
+ int get_ivSize() const { return 0; }
+ RC4();
+ ~RC4();
+private:
+ struct RC4Impl;
+ RC4Impl* pimpl_;
+
+ RC4(const RC4&); // hide copy
+ RC4& operator=(const RC4&); // & assign
+};
+
+
+// AES
+class AES : public BulkCipher {
+public:
+ void encrypt(byte*, const byte*, unsigned int);
+ void decrypt(byte*, const byte*, unsigned int);
+ void set_encryptKey(const byte*, const byte*);
+ void set_decryptKey(const byte*, const byte*);
+ uint get_blockSize() const { return AES_BLOCK_SZ; }
+ int get_keySize() const;
+ int get_ivSize() const { return AES_IV_SZ; }
+ explicit AES(unsigned int = AES_128_KEY_SZ);
+ ~AES();
+private:
+ struct AESImpl;
+ AESImpl* pimpl_;
+
+ AES(const AES&); // hide copy
+ AES& operator=(const AES&); // & assign
+};
+
+
+// Random number generator
+class RandomPool {
+public:
+ void Fill(opaque* dst, uint sz) const;
+ RandomPool();
+ ~RandomPool();
+
+ int GetError() const;
+
+ friend class RSA;
+ friend class DSS;
+ friend class DiffieHellman;
+private:
+ struct RandomImpl;
+ RandomImpl* pimpl_;
+
+ RandomPool(const RandomPool&); // hide copy
+ RandomPool& operator=(const RandomPool&); // & assign
+};
+
+
+// Authentication policy should implement sign, and verify
+struct Auth {
+ virtual void sign(byte*, const byte*, unsigned int, const RandomPool&) = 0;
+ virtual bool verify(const byte*, unsigned int, const byte*,
+ unsigned int) = 0;
+ virtual uint get_signatureLength() const = 0;
+ virtual ~Auth() {}
+};
+
+
+// For use with NULL Authentication schemes
+struct NO_Auth : public Auth {
+ void sign(byte*, const byte*, unsigned int, const RandomPool&) {}
+ bool verify(const byte*, unsigned int, const byte*, unsigned int)
+ { return true; }
+};
+
+
+// Digitial Signature Standard scheme
+class DSS : public Auth {
+public:
+ void sign(byte*, const byte*, unsigned int, const RandomPool&);
+ bool verify(const byte*, unsigned int, const byte*, unsigned int);
+ uint get_signatureLength() const;
+ DSS(const byte*, unsigned int, bool publicKey = true);
+ ~DSS();
+private:
+ struct DSSImpl;
+ DSSImpl* pimpl_;
+
+ DSS(const DSS&);
+ DSS& operator=(const DSS&);
+};
+
+
+// RSA Authentication and exchange
+class RSA : public Auth {
+public:
+ void sign(byte*, const byte*, unsigned int, const RandomPool&);
+ bool verify(const byte*, unsigned int, const byte*, unsigned int);
+ void encrypt(byte*, const byte*, unsigned int, const RandomPool&);
+ void decrypt(byte*, const byte*, unsigned int, const RandomPool&);
+ uint get_signatureLength() const;
+ uint get_cipherLength() const;
+ RSA(const byte*, unsigned int, bool publicKey = true);
+ ~RSA();
+private:
+ struct RSAImpl;
+ RSAImpl* pimpl_;
+
+ RSA(const RSA&); // hide copy
+ RSA& operator=(const RSA&); // & assing
+};
+
+
+class Integer;
+
+// Diffie-Hellman agreement
+// hide for now TODO: figure out a way to give access to C clients p and g args
+class DiffieHellman {
+public:
+ DiffieHellman(const byte*, unsigned int, const byte*, unsigned int,
+ const byte*, unsigned int, const RandomPool& random);
+ //DiffieHellman(const char*, const RandomPool&);
+ DiffieHellman(const Integer&, const Integer&, const RandomPool&);
+ ~DiffieHellman();
+
+ DiffieHellman(const DiffieHellman&);
+ DiffieHellman& operator=(const DiffieHellman&);
+
+ uint get_agreedKeyLength() const;
+ const byte* get_agreedKey() const;
+ const byte* get_publicKey() const;
+ void makeAgreement(const byte*);
+
+ void set_sizes(int&, int&, int&) const;
+ void get_parms(byte*, byte*, byte*) const;
+private:
+ struct DHImpl;
+ DHImpl* pimpl_;
+};
+
+
+// Lagrge Integer
+class Integer {
+public:
+ Integer();
+ ~Integer();
+
+ Integer(const Integer&);
+ Integer& operator=(const Integer&);
+
+ void assign(const byte*, unsigned int);
+
+ friend class DiffieHellman;
+private:
+ struct IntegerImpl;
+ IntegerImpl* pimpl_;
+};
+
+
+class x509;
+
+x509* PemToDer(const char*, CertType);
+
+
+} // naemspace
+
+#endif // yaSSL_CRYPTO_WRAPPER_HPP
diff --git a/extra/yassl/include/factory.hpp b/extra/yassl/include/factory.hpp
new file mode 100644
index 00000000000..96798466352
--- /dev/null
+++ b/extra/yassl/include/factory.hpp
@@ -0,0 +1,106 @@
+/* factory.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* The factory header defines an Object Factory, used by SSL message and
+ * handshake types.
+ *
+ * See Desgin Pattern in GoF and Alexandrescu's chapter in Modern C++ Design,
+ * page 208
+ */
+
+
+
+#ifndef yaSSL_FACTORY_HPP
+#define yaSSL_FACTORY_HPP
+
+#include "vector.hpp"
+#include "pair.hpp"
+#include "yassl_error.hpp"
+
+
+
+// VC60 workaround: it doesn't allow typename in some places
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ #define CPP_TYPENAME
+#else
+ #define CPP_TYPENAME typename
+#endif
+
+
+namespace yaSSL {
+
+
+// Factory uses its callback map to create objects by id,
+// returning an abstract base pointer
+template<class AbstractProduct,
+ typename IdentifierType = int,
+ typename ProductCreator = AbstractProduct* (*)()
+ >
+class Factory {
+ typedef mySTL::pair<IdentifierType, ProductCreator> CallBack;
+ typedef mySTL::vector<CallBack> CallBackVector;
+
+ CallBackVector callbacks_;
+public:
+ // pass function pointer to register all callbacks upon creation
+ explicit Factory(void (*init)(Factory<AbstractProduct, IdentifierType,
+ ProductCreator>&))
+ {
+ init(*this);
+ }
+
+ // reservce place in vector before registering, used by init funcion
+ void Reserve(size_t sz)
+ {
+ callbacks_.reserve(sz);
+ }
+
+ // register callback
+ void Register(const IdentifierType& id, ProductCreator pc)
+ {
+ callbacks_.push_back(mySTL::make_pair(id, pc));
+ }
+
+ // THE Creator, returns a new object of the proper type or 0
+ AbstractProduct* CreateObject(const IdentifierType& id) const
+ {
+ const CallBack* first = callbacks_.begin();
+ const CallBack* last = callbacks_.end();
+
+ while (first != last) {
+ if (first->first == id)
+ break;
+ ++first;
+ }
+
+ if (first == callbacks_.end())
+ return 0;
+ return (first->second)();
+ }
+private:
+ Factory(const Factory&); // hide copy
+ Factory& operator=(const Factory&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_FACTORY_HPP
diff --git a/extra/yassl/include/handshake.hpp b/extra/yassl/include/handshake.hpp
new file mode 100644
index 00000000000..6261359cd58
--- /dev/null
+++ b/extra/yassl/include/handshake.hpp
@@ -0,0 +1,72 @@
+/* handshake.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* The handshake header declares function prototypes for creating and reading
+ * the various handshake messages.
+ */
+
+
+
+#ifndef yaSSL_HANDSHAKE_HPP
+#define yaSSL_HANDSHAKE_HPP
+
+#include "yassl_types.hpp"
+
+
+namespace yaSSL {
+
+// forward decls
+class SSL;
+class Finished;
+class Data;
+class Alert;
+struct Hashes;
+
+enum BufferOutput { buffered, unbuffered };
+
+void sendClientHello(SSL&);
+void sendServerHello(SSL&, BufferOutput = buffered);
+void sendServerHelloDone(SSL&, BufferOutput = buffered);
+void sendClientKeyExchange(SSL&, BufferOutput = buffered);
+void sendServerKeyExchange(SSL&, BufferOutput = buffered);
+void sendChangeCipher(SSL&, BufferOutput = buffered);
+void sendFinished(SSL&, ConnectionEnd, BufferOutput = buffered);
+void sendCertificate(SSL&, BufferOutput = buffered);
+void sendCertificateRequest(SSL&, BufferOutput = buffered);
+void sendCertificateVerify(SSL&, BufferOutput = buffered);
+int sendData(SSL&, const void*, int);
+int sendAlert(SSL& ssl, const Alert& alert);
+
+int receiveData(SSL&, Data&);
+void processReply(SSL&);
+
+void buildFinished(SSL&, Finished&, const opaque*);
+void build_certHashes(SSL&, Hashes&);
+
+void hmac(SSL&, byte*, const byte*, uint, ContentType, bool verify = false);
+void TLS_hmac(SSL&, byte*, const byte*, uint, ContentType,
+ bool verify = false);
+void PRF(byte* digest, uint digLen, const byte* secret, uint secLen,
+ const byte* label, uint labLen, const byte* seed, uint seedLen);
+
+} // naemspace
+
+#endif // yaSSL_HANDSHAKE_HPP
diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp
new file mode 100644
index 00000000000..11a623879d4
--- /dev/null
+++ b/extra/yassl/include/lock.hpp
@@ -0,0 +1,90 @@
+/* lock.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* lock.hpp provides an os specific Lock, locks mutex on entry and unlocks
+ * automatically upon exit, no-ops provided for Single Threaded
+*/
+
+#ifndef yaSSL_LOCK_HPP
+#define yaSSL_LOCK_HPP
+
+
+namespace yaSSL {
+
+
+#ifdef MULTI_THREADED
+ #ifdef WIN32
+ #include <windows.h>
+
+ class Mutex {
+ CRITICAL_SECTION cs_;
+ public:
+ Mutex();
+ ~Mutex();
+
+ class Lock;
+ friend class Lock;
+
+ class Lock {
+ Mutex& mutex_;
+ public:
+ explicit Lock(Mutex& lm);
+ ~Lock();
+ };
+ };
+ #else // WIN32
+ #include <pthread.h>
+
+ class Mutex {
+ pthread_mutex_t mutex_;
+ public:
+
+ Mutex();
+ ~Mutex();
+
+ class Lock;
+ friend class Lock;
+
+ class Lock {
+ Mutex& mutex_;
+ public:
+ explicit Lock(Mutex& lm);
+ ~Lock();
+ };
+ };
+
+ #endif // WIN32
+#else // MULTI_THREADED (WE'RE SINGLE)
+
+ class Mutex {
+ public:
+ class Lock {
+ public:
+ explicit Lock(Mutex&) {}
+ };
+ };
+
+#endif // MULTI_THREADED
+
+
+
+} // namespace
+#endif // yaSSL_LOCK_HPP
diff --git a/extra/yassl/include/log.hpp b/extra/yassl/include/log.hpp
new file mode 100644
index 00000000000..5753bb4502d
--- /dev/null
+++ b/extra/yassl/include/log.hpp
@@ -0,0 +1,58 @@
+/* log.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL log interface
+ *
+ */
+
+#ifndef yaSSL_LOG_HPP
+#define yaSSL_LOG_HPP
+
+#include "socket_wrapper.hpp"
+
+#ifdef YASSL_LOG
+#include <cstdio>
+#endif
+
+namespace yaSSL {
+
+typedef unsigned int uint;
+
+
+// Debug logger
+class Log {
+#ifdef YASSL_LOG
+ FILE* log_;
+#endif
+public:
+ explicit Log(const char* str = "yaSSL.log");
+ ~Log();
+
+ void Trace(const char*);
+ void ShowTCP(socket_t, bool ended = false);
+ void ShowData(uint, bool sent = false);
+};
+
+
+} // naemspace
+
+#endif // yaSSL_LOG_HPP
diff --git a/extra/yassl/include/openssl/crypto.h b/extra/yassl/include/openssl/crypto.h
new file mode 100644
index 00000000000..4a0c1db0df1
--- /dev/null
+++ b/extra/yassl/include/openssl/crypto.h
@@ -0,0 +1,13 @@
+/* crypto.h for openSSL */
+
+#ifndef ysSSL_crypto_h__
+#define yaSSL_crypto_h__
+
+const char* SSLeay_version(int type);
+
+#define SSLEAY_VERSION 0x0900L
+#define SSLEAY_VERSION_NUMBER SSLEAY_VERSION
+
+
+#endif /* yaSSL_crypto_h__ */
+
diff --git a/extra/yassl/include/openssl/des.h b/extra/yassl/include/openssl/des.h
new file mode 100644
index 00000000000..67be7eecfb9
--- /dev/null
+++ b/extra/yassl/include/openssl/des.h
@@ -0,0 +1 @@
+/* des.h for openssl */
diff --git a/extra/yassl/include/openssl/err.h b/extra/yassl/include/openssl/err.h
new file mode 100644
index 00000000000..054d0940509
--- /dev/null
+++ b/extra/yassl/include/openssl/err.h
@@ -0,0 +1,8 @@
+/* err.h for openssl */
+
+#ifndef ysSSL_err_h__
+#define yaSSL_err_h__
+
+
+
+#endif /* yaSSL_err_h__ */
diff --git a/extra/yassl/include/openssl/lhash.h b/extra/yassl/include/openssl/lhash.h
new file mode 100644
index 00000000000..01f8535f869
--- /dev/null
+++ b/extra/yassl/include/openssl/lhash.h
@@ -0,0 +1,2 @@
+/* lhash.h for openSSL */
+
diff --git a/extra/yassl/include/openssl/md5.h b/extra/yassl/include/openssl/md5.h
new file mode 100644
index 00000000000..a1025b92782
--- /dev/null
+++ b/extra/yassl/include/openssl/md5.h
@@ -0,0 +1 @@
+/* md5.h for openssl */
diff --git a/extra/yassl/include/openssl/opensslv.h b/extra/yassl/include/openssl/opensslv.h
new file mode 100644
index 00000000000..d932130684f
--- /dev/null
+++ b/extra/yassl/include/openssl/opensslv.h
@@ -0,0 +1,12 @@
+/* opensslv.h compatibility */
+
+#ifndef yaSSL_opensslv_h__
+#define yaSSL_opensslv_h__
+
+
+/* api version compatibility */
+#define OPENSSL_VERSION_NUMBER 0x0090700f
+
+
+#endif /* yaSSLopensslv_h__ */
+
diff --git a/extra/yassl/include/openssl/rand.h b/extra/yassl/include/openssl/rand.h
new file mode 100644
index 00000000000..df9c9020346
--- /dev/null
+++ b/extra/yassl/include/openssl/rand.h
@@ -0,0 +1,2 @@
+/* rand.h for openSSL */
+
diff --git a/extra/yassl/include/openssl/rsa.h b/extra/yassl/include/openssl/rsa.h
new file mode 100644
index 00000000000..1ab9d13b89f
--- /dev/null
+++ b/extra/yassl/include/openssl/rsa.h
@@ -0,0 +1,10 @@
+/* rsa.h for openSSL */
+
+
+#ifndef ysSSL_rsa_h__
+#define yaSSL_rsa_h__
+
+enum { RSA_F4 = 1 };
+
+
+#endif /* yaSSL_rsa_h__ */
diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h
new file mode 100644
index 00000000000..361918846fc
--- /dev/null
+++ b/extra/yassl/include/openssl/ssl.h
@@ -0,0 +1,400 @@
+/* ssl.h
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* ssl.h defines openssl compatibility layer
+ *
+ */
+
+#ifndef ysSSL_openssl_h__
+#define yaSSL_openssl_h__
+
+#include <stdio.h> /* ERR_print fp */
+#include "rsa.h"
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+namespace yaSSL {
+extern "C" {
+#endif
+
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+ class SSL;
+ class SSL_SESSION;
+ class SSL_METHOD;
+ class SSL_CTX;
+ class SSL_CIPHER;
+
+ class RSA;
+
+ class X509;
+ class X509_NAME;
+#else
+ typedef struct SSL SSL;
+ typedef struct SSL_SESION SSL_SESSION;
+ typedef struct SSL_METHOD SSL_METHOD;
+ typedef struct SSL_CTX SSL_CTX;
+ typedef struct SSL_CIPHER SSL_CIPHER;
+
+ typedef struct RSA RSA;
+
+ typedef struct X509 X509;
+ typedef struct X509_NAME X509_NAME;
+#endif
+
+
+/* Big Number stuff, different file? */
+typedef struct BIGNUM BIGNUM;
+
+BIGNUM *BN_bin2bn(const unsigned char*, int, BIGNUM*);
+
+
+/* Diffie-Hellman stuff, different file? */
+/* mySQL deferences to set group parameters */
+typedef struct DH {
+ BIGNUM* p;
+ BIGNUM* g;
+} DH;
+
+DH* DH_new(void);
+void DH_free(DH*);
+
+/* RSA stuff */
+
+void RSA_free(RSA*);
+RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*);
+
+
+/* X509 stuff, different file? */
+
+typedef struct X509_STORE X509_STORE;
+typedef struct X509_LOOKUP X509_LOOKUP;
+typedef struct X509_OBJECT { char c; } X509_OBJECT;
+typedef struct X509_CRL X509_CRL;
+typedef struct X509_REVOKED X509_REVOKED;
+typedef struct X509_LOOKUP_METHOD X509_LOOKUP_METHOD;
+
+
+void X509_free(X509*);
+
+
+/* bio stuff */
+typedef struct BIO BIO;
+
+/* ASN stuff */
+typedef struct ASN1_TIME ASN1_TIME;
+
+
+
+/* because mySQL dereferences to use error and current_cert, even after calling
+ * get functions for local references */
+typedef struct X509_STORE_CTX {
+ int error;
+ int error_depth;
+ X509* current_cert;
+} X509_STORE_CTX;
+
+
+
+X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX*);
+int X509_STORE_CTX_get_error(X509_STORE_CTX*);
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX*);
+
+char* X509_NAME_oneline(X509_NAME*, char*, int);
+X509_NAME* X509_get_issuer_name(X509*);
+X509_NAME* X509_get_subject_name(X509*);
+const char* X509_verify_cert_error_string(long);
+
+int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long);
+int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long);
+X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void);
+X509_LOOKUP_METHOD* X509_LOOKUP_file(void);
+
+X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*);
+X509_STORE* X509_STORE_new(void);
+int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*,
+ X509_OBJECT*);
+
+
+
+
+enum { /* X509 Constants */
+ X509_V_OK = 0,
+ X509_V_ERR_CERT_CHAIN_TOO_LONG = 1,
+ X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2,
+ X509_V_ERR_CERT_NOT_YET_VALID = 3,
+ X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 4,
+ X509_V_ERR_CERT_HAS_EXPIRED = 5,
+ X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 6,
+ X509_FILETYPE_PEM = 7,
+ X509_LU_X509 = 8,
+ X509_LU_CRL = 9,
+ X509_V_ERR_CRL_SIGNATURE_FAILURE = 10,
+ X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 11,
+ X509_V_ERR_CRL_HAS_EXPIRED = 12,
+ X509_V_ERR_CERT_REVOKED = 13,
+
+};
+
+
+/* Error stuff, could move to yassl_error */
+unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *);
+void ERR_print_errors_fp(FILE*);
+char* ERR_error_string(unsigned long,char*);
+void ERR_remove_state(unsigned long);
+unsigned long ERR_get_error(void);
+unsigned long ERR_peek_error(void);
+int ERR_GET_REASON(int);
+
+
+enum { /* ERR Constants */
+ ERR_TXT_STRING = 1,
+ EVP_R_BAD_DECRYPT = 2,
+};
+
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD*);
+SSL* SSL_new(SSL_CTX*);
+int SSL_set_fd (SSL*, int);
+int SSL_connect(SSL*);
+int SSL_write(SSL*, const void*, int);
+int SSL_read(SSL*, void*, int);
+int SSL_accept(SSL*);
+void SSL_CTX_free(SSL_CTX*);
+void SSL_free(SSL*);
+int SSL_clear(SSL*);
+int SSL_shutdown(SSL*);
+
+void SSL_set_connect_state(SSL*);
+void SSL_set_accept_state(SSL*);
+int SSL_do_handshake(SSL*);
+
+const char* SSL_get_cipher(SSL*);
+const char* SSL_get_cipher_name(SSL*); /* uses SSL_get_cipher */
+char* SSL_get_shared_ciphers(SSL*, char*, int);
+const char* SSL_get_cipher_list(SSL*, int);
+const char* SSL_get_version(SSL*);
+const char* SSLeay_version(int);
+
+int SSL_get_error(SSL*, int);
+void SSL_load_error_strings(void);
+
+int SSL_set_session(SSL *ssl, SSL_SESSION *session);
+SSL_SESSION* SSL_get_session(SSL* ssl);
+long SSL_SESSION_set_timeout(SSL_SESSION*, long);
+X509* SSL_get_peer_certificate(SSL*);
+long SSL_get_verify_result(SSL*);
+
+
+typedef int (*VerifyCallback)(int, X509_STORE_CTX*);
+typedef int (*pem_password_cb)(char*, int, int, void*);
+
+void SSL_CTX_set_verify(SSL_CTX*, int, VerifyCallback verify_callback);
+int SSL_CTX_load_verify_locations(SSL_CTX*, const char*, const char*);
+int SSL_CTX_set_default_verify_paths(SSL_CTX*);
+int SSL_CTX_check_private_key(SSL_CTX*);
+int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
+ unsigned int);
+
+void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int));
+long SSL_CTX_set_options(SSL_CTX*, long);
+long SSL_CTX_set_session_cache_mode(SSL_CTX*, long);
+long SSL_CTX_set_timeout(SSL_CTX*, long);
+int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*);
+void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb);
+int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int);
+void SSL_CTX_set_info_callback(SSL_CTX*, void (*)());
+
+long SSL_CTX_sess_accept(SSL_CTX*);
+long SSL_CTX_sess_connect(SSL_CTX*);
+long SSL_CTX_sess_accept_good(SSL_CTX*);
+long SSL_CTX_sess_connect_good(SSL_CTX*);
+long SSL_CTX_sess_accept_renegotiate(SSL_CTX*);
+long SSL_CTX_sess_connect_renegotiate(SSL_CTX*);
+long SSL_CTX_sess_hits(SSL_CTX*);
+long SSL_CTX_sess_cb_hits(SSL_CTX*);
+long SSL_CTX_sess_cache_full(SSL_CTX*);
+long SSL_CTX_sess_misses(SSL_CTX*);
+long SSL_CTX_sess_timeouts(SSL_CTX*);
+long SSL_CTX_sess_number(SSL_CTX*);
+long SSL_CTX_sess_get_cache_size(SSL_CTX*);
+
+int SSL_CTX_get_verify_mode(SSL_CTX*);
+int SSL_get_verify_mode(SSL*);
+int SSL_CTX_get_verify_depth(SSL_CTX*);
+int SSL_get_verify_depth(SSL*);
+
+long SSL_get_default_timeout(SSL*);
+long SSL_CTX_get_session_cache_mode(SSL_CTX*);
+int SSL_session_reused(SSL*);
+
+int SSL_set_rfd(SSL*, int);
+int SSL_set_wfd(SSL*, int);
+void SSL_set_shutdown(SSL*, int);
+
+int SSL_want_read(SSL*);
+int SSL_want_write(SSL*);
+
+int SSL_pending(SSL*);
+
+
+enum { /* ssl Constants */
+ SSL_BAD_FILETYPE = -5,
+ SSL_BAD_FILE = -4,
+ SSL_NOT_IMPLEMENTED = -3,
+ SSL_UNKNOWN = -2,
+ SSL_FATAL_ERROR = -1,
+ SSL_NORMAL_SHUTDOWN = 0,
+ SSL_ERROR_NONE = 0, // for most functions
+ SSL_FAILURE = 0, // for some functions
+ SSL_SUCCESS = 1,
+
+ SSL_FILETYPE_ASN1 = 10,
+ SSL_FILETYPE_PEM = 11,
+ SSL_FILETYPE_DEFAULT = 10, /* ASN1 */
+
+ SSL_VERIFY_NONE = 0,
+ SSL_VERIFY_PEER = 1,
+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2,
+ SSL_VERIFY_CLIENT_ONCE = 4,
+
+ SSL_SESS_CACHE_OFF = 30,
+ SSL_SESS_CACHE_CLIENT = 31,
+ SSL_SESS_CACHE_SERVER = 32,
+ SSL_SESS_CACHE_BOTH = 33,
+ SSL_SESS_CACHE_NO_AUTO_CLEAR = 34,
+ SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35,
+
+ SSL_OP_MICROSOFT_SESS_ID_BUG = 50,
+ SSL_OP_NETSCAPE_CHALLENGE_BUG = 51,
+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 52,
+ SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 53,
+ SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 54,
+ SSL_OP_MSIE_SSLV2_RSA_PADDING = 55,
+ SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 56,
+ SSL_OP_TLS_D5_BUG = 57,
+ SSL_OP_TLS_BLOCK_PADDING_BUG = 58,
+ SSL_OP_TLS_ROLLBACK_BUG = 59,
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 60,
+ SSL_OP_ALL = 61,
+ SSL_OP_SINGLE_DH_USE = 62,
+ SSL_OP_EPHEMERAL_RSA = 63,
+ SSL_OP_NO_SSLv2 = 64,
+ SSL_OP_NO_SSLv3 = 65,
+ SSL_OP_NO_TLSv1 = 66,
+ SSL_OP_PKCS1_CHECK_1 = 67,
+ SSL_OP_PKCS1_CHECK_2 = 68,
+ SSL_OP_NETSCAPE_CA_DN_BUG = 69,
+ SSL_OP_NON_EXPORT_FIRST = 70,
+ SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 71,
+
+ SSL_ERROR_WANT_READ = 80,
+ SSL_ERROR_WANT_WRITE = 81,
+ SSL_ERROR_SYSCALL = 82,
+ SSL_ERROR_WANT_X509_LOOKUP = 83,
+ SSL_ERROR_ZERO_RETURN = 84,
+ SSL_ERROR_SSL = 85,
+
+ SSL_SENT_SHUTDOWN = 90,
+ SSL_RECEIVED_SHUTDOWN = 91,
+ SSL_CB_LOOP = 92,
+ SSL_ST_CONNECT = 93,
+ SSL_ST_ACCEPT = 94,
+ SSL_CB_ALERT = 95,
+ SSL_CB_READ = 96,
+ SSL_CB_HANDSHAKE_DONE = 97,
+
+};
+
+
+SSL_METHOD *SSLv3_method(void);
+SSL_METHOD *SSLv3_server_method(void);
+SSL_METHOD *SSLv3_client_method(void);
+SSL_METHOD *TLSv1_server_method(void);
+SSL_METHOD *TLSv1_client_method(void);
+SSL_METHOD *SSLv23_server_method(void);
+
+int SSL_CTX_use_certificate_file(SSL_CTX*, const char*, int);
+int SSL_CTX_use_PrivateKey_file(SSL_CTX*, const char*, int);
+int SSL_CTX_set_cipher_list(SSL_CTX*, const char*);
+
+long SSL_CTX_sess_set_cache_size(SSL_CTX*, long);
+long SSL_CTX_set_tmp_dh(SSL_CTX*, DH*);
+
+void OpenSSL_add_all_algorithms(void);
+void SSLeay_add_ssl_algorithms(void);
+
+
+SSL_CIPHER* SSL_get_current_cipher(SSL*);
+char* SSL_CIPHER_description(SSL_CIPHER*, char*, int);
+
+
+char* SSL_alert_type_string_long(int);
+char* SSL_alert_desc_string_long(int);
+char* SSL_state_string_long(SSL*);
+
+
+/* EVP stuff, des and md5, different file? */
+typedef struct Digest Digest;
+typedef Digest EVP_MD;
+
+typedef struct BulkCipher BulkCipher;
+typedef BulkCipher EVP_CIPHER;
+
+typedef struct EVP_PKEY EVP_PKEY;
+
+typedef unsigned char DES_cblock[8];
+typedef const DES_cblock const_DES_cblock;
+typedef DES_cblock DES_key_schedule;
+
+
+const EVP_MD* EVP_md5(void);
+const EVP_CIPHER* EVP_des_ede3_cbc(void);
+
+typedef unsigned char opaque;
+
+int EVP_BytesToKey(const EVP_CIPHER*, const EVP_MD*, const opaque*,
+ const opaque*, int, int, opaque*, opaque*);
+
+void DES_set_key_unchecked(const_DES_cblock*, DES_key_schedule*);
+void DES_ede3_cbc_encrypt(const opaque*, opaque*, long, DES_key_schedule*,
+ DES_key_schedule*, DES_key_schedule*, DES_cblock*, int);
+
+
+/* RAND stuff */
+void RAND_screen(void);
+const char* RAND_file_name(char*, size_t);
+int RAND_write_file(const char*);
+int RAND_load_file(const char*, long);
+
+
+#define SSL_DEFAULT_CIPHER_LIST "" /* default all */
+
+
+
+
+#if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
+} /* namespace */
+} /* extern "C" */
+#endif
+
+
+#endif /* yaSSL_openssl_h__ */
diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp
new file mode 100644
index 00000000000..dddbd65e220
--- /dev/null
+++ b/extra/yassl/include/socket_wrapper.hpp
@@ -0,0 +1,95 @@
+/* socket_wrapper.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The socket wrapper header defines a Socket class that hides the differences
+ * between Berkely style sockets and Windows sockets, allowing transparent TCP
+ * access.
+ */
+
+
+#ifndef yaSSL_SOCKET_WRAPPER_HPP
+#define yaSSL_SOCKET_WRAPPER_HPP
+
+#include <cassert>
+
+#ifdef WIN32
+ #include <winsock2.h>
+#else
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+#endif
+
+
+namespace yaSSL {
+
+typedef unsigned int uint;
+
+#ifdef WIN32
+ typedef SOCKET socket_t;
+#else
+ typedef int socket_t;
+ const socket_t INVALID_SOCKET = -1;
+ const int SD_RECEIVE = 0;
+ const int SD_SEND = 1;
+ const int SD_BOTH = 2;
+ const int SOCKET_ERROR = -1;
+#endif
+
+
+
+typedef unsigned char byte;
+
+
+// Wraps Windows Sockets and BSD Sockets
+class Socket {
+ socket_t socket_; // underlying socket descriptor
+public:
+ explicit Socket(socket_t s = INVALID_SOCKET);
+ virtual ~Socket();
+
+ void set_fd(socket_t s);
+ uint get_ready() const;
+ socket_t get_fd() const;
+
+ uint send(const byte* buf, unsigned int len, int flags = 0) const;
+ uint receive(byte* buf, unsigned int len, int flags = 0) const;
+
+ void wait() const;
+
+ void closeSocket();
+ void shutDown(int how = SD_SEND);
+
+ static int get_lastError();
+ static void set_lastError(int error);
+private:
+ Socket(const Socket&); // hide copy
+ Socket& operator= (const Socket&); // and assign
+};
+
+
+} // naemspace
+
+#endif // yaSSL_SOCKET_WRAPPER_HPP
diff --git a/extra/yassl/include/timer.hpp b/extra/yassl/include/timer.hpp
new file mode 100644
index 00000000000..3025b7a0bd9
--- /dev/null
+++ b/extra/yassl/include/timer.hpp
@@ -0,0 +1,43 @@
+/* timer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* timer.hpp provides a high res and low res timers
+ *
+*/
+
+
+#ifndef yaSSL_TIMER_HPP
+#define yaSSL_TIMER_HPP
+
+namespace yaSSL {
+
+typedef double timer_d;
+typedef unsigned int uint;
+
+
+
+timer_d timer();
+uint lowResTimer();
+
+
+
+} // namespace
+#endif // yaSSL_TIMER_HPP
diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp
new file mode 100644
index 00000000000..4165eb24b66
--- /dev/null
+++ b/extra/yassl/include/yassl_error.hpp
@@ -0,0 +1,78 @@
+/* yassl_error.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL error header defines error codes and an exception class
+ */
+
+#ifndef yaSSL_ERROR_HPP
+#define yaSSL_ERROR_HPP
+
+#include "stdexcept.hpp"
+
+
+namespace yaSSL {
+
+
+enum YasslError {
+ no_error = 0,
+
+ // 10 - 47 from AlertDescription, 0 also close_notify
+
+ range_error = 101,
+ realloc_error = 102,
+ factory_error = 103,
+ unknown_cipher = 104,
+ prefix_error = 105,
+ record_layer = 106,
+ handshake_layer = 107,
+ out_of_order = 108,
+ bad_input = 109,
+ match_error = 110,
+ no_key_file = 111,
+ verify_error = 112,
+ send_error = 113,
+ receive_error = 114,
+ certificate_error = 115,
+
+ // 1000+ from TaoCrypt error.hpp
+
+};
+
+
+enum Library { yaSSL_Lib = 0, CryptoLib, SocketLib };
+
+// Base class for all yaSSL exceptions
+class Error : public mySTL::runtime_error {
+ YasslError error_;
+ Library lib_;
+public:
+ explicit Error(const char* s = "", YasslError e = no_error,
+ Library l = yaSSL_Lib);
+
+ YasslError get_number() const;
+ Library get_lib() const;
+};
+
+
+} // naemspace
+
+#endif // yaSSL_ERROR_HPP
diff --git a/extra/yassl/include/yassl_imp.hpp b/extra/yassl/include/yassl_imp.hpp
new file mode 100644
index 00000000000..52108b6aa1c
--- /dev/null
+++ b/extra/yassl/include/yassl_imp.hpp
@@ -0,0 +1,742 @@
+/* yassl_imp.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* yaSSL implementation header defines all strucutres from the SSL.v3
+ * specification "draft-freier-ssl-version3-02.txt"
+ * all page citations refer to this document unless otherwise noted.
+ */
+
+
+#ifndef yaSSL_IMP_HPP
+#define yaSSL_IMP_HPP
+
+#ifdef _MSC_VER
+ // disable truncated debug symbols
+ #pragma warning(disable:4786)
+#endif
+
+#include "yassl_types.hpp"
+#include "factory.hpp"
+#include "list.hpp" // mySTL::list
+
+
+namespace yaSSL {
+
+
+class SSL; // forward decls
+class input_buffer;
+class output_buffer;
+
+
+struct ProtocolVersion {
+ uint8 major_;
+ uint8 minor_; // major and minor SSL/TLS version numbers
+
+ ProtocolVersion(uint8 maj = 3, uint8 min = 0);
+};
+
+
+// Record Layer Header for PlainText, Compressed, and CipherText
+struct RecordLayerHeader {
+ ContentType type_;
+ ProtocolVersion version_;
+ uint16 length_; // should not exceed 2^14
+};
+
+
+// base for all messages
+struct Message {
+ virtual input_buffer& set(input_buffer&) =0;
+ virtual output_buffer& get(output_buffer&) const =0;
+
+ virtual void Process(input_buffer&, SSL&) =0;
+ virtual ContentType get_type() const =0;
+ virtual uint16 get_length() const =0;
+
+ virtual ~Message() {}
+};
+
+
+class ChangeCipherSpec : public Message {
+ CipherChoice type_;
+public:
+ ChangeCipherSpec();
+
+ friend input_buffer& operator>>(input_buffer&, ChangeCipherSpec&);
+ friend output_buffer& operator<<(output_buffer&, const ChangeCipherSpec&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ void Process(input_buffer&, SSL&);
+private:
+ ChangeCipherSpec(const ChangeCipherSpec&); // hide copy
+ ChangeCipherSpec& operator=(const ChangeCipherSpec&); // and assign
+};
+
+
+
+class Alert : public Message {
+ AlertLevel level_;
+ AlertDescription description_;
+public:
+ Alert() {}
+ Alert(AlertLevel al, AlertDescription ad);
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ void Process(input_buffer&, SSL&);
+
+ friend input_buffer& operator>>(input_buffer&, Alert&);
+ friend output_buffer& operator<<(output_buffer&, const Alert&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+private:
+ Alert(const Alert&); // hide copy
+ Alert& operator=(const Alert&); // and assign
+};
+
+
+class Data : public Message {
+ uint16 length_;
+ opaque* buffer_; // read buffer used by fillData input
+ const opaque* write_buffer_; // write buffer used by output operator
+public:
+ Data();
+ Data(uint16 len, opaque* b);
+ Data(uint16 len, const opaque* w);
+
+ friend output_buffer& operator<<(output_buffer&, const Data&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ const opaque* get_buffer() const;
+ void set_length(uint16 l);
+ opaque* set_buffer();
+ void Process(input_buffer&, SSL&);
+private:
+ Data(const Data&); // hide copy
+ Data& operator=(const Data&); // and assign
+};
+
+
+uint32 c24to32(const uint24); // forward form internal header
+void c32to24(uint32, uint24&);
+
+
+// HandShake header, same for each message type from page 20/21
+class HandShakeHeader : public Message {
+ HandShakeType type_;
+ uint24 length_; // length of message
+public:
+ HandShakeHeader() {}
+
+ ContentType get_type() const;
+ uint16 get_length() const;
+ HandShakeType get_handshakeType() const;
+ void Process(input_buffer&, SSL&);
+
+ void set_type(HandShakeType hst);
+ void set_length(uint32 u32);
+
+ friend input_buffer& operator>>(input_buffer&, HandShakeHeader&);
+ friend output_buffer& operator<<(output_buffer&, const HandShakeHeader&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+private:
+ HandShakeHeader(const HandShakeHeader&); // hide copy
+ HandShakeHeader& operator=(const HandShakeHeader&); // and assign
+};
+
+
+// Base Class for all handshake messages
+class HandShakeBase {
+ int length_;
+public:
+ int get_length() const;
+ void set_length(int);
+
+ // for building buffer's type field
+ virtual HandShakeType get_type() const =0;
+
+ // handles dispactch of proper >>
+ virtual input_buffer& set(input_buffer& in) =0;
+ virtual output_buffer& get(output_buffer& out) const =0;
+
+ virtual void Process(input_buffer&, SSL&) =0;
+
+ virtual ~HandShakeBase() {}
+};
+
+
+struct HelloRequest : public HandShakeBase {
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer&, SSL&);
+
+ HandShakeType get_type() const;
+};
+
+
+// The Client's Hello Message from page 23
+class ClientHello : public HandShakeBase {
+ ProtocolVersion client_version_;
+ Random random_;
+ uint8 id_len_; // session id length
+ opaque session_id_[ID_LEN];
+ uint16 suite_len_; // cipher suite length
+ opaque cipher_suites_[MAX_SUITE_SZ];
+ uint8 comp_len_; // compression length
+ CompressionMethod compression_methods_;
+public:
+ friend input_buffer& operator>>(input_buffer&, ClientHello&);
+ friend output_buffer& operator<<(output_buffer&, const ClientHello&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+
+ const opaque* get_random() const;
+ friend void buildClientHello(SSL&, ClientHello&, CompressionMethod);
+ friend void ProcessOldClientHello(input_buffer& input, SSL& ssl);
+
+ ClientHello();
+ explicit ClientHello(ProtocolVersion pv);
+private:
+ ClientHello(const ClientHello&); // hide copy
+ ClientHello& operator=(const ClientHello&); // and assign
+};
+
+
+
+// The Server's Hello Message from page 24
+class ServerHello : public HandShakeBase {
+ ProtocolVersion server_version_;
+ Random random_;
+ uint8 id_len_; // session id length
+ opaque session_id_[ID_LEN];
+ opaque cipher_suite_[SUITE_LEN];
+ CompressionMethod compression_method_;
+public:
+ explicit ServerHello(ProtocolVersion pv);
+ ServerHello();
+
+ friend input_buffer& operator>>(input_buffer&, ServerHello&);
+ friend output_buffer& operator<<(output_buffer&, const ServerHello&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+
+ const opaque* get_random() const;
+ friend void buildServerHello(SSL&, ServerHello&);
+private:
+ ServerHello(const ServerHello&); // hide copy
+ ServerHello& operator=(const ServerHello&); // and assign
+};
+
+
+class x509;
+
+// Certificate could be a chain
+class Certificate : public HandShakeBase {
+ const x509* cert_;
+public:
+ Certificate();
+ explicit Certificate(const x509* cert);
+ friend output_buffer& operator<<(output_buffer&, const Certificate&);
+
+ const opaque* get_buffer() const;
+
+ // Process handles input, needs SSL
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+private:
+ Certificate(const Certificate&); // hide copy
+ Certificate& operator=(const Certificate&); // and assign
+};
+
+
+
+// RSA Public Key
+struct ServerRSAParams {
+ opaque* rsa_modulus_;
+ opaque* rsa_exponent_;
+};
+
+
+// Ephemeral Diffie-Hellman Parameters
+class ServerDHParams {
+ int pSz_;
+ int gSz_;
+ int pubSz_;
+ opaque* p_;
+ opaque* g_;
+ opaque* Ys_;
+public:
+ ServerDHParams();
+ ~ServerDHParams();
+
+ int get_pSize() const;
+ int get_gSize() const;
+ int get_pubSize() const;
+
+ const opaque* get_p() const;
+ const opaque* get_g() const;
+ const opaque* get_pub() const;
+
+ opaque* alloc_p(int sz);
+ opaque* alloc_g(int sz);
+ opaque* alloc_pub(int sz);
+private:
+ ServerDHParams(const ServerDHParams&); // hide copy
+ ServerDHParams& operator=(const ServerDHParams&); // and assign
+};
+
+
+struct ServerKeyBase {
+ virtual ~ServerKeyBase() {}
+ virtual void build(SSL&) {}
+ virtual void read(SSL&, input_buffer&) {}
+ virtual int get_length() const;
+ virtual opaque* get_serverKey() const;
+};
+
+
+// Server random number for FORTEZZA KEA
+struct Fortezza_Server : public ServerKeyBase {
+ opaque r_s_[FORTEZZA_MAX];
+};
+
+
+struct SignatureBase {
+ virtual ~SignatureBase() {}
+};
+
+struct anonymous_sa : public SignatureBase {};
+
+
+struct Hashes {
+ uint8 md5_[MD5_LEN];
+ uint8 sha_[SHA_LEN];
+};
+
+
+struct rsa_sa : public SignatureBase {
+ Hashes hashes_;
+};
+
+
+struct dsa_sa : public SignatureBase {
+ uint8 sha_[SHA_LEN];
+};
+
+
+// Server's Diffie-Hellman exchange
+class DH_Server : public ServerKeyBase {
+ ServerDHParams parms_;
+ opaque* signature_;
+
+ int length_; // total length of message
+ opaque* keyMessage_; // total exchange message
+public:
+ DH_Server();
+ ~DH_Server();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_serverKey() const;
+private:
+ DH_Server(const DH_Server&); // hide copy
+ DH_Server& operator=(const DH_Server&); // and assign
+};
+
+
+// Server's RSA exchange
+struct RSA_Server : public ServerKeyBase {
+ ServerRSAParams params_;
+ opaque* signature_; // signed rsa_sa hashes
+};
+
+
+class ServerKeyExchange : public HandShakeBase {
+ ServerKeyBase* server_key_;
+public:
+ explicit ServerKeyExchange(SSL&);
+ ServerKeyExchange();
+ ~ServerKeyExchange();
+
+ void createKey(SSL&);
+ void build(SSL& ssl);
+
+ const opaque* getKey() const;
+ int getKeyLength() const;
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend output_buffer& operator<<(output_buffer&, const ServerKeyExchange&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+private:
+ ServerKeyExchange(const ServerKeyExchange&); // hide copy
+ ServerKeyExchange& operator=(const ServerKeyExchange&); // and assign
+};
+
+
+
+class CertificateRequest : public HandShakeBase {
+ ClientCertificateType certificate_types_[CERT_TYPES];
+ int typeTotal_;
+ mySTL::list<DistinguishedName> certificate_authorities_;
+public:
+ CertificateRequest();
+ ~CertificateRequest();
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend input_buffer& operator>>(input_buffer&, CertificateRequest&);
+ friend output_buffer& operator<<(output_buffer&,
+ const CertificateRequest&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+
+ void Build();
+private:
+ CertificateRequest(const CertificateRequest&); // hide copy
+ CertificateRequest& operator=(const CertificateRequest&); // and assign
+};
+
+
+struct ServerHelloDone : public HandShakeBase {
+ ServerHelloDone();
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer& input, SSL& ssl);
+
+ HandShakeType get_type() const;
+};
+
+
+struct PreMasterSecret {
+ opaque random_[SECRET_LEN]; // first two bytes Protocol Version
+};
+
+
+struct ClientKeyBase {
+ virtual ~ClientKeyBase() {}
+ virtual void build(SSL&) {}
+ virtual void read(SSL&, input_buffer&) {}
+ virtual int get_length() const;
+ virtual opaque* get_clientKey() const;
+};
+
+
+class EncryptedPreMasterSecret : public ClientKeyBase {
+ opaque* secret_;
+ int length_;
+public:
+ EncryptedPreMasterSecret();
+ ~EncryptedPreMasterSecret();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_clientKey() const;
+ void alloc(int sz);
+private:
+ // hide copy and assign
+ EncryptedPreMasterSecret(const EncryptedPreMasterSecret&);
+ EncryptedPreMasterSecret& operator=(const EncryptedPreMasterSecret&);
+};
+
+
+// Fortezza Key Parameters from page 29
+// hard code lengths cause only used here
+struct FortezzaKeys : public ClientKeyBase {
+ opaque y_c_ [128]; // client's Yc, public value
+ opaque r_c_ [128]; // client's Rc
+ opaque y_signature_ [40]; // DSS signed public key
+ opaque wrapped_client_write_key_ [12]; // wrapped by the TEK
+ opaque wrapped_server_write_key_ [12]; // wrapped by the TEK
+ opaque client_write_iv_ [24];
+ opaque server_write_iv_ [24];
+ opaque master_secret_iv_ [24]; // IV used to encrypt preMaster
+ opaque encrypted_preMasterSecret_[48]; // random & crypted by the TEK
+};
+
+
+
+// Diffie-Hellman public key from page 40/41
+class ClientDiffieHellmanPublic : public ClientKeyBase {
+ PublicValueEncoding public_value_encoding_;
+ int length_; // includes two byte length for message
+ opaque* Yc_; // length + Yc_
+ // dh_Yc only if explicit, otherwise sent in certificate
+ enum { KEY_OFFSET = 2 };
+public:
+ ClientDiffieHellmanPublic();
+ ~ClientDiffieHellmanPublic();
+
+ void build(SSL&);
+ void read(SSL&, input_buffer&);
+ int get_length() const;
+ opaque* get_clientKey() const;
+ void alloc(int sz, bool offset = false);
+private:
+ // hide copy and assign
+ ClientDiffieHellmanPublic(const ClientDiffieHellmanPublic&);
+ ClientDiffieHellmanPublic& operator=(const ClientDiffieHellmanPublic&);
+};
+
+
+class ClientKeyExchange : public HandShakeBase {
+ ClientKeyBase* client_key_;
+public:
+ explicit ClientKeyExchange(SSL& ssl);
+ ClientKeyExchange();
+ ~ClientKeyExchange();
+
+ void createKey(SSL&);
+ void build(SSL& ssl);
+
+ const opaque* getKey() const;
+ int getKeyLength() const;
+
+ friend output_buffer& operator<<(output_buffer&, const ClientKeyExchange&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ HandShakeType get_type() const;
+ void Process(input_buffer&, SSL&);
+private:
+ ClientKeyExchange(const ClientKeyExchange&); // hide copy
+ ClientKeyExchange& operator=(const ClientKeyExchange&); // and assign
+};
+
+
+class CertificateVerify : public HandShakeBase {
+ Hashes hashes_;
+ byte* signature_; // owns
+public:
+ CertificateVerify();
+ ~CertificateVerify();
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ friend input_buffer& operator>>(input_buffer&, CertificateVerify&);
+ friend output_buffer& operator<<(output_buffer&, const CertificateVerify&);
+
+ void Process(input_buffer&, SSL&);
+ HandShakeType get_type() const;
+
+ void Build(SSL&);
+private:
+ CertificateVerify(const CertificateVerify&); // hide copy
+ CertificateVerify& operator=(const CertificateVerify&); // and assign
+};
+
+
+class Finished : public HandShakeBase {
+ Hashes hashes_;
+public:
+ Finished();
+
+ uint8* set_md5();
+ uint8* set_sha();
+
+ friend input_buffer& operator>>(input_buffer&, Finished&);
+ friend output_buffer& operator<<(output_buffer&, const Finished&);
+
+ input_buffer& set(input_buffer& in);
+ output_buffer& get(output_buffer& out) const;
+
+ void Process(input_buffer&, SSL&);
+
+ HandShakeType get_type() const;
+private:
+ Finished(const Finished&); // hide copy
+ Finished& operator=(const Finished&); // and assign
+};
+
+
+class RandomPool; // forward for connection
+
+
+// SSL Connection defined on page 11
+struct Connection {
+ opaque *pre_master_secret_;
+ opaque master_secret_[SECRET_LEN];
+ opaque client_random_[RAN_LEN];
+ opaque server_random_[RAN_LEN];
+ opaque sessionID_[ID_LEN];
+ opaque client_write_MAC_secret_[SHA_LEN]; // sha is max size
+ opaque server_write_MAC_secret_[SHA_LEN];
+ opaque client_write_key_[AES_256_KEY_SZ]; // aes 256bit is max sz
+ opaque server_write_key_[AES_256_KEY_SZ];
+ opaque client_write_IV_[AES_IV_SZ]; // aes is max size
+ opaque server_write_IV_[AES_IV_SZ];
+ uint32 sequence_number_;
+ uint32 peer_sequence_number_;
+ uint32 pre_secret_len_; // pre master length
+ bool send_server_key_; // server key exchange?
+ bool master_clean_; // master secret clean?
+ bool TLS_; // TLSv1 or greater
+ ProtocolVersion version_;
+ RandomPool& random_;
+
+ Connection(ProtocolVersion v, RandomPool& ran);
+ ~Connection();
+
+ void AllocPreSecret(uint sz);
+ void CleanPreMaster();
+ void CleanMaster();
+ void TurnOffTLS();
+private:
+ Connection(const Connection&); // hide copy
+ Connection& operator=(const Connection&); // and assign
+};
+
+
+struct Ciphers; // forward
+
+
+// TLSv1 Security Spec, defined on page 56 of RFC 2246
+struct Parameters {
+ ConnectionEnd entity_;
+ BulkCipherAlgorithm bulk_cipher_algorithm_;
+ CipherType cipher_type_;
+ uint8 key_size_;
+ uint8 iv_size_;
+ IsExportable is_exportable_;
+ MACAlgorithm mac_algorithm_;
+ uint8 hash_size_;
+ CompressionMethod compression_algorithm_;
+ KeyExchangeAlgorithm kea_; // yassl additions
+ SignatureAlgorithm sig_algo_; // signature auth type
+ SignatureAlgorithm verify_algo_; // cert verify auth type
+ bool pending_;
+ bool resumable_; // new conns by session
+ uint16 encrypt_size_; // current msg encrypt sz
+ Cipher suite_[SUITE_LEN]; // choosen suite
+ uint8 suites_size_;
+ Cipher suites_[MAX_SUITE_SZ];
+ char cipher_name_[MAX_SUITE_NAME];
+ char cipher_list_[MAX_CIPHER_LIST];
+
+ Parameters(ConnectionEnd, const Ciphers&, ProtocolVersion);
+
+ void SetSuites(ProtocolVersion pv);
+ void SetCipherNames();
+private:
+ Parameters(const Parameters&); // hide copy
+ Parameters& operator=(const Parameters&); // and assing
+};
+
+
+input_buffer& operator>>(input_buffer&, RecordLayerHeader&);
+output_buffer& operator<<(output_buffer&, const RecordLayerHeader&);
+
+input_buffer& operator>>(input_buffer&, Message&);
+output_buffer& operator<<(output_buffer&, const Message&);
+
+input_buffer& operator>>(input_buffer&, HandShakeBase&);
+output_buffer& operator<<(output_buffer&, const HandShakeBase&);
+
+
+// Message Factory definition
+// uses the ContentType enumeration for unique id
+typedef Factory<Message> MessageFactory;
+void InitMessageFactory(MessageFactory&); // registers derived classes
+
+// HandShake Factory definition
+// uses the HandShakeType enumeration for unique id
+typedef Factory<HandShakeBase> HandShakeFactory;
+void InitHandShakeFactory(HandShakeFactory&); // registers derived classes
+
+// ServerKey Factory definition
+// uses KeyExchangeAlgorithm enumeration for unique id
+typedef Factory<ServerKeyBase> ServerKeyFactory;
+void InitServerKeyFactory(ServerKeyFactory&);
+
+// ClientKey Factory definition
+// uses KeyExchangeAlgorithm enumeration for unique id
+typedef Factory<ClientKeyBase> ClientKeyFactory;
+void InitClientKeyFactory(ClientKeyFactory&);
+
+
+// Message Creators
+Message* CreateHandShake();
+Message* CreateCipherSpec();
+Message* CreateAlert();
+Message* CreateData();
+
+
+// HandShake Creators
+HandShakeBase* CreateCertificate();
+HandShakeBase* CreateHelloRequest();
+HandShakeBase* CreateClientHello();
+HandShakeBase* CreateServerHello();
+HandShakeBase* CreateServerKeyExchange();
+HandShakeBase* CreateCertificateRequest();
+HandShakeBase* CreateServerHelloDone();
+HandShakeBase* CreateClientKeyExchange();
+HandShakeBase* CreateCertificateVerify();
+HandShakeBase* CreateFinished();
+
+
+// ServerKey Exchange Creators
+ServerKeyBase* CreateRSAServerKEA();
+ServerKeyBase* CreateDHServerKEA();
+ServerKeyBase* CreateFortezzaServerKEA();
+
+// ClientKey Exchange Creators
+ClientKeyBase* CreateRSAClient();
+ClientKeyBase* CreateDHClient();
+ClientKeyBase* CreateFortezzaClient();
+
+
+
+} // naemspace
+
+#endif // yaSSL_IMP_HPP
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
new file mode 100644
index 00000000000..fa13baf1ac2
--- /dev/null
+++ b/extra/yassl/include/yassl_int.hpp
@@ -0,0 +1,538 @@
+/* yassl_int.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL internal header defines SSL supporting types not specified in the
+ * draft along with type conversion functions and openssl compatibility
+ */
+
+
+#ifndef yaSSL_INT_HPP
+#define yaSSL_INT_HPP
+
+#include "yassl_imp.hpp"
+#include "crypto_wrapper.hpp"
+#include "cert_wrapper.hpp"
+#include "lock.hpp"
+#include "log.hpp"
+
+
+namespace yaSSL {
+
+
+// State Machine for Record Layer Protocol
+enum RecordLayerState {
+ recordNotReady = 0, // fatal error, no more processing
+ recordReady
+};
+
+
+// State Machine for HandShake Protocol
+enum HandShakeState {
+ handShakeNotReady = 0, // fatal error, no more processing
+ preHandshake, // initial state
+ inHandshake, // handshake started
+ handShakeReady // handshake done
+};
+
+
+// client input HandShake state, use if HandShakeState == inHandShake
+enum ClientState {
+ serverNull = 0,
+ serverHelloComplete,
+ serverCertComplete,
+ serverKeyExchangeComplete,
+ serverHelloDoneComplete,
+ serverFinishedComplete
+};
+
+
+// server input HandShake state, use if HandShakeState == inHandShake
+enum ServerState {
+ clientNull = 0,
+ clientHelloComplete,
+ clientKeyExchangeComplete,
+ clientFinishedComplete
+};
+
+
+// combines all states
+class States {
+ enum {MAX_ERROR_SZ = 80 };
+
+ RecordLayerState recordLayer_;
+ HandShakeState handshakeLayer_;
+ ClientState clientState_;
+ ServerState serverState_;
+ char errorString_[MAX_ERROR_SZ];
+ YasslError what_;
+public:
+ States();
+
+ const RecordLayerState& getRecord() const;
+ const HandShakeState& getHandShake() const;
+ const ClientState& getClient() const;
+ const ServerState& getServer() const;
+ const char* getString() const;
+ YasslError What() const;
+
+ RecordLayerState& useRecord();
+ HandShakeState& useHandShake();
+ ClientState& useClient();
+ ServerState& useServer();
+ char* useString();
+ void SetError(YasslError);
+private:
+ States(const States&); // hide copy
+ States& operator=(const States&); // and assign
+};
+
+
+// holds all factories
+class sslFactory {
+ MessageFactory messageFactory_; // creates new messages by type
+ HandShakeFactory handShakeFactory_; // creates new handshake types
+ ServerKeyFactory serverKeyFactory_; // creates new server key types
+ ClientKeyFactory clientKeyFactory_; // creates new client key types
+
+ sslFactory(); // only GetSSL_Factory creates
+public:
+ const MessageFactory& getMessage() const;
+ const HandShakeFactory& getHandShake() const;
+ const ServerKeyFactory& getServerKey() const;
+ const ClientKeyFactory& getClientKey() const;
+
+ friend sslFactory& GetSSL_Factory(); // singleton creator
+private:
+ sslFactory(const sslFactory&); // hide copy
+ sslFactory& operator=(const sslFactory&); // and assign
+};
+
+
+// openSSL X509 names
+class X509_NAME {
+ char* name_;
+public:
+ X509_NAME(const char*, size_t sz);
+ ~X509_NAME();
+
+ char* GetName();
+private:
+ X509_NAME(const X509_NAME&); // hide copy
+ X509_NAME& operator=(const X509_NAME&); // and assign
+};
+
+
+// openSSL X509
+class X509 {
+ X509_NAME issuer_;
+ X509_NAME subject_;
+public:
+ X509(const char* i, size_t, const char* s, size_t);
+ ~X509() {}
+
+ X509_NAME* GetIssuer();
+ X509_NAME* GetSubject();
+private:
+ X509(const X509&); // hide copy
+ X509& operator=(const X509&); // and assign
+};
+
+
+// openSSL bignum
+struct BIGNUM {
+ Integer int_;
+ void assign(const byte* b, uint s) { int_.assign(b,s); }
+};
+
+
+// openSSL session
+class SSL_SESSION {
+ opaque sessionID_[ID_LEN];
+ opaque master_secret_[SECRET_LEN];
+ Cipher suite_[SUITE_LEN];
+ uint bornOn_; // create time in seconds
+ uint timeout_; // timeout in seconds
+ RandomPool& random_; // will clean master secret
+public:
+ explicit SSL_SESSION(RandomPool&);
+ SSL_SESSION(const SSL&, RandomPool&);
+ ~SSL_SESSION();
+
+ const opaque* GetID() const;
+ const opaque* GetSecret() const;
+ const Cipher* GetSuite() const;
+ uint GetBornOn() const;
+ uint GetTimeOut() const;
+ void SetTimeOut(uint);
+
+ SSL_SESSION& operator=(const SSL_SESSION&); // allow assign for resumption
+private:
+ SSL_SESSION(const SSL_SESSION&); // hide copy
+};
+
+
+// holds all sessions
+class Sessions {
+ mySTL::list<SSL_SESSION*> list_;
+ RandomPool random_; // for session cleaning
+ Mutex mutex_; // no-op for single threaded
+
+ Sessions() {} // only GetSessions can create
+public:
+ SSL_SESSION* lookup(const opaque*, SSL_SESSION* copy = 0);
+ void add(const SSL&);
+ void remove(const opaque*);
+
+ ~Sessions();
+
+ friend Sessions& GetSessions(); // singleton creator
+private:
+ Sessions(const Sessions&); // hide copy
+ Sessions& operator=(const Sessions&); // and assign
+};
+
+
+Sessions& GetSessions(); // forward singletons
+sslFactory& GetSSL_Factory();
+
+
+// openSSL method and context types
+class SSL_METHOD {
+ ProtocolVersion version_;
+ ConnectionEnd side_;
+ bool verifyPeer_;
+ bool failNoCert_;
+public:
+ explicit SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv);
+
+ ProtocolVersion getVersion() const;
+ ConnectionEnd getSide() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+
+ bool verifyPeer() const;
+ bool failNoCert() const;
+private:
+ SSL_METHOD(const SSL_METHOD&); // hide copy
+ SSL_METHOD& operator=(const SSL_METHOD&); // and assign
+};
+
+
+struct Ciphers {
+ bool setSuites_; // user set suites from default
+ byte suites_[MAX_SUITE_SZ]; // new suites
+ int suiteSz_; // suite length in bytes
+
+ Ciphers() : setSuites_(false), suiteSz_(0) {}
+};
+
+
+struct DH; // forward
+
+
+// save for SSL construction
+struct DH_Parms {
+ Integer p_;
+ Integer g_;
+ bool set_; // if set by user
+
+ DH_Parms() : set_(false) {}
+};
+
+
+enum StatsField {
+ Accept, Connect, AcceptGood, ConnectGood, AcceptRenegotiate,
+ ConnectRenegotiate, Hits, CbHits, CacheFull, Misses, Timeouts, Number,
+ GetCacheSize, VerifyMode, VerifyDepth
+};
+
+
+// SSL stats
+struct Stats {
+ long accept_;
+ long connect_;
+ long acceptGood_;
+ long connectGood_;
+ long acceptRenegotiate_;
+ long connectRenegotiate_;
+
+ long hits_;
+ long cbHits_;
+ long cacheFull_;
+ long misses_;
+ long timeouts_;
+ long number_;
+ long getCacheSize_;
+
+ int verifyMode_;
+ int verifyDepth_;
+public:
+ Stats() : accept_(0), connect_(0), acceptGood_(0), connectGood_(0),
+ acceptRenegotiate_(0), connectRenegotiate_(0), hits_(0), cbHits_(0),
+ cacheFull_(0), misses_(0), timeouts_(0), number_(0), getCacheSize_(0),
+ verifyMode_(0), verifyDepth_(0)
+ {}
+private:
+ Stats(const Stats&); // hide copy
+ Stats& operator=(const Stats&); // and assign
+};
+
+
+// the SSL context
+class SSL_CTX {
+public:
+ typedef mySTL::list<x509*> CertList;
+private:
+ SSL_METHOD* method_;
+ x509* certificate_;
+ x509* privateKey_;
+ CertList caList_;
+ Ciphers ciphers_;
+ DH_Parms dhParms_;
+ Stats stats_;
+ Mutex mutex_; // for Stats
+public:
+ explicit SSL_CTX(SSL_METHOD* meth);
+ ~SSL_CTX();
+
+ const x509* getCert() const;
+ const x509* getKey() const;
+ const SSL_METHOD* getMethod() const;
+ const Ciphers& GetCiphers() const;
+ const DH_Parms& GetDH_Parms() const;
+ const Stats& GetStats() const;
+
+ void setVerifyPeer();
+ void setFailNoCert();
+ bool SetCipherList(const char*);
+ bool SetDH(const DH&);
+
+ void IncrementStats(StatsField);
+ void AddCA(x509* ca);
+ const CertList& GetCA_List() const;
+
+ friend int read_file(SSL_CTX*, const char*, int, CertType);
+private:
+ SSL_CTX(const SSL_CTX&); // hide copy
+ SSL_CTX& operator=(const SSL_CTX&); // and assign
+};
+
+
+// holds all cryptographic types
+class Crypto {
+ Digest* digest_; // agreed upon digest
+ BulkCipher* cipher_; // agreed upon cipher
+ DiffieHellman* dh_; // dh parms
+ RandomPool random_; // random number generator
+ CertManager cert_; // manages certificates
+public:
+ explicit Crypto();
+ ~Crypto();
+
+ const Digest& get_digest() const;
+ const BulkCipher& get_cipher() const;
+ const DiffieHellman& get_dh() const;
+ const RandomPool& get_random() const;
+ const CertManager& get_certManager() const;
+
+ Digest& use_digest();
+ BulkCipher& use_cipher();
+ DiffieHellman& use_dh();
+ RandomPool& use_random();
+ CertManager& use_certManager();
+
+ void SetDH(DiffieHellman*);
+ void SetDH(const DH_Parms&);
+ void setDigest(Digest*);
+ void setCipher(BulkCipher*);
+
+ bool DhSet();
+private:
+ Crypto(const Crypto&); // hide copy
+ Crypto& operator=(const Crypto&); // and assign
+};
+
+
+// holds all handshake and verify hashes
+class sslHashes {
+ MD5 md5HandShake_; // md5 handshake hash
+ SHA shaHandShake_; // sha handshake hash
+ Finished verify_; // peer's verify hash
+ Hashes certVerify_; // peer's cert verify hash
+public:
+ sslHashes() {}
+
+ const MD5& get_MD5() const;
+ const SHA& get_SHA() const;
+ const Finished& get_verify() const;
+ const Hashes& get_certVerify() const;
+
+ MD5& use_MD5();
+ SHA& use_SHA();
+ Finished& use_verify();
+ Hashes& use_certVerify();
+private:
+ sslHashes(const sslHashes&); // hide copy
+ sslHashes& operator=(const sslHashes&); // and assign
+};
+
+
+// holds input and output buffers
+class Buffers {
+ typedef mySTL::list<input_buffer*> inputList;
+ typedef mySTL::list<output_buffer*> outputList;
+
+ inputList dataList_; // list of users app data / handshake
+ outputList handShakeList_; // buffered handshake msgs
+public:
+ Buffers() {}
+ ~Buffers();
+
+ const inputList& getData() const;
+ const outputList& getHandShake() const;
+
+ inputList& useData();
+ outputList& useHandShake();
+private:
+ Buffers(const Buffers&); // hide copy
+ Buffers& operator=(const Buffers&); // and assign
+};
+
+
+// wraps security parameters
+class Security {
+ Connection conn_; // connection information
+ Parameters parms_; // may be pending
+ SSL_SESSION resumeSession_; // if resuming
+ SSL_CTX* ctx_; // context used to init
+ bool resuming_; // trying to resume
+public:
+ Security(ProtocolVersion, RandomPool&, ConnectionEnd, const Ciphers&,
+ SSL_CTX*);
+
+ const SSL_CTX* GetContext() const;
+ const Connection& get_connection() const;
+ const Parameters& get_parms() const;
+ const SSL_SESSION& get_resume() const;
+ bool get_resuming() const;
+
+ Connection& use_connection();
+ Parameters& use_parms();
+ SSL_SESSION& use_resume();
+
+ void set_resuming(bool b);
+private:
+ Security(const Security&); // hide copy
+ Security& operator=(const Security&); // and assign
+};
+
+
+// THE SSL type
+class SSL {
+ Crypto crypto_; // agreed crypto agents
+ Security secure_; // Connection and Session parms
+ States states_; // Record and HandShake states
+ sslHashes hashes_; // handshake, finished hashes
+ Socket socket_; // socket wrapper
+ Buffers buffers_; // buffered handshakes and data
+ Log log_; // logger
+public:
+ SSL(SSL_CTX* ctx);
+
+ // gets and uses
+ const Crypto& getCrypto() const;
+ const Security& getSecurity() const;
+ const States& getStates() const;
+ const sslHashes& getHashes() const;
+ const sslFactory& getFactory() const;
+ const Socket& getSocket() const;
+ YasslError GetError() const;
+
+ Crypto& useCrypto();
+ Security& useSecurity();
+ States& useStates();
+ sslHashes& useHashes();
+ Socket& useSocket();
+ Log& useLog();
+
+ // sets
+ void set_pending(Cipher suite);
+ void set_random(const opaque*, ConnectionEnd);
+ void set_sessionID(const opaque*);
+ void set_session(SSL_SESSION*);
+ void set_preMaster(const opaque*, uint);
+ void set_masterSecret(const opaque*);
+ void SetError(YasslError);
+
+ // helpers
+ bool isTLS() const;
+ void order_error();
+ void makeMasterSecret();
+ void makeTLSMasterSecret();
+ void addData(input_buffer* data);
+ void fillData(Data&);
+ void addBuffer(output_buffer* b);
+ void flushBuffer();
+ void verifyState(const RecordLayerHeader&);
+ void verifyState(const HandShakeHeader&);
+ void verifyState(ClientState);
+ void verifyState(ServerState);
+ void verfiyHandShakeComplete();
+ void matchSuite(const opaque*, uint length);
+ void deriveKeys();
+ void deriveTLSKeys();
+ void Send(const byte*, uint);
+
+ uint bufferedData();
+ uint get_SEQIncrement(bool);
+
+ const byte* get_macSecret(bool);
+private:
+ void storeKeys(const opaque*);
+ void setKeys();
+ void verifyClientState(HandShakeType);
+ void verifyServerState(HandShakeType);
+
+ SSL(const SSL&); // hide copy
+ const SSL& operator=(const SSL&); // and assign
+};
+
+
+
+// conversion functions
+void c32to24(uint32, uint24&);
+void c24to32(const uint24, uint32&);
+
+uint32 c24to32(const uint24);
+
+void ato16(const opaque*, uint16&);
+void ato24(const opaque*, uint24&);
+
+void c16toa(uint16, opaque*);
+void c24toa(const uint24, opaque*);
+void c32toa(uint32 u32, opaque*);
+
+
+} // naemspace
+
+#endif // yaSSL_INT_HPP
diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp
new file mode 100644
index 00000000000..70888f35c81
--- /dev/null
+++ b/extra/yassl/include/yassl_types.hpp
@@ -0,0 +1,415 @@
+/* yassl_types.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* yaSSL types header defines all constants, enums, and typedefs
+ * from the SSL.v3 specification "draft-freier-ssl-version3-02.txt"
+ */
+
+
+#ifndef yaSSL_TYPES_HPP
+#define yaSSL_TYPES_HPP
+
+#include<cstddef>
+
+namespace yaSSL {
+
+// library allocation
+struct new_t {}; // yaSSL New type
+extern new_t ys; // pass in parameter
+
+} // namespace yaSSL
+
+void* operator new (size_t, yaSSL::new_t);
+void* operator new[](size_t, yaSSL::new_t);
+
+namespace yaSSL {
+
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef uint8 uint24[3];
+typedef uint32 uint64[2];
+
+typedef uint8 opaque;
+typedef opaque byte;
+
+typedef unsigned int uint;
+
+
+// all length constants in bytes
+const int ID_LEN = 32; // session id length
+const int SUITE_LEN = 2; // cipher suite length
+const int SECRET_LEN = 48; // pre RSA and all master secret length
+const int MASTER_ROUNDS = 3; // master secret derivation rounds
+const int RAN_LEN = 32; // client and server random length
+const int MAC_BLOCK_SZ = 64; // MAC block size, & padding
+const int MD5_LEN = 16; // MD5 digest length
+const int SHA_LEN = 20; // SHA digest length
+const int RMD_LEN = 20; // RIPEMD-160 digest length
+const int PREFIX = 3; // up to 3 prefix letters for secret rounds
+const int KEY_PREFIX = 7; // up to 7 prefix letters for key rounds
+const int FORTEZZA_MAX = 128; // Maximum Fortezza Key length
+const int MAX_SUITE_SZ = 64; // 32 max suites * sizeof(suite)
+const int MAX_SUITE_NAME = 48; // max length of suite name
+const int MAX_CIPHER_LIST = 512; // max length of cipher list names
+const int SIZEOF_ENUM = 1; // SSL considers an enum 1 byte, not 4
+const int SIZEOF_SENDER = 4; // Sender constant, for finished generation
+const int PAD_MD5 = 48; // pad length 1 and 2 for md5 finished
+const int PAD_SHA = 40; // should be 44, specd wrong by netscape
+const int PAD_RMD = 44; // pad length for RIPEMD-160, some use 40??
+const int CERT_HEADER = 3; // always use 3 bytes for certificate
+const int CERT_TYPES = 7; // certificate request types
+const int REQUEST_HEADER = 2; // request uses 2 bytes
+const int VERIFY_HEADER = 2; // verify length field
+const int MIN_CERT_TYPES = 1; // minimum certificate request types
+const int MIN_DIS_NAMES = 3; // minimum distinguished names
+const int MIN_DIS_SIZE = 1; // minimum distinguished name size
+const int RECORD_HEADER = 5; // type + version + length(2)
+const int HANDSHAKE_HEADER = 4; // type + length(3)
+const int FINISHED_SZ = MD5_LEN + SHA_LEN; // sizeof finished data
+const int TLS_FINISHED_SZ = 12; // TLS verify data size
+const int SEQ_SZ = 8; // 64 bit sequence number
+const int LENGTH_SZ = 2; // length field for HMAC, data only
+const int VERSION_SZ = SIZEOF_ENUM * 2; // SSL/TLS length of version
+const int DES_KEY_SZ = 8; // DES Key length
+const int DES_EDE_KEY_SZ = 24; // DES EDE Key length
+const int DES_BLOCK = 8; // DES is always fixed block size 8
+const int DES_IV_SZ = DES_BLOCK; // Init Vector length for DES
+const int RC4_KEY_SZ = 16; // RC4 Key length
+const int AES_128_KEY_SZ = 16; // AES 128bit Key length
+const int AES_256_KEY_SZ = 32; // AES 256bit Key length
+const int AES_BLOCK_SZ = 16; // AES 128bit block size, rfc 3268
+const int AES_IV_SZ = AES_BLOCK_SZ; // AES Init Vector length
+const int DSS_SIG_SZ = 40; // two 20 byte high byte first Integers
+const int DSS_ENCODED_EXTRA = 6; // seqID + len(1) + (intID + len(1)) * 2
+const int EVP_SALT_SZ = 8;
+const int MASTER_LABEL_SZ = 13; // TLS master secret label size
+const int KEY_LABEL_SZ = 13; // TLS key block expansion size
+const int FINISHED_LABEL_SZ = 15; // TLS finished lable length
+const int SEED_LEN = RAN_LEN * 2; // TLS seed, client + server random
+const int DEFAULT_TIMEOUT = 500; // Default Session timeout in seconds
+const int MAX_RECORD_SIZE = 16384; // 2^14, max size by standard
+
+
+typedef uint8 Cipher; // first byte is always 0x00 for SSLv3 & TLS
+
+typedef opaque Random[RAN_LEN];
+
+typedef opaque* DistinguishedName;
+
+typedef bool IsExportable;
+
+
+enum CompressionMethod { no_compression = 0 };
+
+enum CipherType { stream, block };
+
+enum CipherChoice { change_cipher_spec_choice = 1 };
+
+enum PublicValueEncoding { implicit_encoding, explicit_encoding };
+
+enum ConnectionEnd { server_end, client_end };
+
+enum AlertLevel { warning = 1, fatal = 2, };
+
+
+
+// Record Layer Header identifier from page 12
+enum ContentType {
+ no_type = 0,
+ change_cipher_spec = 20,
+ alert = 21,
+ handshake = 22,
+ application_data = 23
+};
+
+
+// HandShake Layer Header identifier from page 20
+enum HandShakeType {
+ no_shake = -1,
+ hello_request = 0,
+ client_hello = 1,
+ server_hello = 2,
+ certificate = 11,
+ server_key_exchange = 12,
+ certificate_request = 13,
+ server_hello_done = 14,
+ certificate_verify = 15,
+ client_key_exchange = 16,
+ finished = 20
+};
+
+
+// Valid Alert types from page 16/17
+enum AlertDescription {
+ close_notify = 0,
+ unexpected_message = 10,
+ bad_record_mac = 20,
+ decompression_failure = 30,
+ handshake_failure = 40,
+ no_certificate = 41,
+ bad_certificate = 42,
+ unsupported_certificate = 43,
+ certificate_revoked = 44,
+ certificate_expired = 45,
+ certificate_unknown = 46,
+ illegal_parameter = 47
+};
+
+
+// Supported Key Exchange Protocols
+enum KeyExchangeAlgorithm {
+ no_kea = 0,
+ rsa_kea,
+ diffie_hellman_kea,
+ fortezza_kea
+};
+
+
+// Supported Authentication Schemes
+enum SignatureAlgorithm {
+ anonymous_sa_algo = 0,
+ rsa_sa_algo,
+ dsa_sa_algo
+};
+
+
+// Valid client certificate request types from page 27
+enum ClientCertificateType {
+ rsa_sign = 1,
+ dss_sign = 2,
+ rsa_fixed_dh = 3,
+ dss_fixed_dh = 4,
+ rsa_ephemeral_dh = 5,
+ dss_ephemeral_dh = 6,
+ fortezza_kea_cert = 20
+};
+
+
+// Supported Ciphers from page 43
+enum BulkCipherAlgorithm {
+ cipher_null,
+ rc4,
+ rc2,
+ des,
+ triple_des, // leading 3 (3des) not valid identifier
+ des40,
+ idea,
+ aes
+};
+
+
+// Supported Message Authentication Codes from page 43
+enum MACAlgorithm {
+ no_mac,
+ md5,
+ sha,
+ rmd
+};
+
+
+// Certificate file Type
+enum CertType { Cert = 0, PrivateKey, CA };
+
+
+// all Cipher Suites from pages 41/42
+const Cipher SSL_NULL_WITH_NULL_NULL = 0; // { 0x00, 0x00 }
+const Cipher SSL_RSA_WITH_NULL_MD5 = 1; // { 0x00, 0x01 }
+const Cipher SSL_RSA_WITH_NULL_SHA = 2; // { 0x00, 0x02 }
+const Cipher SSL_RSA_EXPORT_WITH_RC4_40_MD5 = 3; // { 0x00, 0x03 }
+const Cipher SSL_RSA_WITH_RC4_128_MD5 = 4; // { 0x00, 0x04 }
+const Cipher SSL_RSA_WITH_RC4_128_SHA = 5; // { 0x00, 0x05 }
+const Cipher SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6; // { 0x00, 0x06 }
+const Cipher SSL_RSA_WITH_IDEA_CBC_SHA = 7; // { 0x00, 0x07 }
+const Cipher SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = 8; // { 0x00, 0x08 }
+const Cipher SSL_RSA_WITH_DES_CBC_SHA = 9; // { 0x00, 0x09 }
+const Cipher SSL_RSA_WITH_3DES_EDE_CBC_SHA = 10; // { 0x00, 0x0A }
+const Cipher SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11; // { 0x00, 0x0B }
+const Cipher SSL_DH_DSS_WITH_DES_CBC_SHA = 12; // { 0x00, 0x0C }
+const Cipher SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13; // { 0x00, 0x0D }
+const Cipher SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14; // { 0x00, 0x0E }
+const Cipher SSL_DH_RSA_WITH_DES_CBC_SHA = 15; // { 0x00, 0x0F }
+const Cipher SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16; // { 0x00, 0x10 }
+const Cipher SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17; // { 0x00, 0x11 }
+const Cipher SSL_DHE_DSS_WITH_DES_CBC_SHA = 18; // { 0x00, 0x12 }
+const Cipher SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19; // { 0x00, 0x13 }
+const Cipher SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20; // { 0x00, 0x14 }
+const Cipher SSL_DHE_RSA_WITH_DES_CBC_SHA = 21; // { 0x00, 0x15 }
+const Cipher SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22; // { 0x00, 0x16 }
+const Cipher SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23; // { 0x00, 0x17 }
+const Cipher SSL_DH_anon_WITH_RC4_128_MD5 = 24; // { 0x00, 0x18 }
+const Cipher SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25; // { 0x00, 0x19 }
+const Cipher SSL_DH_anon_WITH_DES_CBC_SHA = 26; // { 0x00, 0x1A }
+const Cipher SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = 27; // { 0x00, 0x1B }
+const Cipher SSL_FORTEZZA_KEA_WITH_NULL_SHA = 28; // { 0x00, 0x1C }
+const Cipher SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 29; // { 0x00, 0x1D }
+const Cipher SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 30; // { 0x00, 0x1E }
+
+// .. to 0x2B uses Kerberos Authentication
+
+
+// TLS AES extensions
+const Cipher TLS_RSA_WITH_AES_128_CBC_SHA = 47; // { 0x00, 0x2F }
+const Cipher TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48; // { 0x00, 0x30 }
+const Cipher TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49; // { 0x00, 0x31 }
+const Cipher TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50; // { 0x00, 0x32 }
+const Cipher TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51; // { 0x00, 0x33 }
+const Cipher TLS_DH_anon_WITH_AES_128_CBC_SHA = 52; // { 0x00, 0x34 }
+
+const Cipher TLS_RSA_WITH_AES_256_CBC_SHA = 53; // { 0x00, 0x35 }
+const Cipher TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54; // { 0x00, 0x36 }
+const Cipher TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55; // { 0x00, 0x37 }
+const Cipher TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56; // { 0x00, 0x38 }
+const Cipher TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57; // { 0x00, 0x39 }
+const Cipher TLS_DH_anon_WITH_AES_256_CBC_SHA = 58; // { 0x00, 0x3A }
+
+
+// OpenPGP extensions
+
+const Cipher TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160 = 114; // { 0x00, 0x72 };
+const Cipher TLS_DHE_DSS_WITH_AES_128_CBC_RMD160 = 115; // { 0x00, 0x73 };
+const Cipher TLS_DHE_DSS_WITH_AES_256_CBC_RMD160 = 116; // { 0x00, 0x74 };
+const Cipher TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160 = 119; // { 0x00, 0x77 };
+const Cipher TLS_DHE_RSA_WITH_AES_128_CBC_RMD160 = 120; // { 0x00, 0x78 };
+const Cipher TLS_DHE_RSA_WITH_AES_256_CBC_RMD160 = 121; // { 0x00, 0x79 };
+const Cipher TLS_RSA_WITH_3DES_EDE_CBC_RMD160 = 124; // { 0x00, 0x7C };
+const Cipher TLS_RSA_WITH_AES_128_CBC_RMD160 = 125; // { 0x00, 0x7D };
+const Cipher TLS_RSA_WITH_AES_256_CBC_RMD160 = 126; // { 0x00, 0x7E };
+
+
+const char* const null_str = "";
+
+const char* const cipher_names[128] =
+{
+ null_str, // SSL_NULL_WITH_NULL_NULL = 0
+ null_str, // SSL_RSA_WITH_NULL_MD5 = 1
+ null_str, // SSL_RSA_WITH_NULL_SHA = 2
+ null_str, // SSL_RSA_EXPORT_WITH_RC4_40_MD5 = 3
+ "RC4-MD5", // SSL_RSA_WITH_RC4_128_MD5 = 4
+ "RC4-SHA", // SSL_RSA_WITH_RC4_128_SHA = 5
+ null_str, // SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 6
+ null_str, // SSL_RSA_WITH_IDEA_CBC_SHA = 7
+ null_str, // SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = 8
+ "DES-CBC-SHA", // SSL_RSA_WITH_DES_CBC_SHA = 9
+ "DES-CBC3-SHA", // SSL_RSA_WITH_3DES_EDE_CBC_SHA = 10
+
+ null_str, // SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 11
+ null_str, // SSL_DH_DSS_WITH_DES_CBC_SHA = 12
+ null_str, // SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = 13
+ null_str, // SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 14
+ null_str, // SSL_DH_RSA_WITH_DES_CBC_SHA = 15
+ null_str, // SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = 16
+ null_str, // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 17
+ "EDH-DSS-DES-CBC-SHA", // SSL_DHE_DSS_WITH_DES_CBC_SHA = 18
+ "EDH-DSS-DES-CBC3-SHA", // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 19
+ null_str, // SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 20
+
+ "EDH-RSA-DES-CBC-SHA", // SSL_DHE_RSA_WITH_DES_CBC_SHA = 21
+ "EDH-RSA-DES-CBC3-SHA", // SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 22
+ null_str, // SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = 23
+ null_str, // SSL_DH_anon_WITH_RC4_128_MD5 = 24
+ null_str, // SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 25
+ null_str, // SSL_DH_anon_WITH_DES_CBC_SHA = 26
+ null_str, // SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = 27
+ null_str, // SSL_FORTEZZA_KEA_WITH_NULL_SHA = 28
+ null_str, // SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 29
+ null_str, // SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 30
+
+ null_str, null_str, null_str, null_str, null_str, // 31 - 35
+ null_str, null_str, null_str, null_str, null_str, // 36 - 40
+ null_str, null_str, null_str, null_str, null_str, // 41 - 45
+ null_str, // 46
+
+ // TLS AES extensions
+ "AES128-SHA", // TLS_RSA_WITH_AES_128_CBC_SHA = 47
+ null_str, // TLS_DH_DSS_WITH_AES_128_CBC_SHA = 48
+ null_str, // TLS_DH_RSA_WITH_AES_128_CBC_SHA = 49
+ "DHE-DSS-AES128-SHA", // TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 50
+ "DHE-RSA-AES128-SHA", // TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 51
+ null_str, // TLS_DH_anon_WITH_AES_128_CBC_SHA = 52
+
+ "AES256-SHA", // TLS_RSA_WITH_AES_256_CBC_SHA = 53
+ null_str, // TLS_DH_DSS_WITH_AES_256_CBC_SHA = 54
+ null_str, // TLS_DH_RSA_WITH_AES_256_CBC_SHA = 55
+ "DHE-DSS-AES256-SHA", // TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 56
+ "DHE-RSA-AES256-SHA", // TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 57
+ null_str, // TLS_DH_anon_WITH_AES_256_CBC_SHA = 58
+
+ null_str, // 59
+ null_str, // 60
+ null_str, null_str, null_str, null_str, null_str, // 61 - 65
+ null_str, null_str, null_str, null_str, null_str, // 66 - 70
+ null_str, null_str, null_str, null_str, null_str, // 71 - 75
+ null_str, null_str, null_str, null_str, null_str, // 76 - 80
+ null_str, null_str, null_str, null_str, null_str, // 81 - 85
+ null_str, null_str, null_str, null_str, null_str, // 86 - 90
+ null_str, null_str, null_str, null_str, null_str, // 91 - 95
+ null_str, null_str, null_str, null_str, null_str, // 96 - 100
+ null_str, null_str, null_str, null_str, null_str, // 101 - 105
+ null_str, null_str, null_str, null_str, null_str, // 106 - 110
+ null_str, null_str, null_str, // 111 - 113
+
+ "DHE-DSS-DES-CBC3-RMD", // TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160 = 114
+ "DHE-DSS-AES128-RMD", // TLS_DHE_DSS_WITH_AES_128_CBC_RMD160 = 115
+ "DHE-DSS-AES256-RMD", // TLS_DHE_DSS_WITH_AES_256_CBC_RMD160 = 116
+ null_str, // 117
+ null_str, // 118
+ "DHE-RSA-DES-CBC3-RMD", // TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160 = 119
+ "DHE-RSA-AES128-RMD", // TLS_DHE_RSA_WITH_AES_128_CBC_RMD160 = 120
+ "DHE-RSA-AES256-RMD", // TLS_DHE_RSA_WITH_AES_256_CBC_RMD160 = 121
+ null_str, // 122
+ null_str, // 123
+ "DES-CBC3-RMD", // TLS_RSA_WITH_3DES_EDE_CBC_RMD160 = 124
+ "AES128-RMD", // TLS_RSA_WITH_AES_128_CBC_RMD160 = 125
+ "AES256-RMD", // TLS_RSA_WITH_AES_256_CBC_RMD160 = 126
+ null_str, // 127
+};
+
+// fill with MD5 pad size since biggest required
+const opaque PAD1[PAD_MD5] = { 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
+ };
+const opaque PAD2[PAD_MD5] = { 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
+ };
+
+const opaque client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 };
+const opaque server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 };
+
+const opaque tls_client[FINISHED_LABEL_SZ + 1] = "client finished";
+const opaque tls_server[FINISHED_LABEL_SZ + 1] = "server finished";
+
+const opaque master_label[MASTER_LABEL_SZ + 1] = "master secret";
+const opaque key_label [KEY_LABEL_SZ + 1] = "key expansion";
+
+
+} // naemspace
+
+#endif // yaSSL_TYPES_HPP
diff --git a/extra/yassl/mySTL/algorithm.hpp b/extra/yassl/mySTL/algorithm.hpp
new file mode 100644
index 00000000000..3ceb0ca5fdc
--- /dev/null
+++ b/extra/yassl/mySTL/algorithm.hpp
@@ -0,0 +1,111 @@
+/* mySTL algorithm.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL algorithm implements max, min, for_each, swap, find_if, copy,
+ * copy_backward, fill
+ */
+
+#ifndef mySTL_ALGORITHM_HPP
+#define mySTL_ALGORITHM_HPP
+
+
+namespace mySTL {
+
+
+template<typename T>
+inline const T& max(const T& a, const T&b)
+{
+ return a < b ? b : a;
+}
+
+
+template<typename T>
+inline const T& min(const T& a, const T&b)
+{
+ return b < a ? b : a;
+}
+
+
+template<typename InIter, typename Func>
+Func for_each(InIter first, InIter last, Func op)
+{
+ while (first != last) {
+ op(*first);
+ ++first;
+ }
+ return op;
+}
+
+
+template<typename T>
+inline void swap(T& a, T& b)
+{
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+
+template<typename InIter, typename Pred>
+InIter find_if(InIter first, InIter last, Pred pred)
+{
+ while (first != last && !pred(*first))
+ ++first;
+ return first;
+}
+
+
+template<typename InputIter, typename OutputIter>
+inline OutputIter copy(InputIter first, InputIter last, OutputIter place)
+{
+ while (first != last) {
+ *place = *first;
+ ++first;
+ ++place;
+ }
+ return place;
+}
+
+
+template<typename InputIter, typename OutputIter>
+inline OutputIter
+copy_backward(InputIter first, InputIter last, OutputIter place)
+{
+ while (first != last)
+ *--place = *--last;
+ return place;
+}
+
+
+template<typename InputIter, typename T>
+void fill(InputIter first, InputIter last, const T& v)
+{
+ while (first != last) {
+ *first = v;
+ ++first;
+ }
+}
+
+
+} // namespace mySTL
+
+#endif // mySTL_ALGORITHM_HPP
diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/mySTL/helpers.hpp
new file mode 100644
index 00000000000..1b62d60cd2e
--- /dev/null
+++ b/extra/yassl/mySTL/helpers.hpp
@@ -0,0 +1,94 @@
+/* mySTL helpers.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL helpers implements misc constructs for vector and list
+ *
+ */
+
+#ifndef mySTL_HELPERS_HPP
+#define mySTL_HELPERS_HPP
+
+#include <cstdlib>
+
+
+namespace mySTL {
+
+
+template <typename T, typename T2>
+inline void construct(T* p, const T2& value)
+{
+ new (static_cast<void*>(p)) T(value);
+}
+
+
+template <typename T>
+inline void construct(T* p)
+{
+ new (static_cast<void*>(p)) T();
+}
+
+
+template <typename T>
+inline void destroy(T* p)
+{
+ p->~T();
+}
+
+
+template <typename Iter>
+void destroy(Iter first, Iter last)
+{
+ while (first != last) {
+ destroy(&*first);
+ ++first;
+ }
+}
+
+
+template <typename Iter, typename PlaceIter>
+PlaceIter uninit_copy(Iter first, Iter last, PlaceIter place)
+{
+ while (first != last) {
+ construct(&*place, *first);
+ ++first;
+ ++place;
+ }
+ return place;
+}
+
+
+template <typename PlaceIter, typename Size, typename T>
+PlaceIter uninit_fill_n(PlaceIter place, Size n, const T& value)
+{
+ while (n) {
+ construct(&*place, value);
+ --n;
+ ++place;
+ }
+ return place;
+}
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_HELPERS_HPP
diff --git a/extra/yassl/mySTL/list.hpp b/extra/yassl/mySTL/list.hpp
new file mode 100644
index 00000000000..223ae5a0fe4
--- /dev/null
+++ b/extra/yassl/mySTL/list.hpp
@@ -0,0 +1,374 @@
+/* mySTL list.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL list implements a simple list
+ *
+ */
+
+#ifndef mySTL_LIST_HPP
+#define mySTL_LIST_HPP
+
+
+#include "helpers.hpp"
+#include <new> // ::operator new and delete, placement too
+
+
+namespace mySTL {
+
+
+
+template<typename T>
+class list {
+ struct node {
+ node(T t) : prev_(0), next_(0), value_(t) {}
+
+ node* prev_;
+ node* next_;
+ T value_;
+ };
+public:
+ list() : head_(0), tail_(0), sz_(0) {}
+ ~list();
+
+ void push_front(T);
+ void pop_front();
+ T front() const;
+ void push_back(T);
+ void pop_back();
+ T back() const;
+ bool remove(T);
+ size_t size() const { return sz_; }
+ bool empty() const { return sz_ == 0; }
+
+ class iterator {
+ node* current_;
+ public:
+ iterator() : current_(0) {}
+ explicit iterator(node* p) : current_(p) {}
+
+ T& operator*() const
+ {
+ return current_->value_;
+ }
+
+ T* operator->() const
+ {
+ return &(operator*());
+ }
+
+ iterator& operator++()
+ {
+ current_ = current_->next_;
+ return *this;
+ }
+
+ iterator& operator--()
+ {
+ current_ = current_->prev_;
+ return *this;
+ }
+
+ iterator& operator++(int)
+ {
+ iterator tmp = *this;
+ current_ = current_->next_;
+ return tmp;
+ }
+
+ iterator& operator--(int)
+ {
+ iterator tmp = *this;
+ current_ = current_->prev_;
+ return tmp;
+ }
+
+ bool operator==(const iterator& other) const
+ {
+ return current_ == other.current_;
+ }
+
+ bool operator!=(const iterator& other) const
+ {
+ return current_ != other.current_;
+ }
+
+ friend class list<T>;
+ };
+
+ bool erase(iterator);
+
+ iterator begin() const { return iterator(head_); }
+ iterator rbegin() const { return iterator(tail_); }
+ iterator end() const { return iterator(); }
+
+ typedef iterator const_iterator; // for now
+
+ class underflow {};
+ class overflow {};
+private:
+ node* head_;
+ node* tail_;
+ size_t sz_;
+
+ node* look_up(T);
+
+ list(const list&); // hide copy
+ list& operator=(const list&); // and assign
+};
+
+
+template<typename T>
+list<T>::~list()
+{
+ node* start = head_;
+ node* next_;
+
+ for (; start; start = next_) {
+ next_ = start->next_;
+ destroy(start);
+ ::operator delete(start);
+ }
+}
+
+
+template<typename T>
+void list<T>::push_front(T t)
+{
+ void* mem = ::operator new(sizeof(node));
+ if (!mem) abort();
+ node* add = new (mem) node(t);
+
+ if (head_) {
+ add->next_ = head_;
+ head_->prev_ = add;
+ }
+ else
+ tail_ = add;
+
+ head_ = add;
+ ++sz_;
+}
+
+
+template<typename T>
+void list<T>::pop_front()
+{
+ node* front = head_;
+
+ if (head_ == 0)
+ return;
+ else if (head_ == tail_)
+ head_ = tail_ = 0;
+ else {
+ head_ = head_->next_;
+ head_->prev_ = 0;
+ }
+ destroy(front);
+ ::operator delete(front);
+ --sz_;
+}
+
+
+template<typename T>
+T list<T>::front() const
+{
+ if (head_ == 0) return 0;
+ return head_->value_;
+}
+
+
+template<typename T>
+void list<T>::push_back(T t)
+{
+ void* mem = ::operator new(sizeof(node));
+ if (!mem) abort();
+ node* add = new (mem) node(t);
+
+ if (tail_) {
+ tail_->next_ = add;
+ add->prev_ = tail_;
+ }
+ else
+ head_ = add;
+
+ tail_ = add;
+ ++sz_;
+}
+
+
+template<typename T>
+void list<T>::pop_back()
+{
+ node* rear = tail_;
+
+ if (tail_ == 0)
+ return;
+ else if (tail_ == head_)
+ tail_ = head_ = 0;
+ else {
+ tail_ = tail_->prev_;
+ tail_->next_ = 0;
+ }
+ destroy(rear);
+ ::operator delete(rear);
+ --sz_;
+}
+
+
+template<typename T>
+T list<T>::back() const
+{
+ if (back == 0) return 0;
+ return back->value_;
+}
+
+
+template<typename T>
+typename list<T>::node* list<T>::look_up(T t)
+{
+ node* list = head_;
+
+ if (list == 0) return 0;
+
+ for (; list; list = list->next_)
+ if (list->value_ == t)
+ return list;
+
+ return 0;
+}
+
+
+template<typename T>
+bool list<T>::remove(T t)
+{
+ node* del = look_up(t);
+
+ if (del == 0)
+ return false;
+ else if (del == head_)
+ pop_front();
+ else if (del == tail_)
+ pop_back();
+ else {
+ del->prev_->next_ = del->next_;
+ del->next_->prev_ = del->prev_;
+
+ destroy(del);
+ ::operator delete(del);
+ --sz_;
+ }
+ return true;
+}
+
+
+template<typename T>
+bool list<T>::erase(iterator iter)
+{
+ node* del = iter.current_;
+
+ if (del == 0)
+ return false;
+ else if (del == head_)
+ pop_front();
+ else if (del == tail_)
+ pop_back();
+ else {
+ del->prev_->next_ = del->next_;
+ del->next_->prev_ = del->prev_;
+
+ destroy(del);
+ ::operator delete(del);
+ --sz_;
+ }
+ return true;
+}
+
+
+/* MSVC can't handle ??
+
+template<typename T>
+T& list<T>::iterator::operator*() const
+{
+ return current_->value_;
+}
+
+
+template<typename T>
+T* list<T>::iterator::operator->() const
+{
+ return &(operator*());
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator++()
+{
+ current_ = current_->next_;
+ return *this;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator--()
+{
+ current_ = current_->prev_;
+ return *this;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator++(int)
+{
+ iterator tmp = *this;
+ current_ = current_->next_;
+ return tmp;
+}
+
+
+template<typename T>
+typename list<T>::iterator& list<T>::iterator::operator--(int)
+{
+ iterator tmp = *this;
+ current_ = current_->prev_;
+ return tmp;
+}
+
+
+template<typename T>
+bool list<T>::iterator::operator==(const iterator& other) const
+{
+ return current_ == other.current_;
+}
+
+
+template<typename T>
+bool list<T>::iterator::operator!=(const iterator& other) const
+{
+ return current_ != other.current_;
+}
+*/ // end MSVC 6 can't handle
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_LIST_HPP
diff --git a/extra/yassl/mySTL/memory.hpp b/extra/yassl/mySTL/memory.hpp
new file mode 100644
index 00000000000..4049ed80813
--- /dev/null
+++ b/extra/yassl/mySTL/memory.hpp
@@ -0,0 +1,127 @@
+/* mySTL memory.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL memory implements auto_ptr
+ *
+ */
+
+#ifndef mySTL_MEMORY_HPP
+#define mySTL_MEMORY_HPP
+
+
+#ifdef _MSC_VER
+ // disable operator-> warning for builtins
+ #pragma warning(disable:4284)
+#endif
+
+
+namespace mySTL {
+
+
+template<typename T>
+struct auto_ptr_ref {
+ T* ptr_;
+ explicit auto_ptr_ref(T* p) : ptr_(p) {}
+};
+
+
+template<typename T>
+class auto_ptr {
+ T* ptr_;
+public:
+ explicit auto_ptr(T* p = 0) : ptr_(p) {}
+ ~auto_ptr()
+ {
+ delete ptr_;
+ }
+
+
+ auto_ptr(auto_ptr& other) : ptr_(other.release()) {}
+ auto_ptr& operator=(auto_ptr& that)
+ {
+ if (this != &that) {
+ delete ptr_;
+ ptr_ = that.release();
+ }
+ return *this;
+ }
+
+
+ T* operator->() const
+ {
+ return ptr_;
+ }
+
+ T& operator*() const
+ {
+ return *ptr_;
+ }
+
+ T* get() const
+ {
+ return ptr_;
+ }
+
+ T* release()
+ {
+ T* tmp = ptr_;
+ ptr_ = 0;
+ return tmp;
+ }
+
+ void reset(T* p = 0)
+ {
+ if (ptr_ != p) {
+ delete ptr_;
+ ptr_ = p;
+ }
+ }
+
+ // auto_ptr_ref conversions
+ auto_ptr(auto_ptr_ref<T> ref) : ptr_(ref.ptr_) {}
+
+ auto_ptr& operator=(auto_ptr_ref<T> ref)
+ {
+ if (this->ptr_ != ref.ptr_) {
+ delete ptr_;
+ ptr_ = ref.ptr_;
+ }
+ return *this;
+ }
+
+ template<typename T2>
+ operator auto_ptr<T2>()
+ {
+ return auto_ptr<T2>(this->release());
+ }
+
+ template<typename T2>
+ operator auto_ptr_ref<T2>()
+ {
+ return auto_ptr_ref<T2>(this->release());
+ }
+};
+
+
+} // namespace mySTL
+
+#endif // mySTL_MEMORY_HPP
diff --git a/extra/yassl/mySTL/pair.hpp b/extra/yassl/mySTL/pair.hpp
new file mode 100644
index 00000000000..c9bb03b5953
--- /dev/null
+++ b/extra/yassl/mySTL/pair.hpp
@@ -0,0 +1,61 @@
+/* mySTL pair.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL pair implements pair
+ *
+ */
+
+#ifndef mySTL_PAIR_HPP
+#define mySTL_PAIR_HPP
+
+
+
+namespace mySTL {
+
+
+template<typename T1, typename T2>
+struct pair {
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ first_type first;
+ second_type second;
+
+ pair() {}
+ pair(const T1& t1, const T2& t2) : first(t1), second(t2) {}
+
+ template<typename U1, typename U2>
+ pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}
+};
+
+
+template<typename T1, typename T2>
+inline pair<T1, T2> make_pair(const T1& a, const T2& b)
+{
+ return pair<T1, T2>(a, b);
+}
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_PAIR_HPP
diff --git a/extra/yassl/mySTL/stdexcept.hpp b/extra/yassl/mySTL/stdexcept.hpp
new file mode 100644
index 00000000000..817861438a5
--- /dev/null
+++ b/extra/yassl/mySTL/stdexcept.hpp
@@ -0,0 +1,72 @@
+/* mySTL stdexcept.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL memory implements exception, runtime_error
+ *
+ */
+
+#ifndef mySTL_STDEXCEPT_HPP
+#define mySTL_STDEXCEPT_HPP
+
+
+#include <cstring> // strncpy
+
+
+namespace mySTL {
+
+
+class exception {
+public:
+ exception() {}
+ virtual ~exception() {}
+
+ virtual const char* what() const { return ""; }
+};
+
+
+class named_exception : public exception {
+public:
+ enum { NAME_SIZE = 80 };
+
+ explicit named_exception(const char* str)
+ {
+ strncpy(name_, str, NAME_SIZE);
+ name_[NAME_SIZE - 1] = 0;
+ }
+
+ virtual const char* what() const { return name_; }
+private:
+ char name_[NAME_SIZE];
+};
+
+
+class runtime_error : public named_exception {
+public:
+ explicit runtime_error(const char* str) : named_exception(str) {}
+};
+
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_STDEXCEPT_HPP
diff --git a/extra/yassl/mySTL/vector.hpp b/extra/yassl/mySTL/vector.hpp
new file mode 100644
index 00000000000..7f1f99295e4
--- /dev/null
+++ b/extra/yassl/mySTL/vector.hpp
@@ -0,0 +1,154 @@
+/* mySTL vector.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* mySTL vector implements simple vector, w/ swap
+ *
+ */
+
+#ifndef mySTL_VECTOR_HPP
+#define mySTL_VECTOR_HPP
+
+
+#include "helpers.hpp" // construct, destory, fill, etc.
+#include "algorithm.hpp" // swap
+#include <new> // ::operator new and delete, placement too
+#include <cassert> // assert
+
+
+namespace mySTL {
+
+
+template <typename T>
+struct vector_base {
+ T* start_;
+ T* finish_;
+ T* end_of_storage_;
+
+ vector_base() : start_(0), finish_(0), end_of_storage_(0) {}
+ vector_base(size_t n)
+ {
+ start_ = static_cast<T*>(::operator new(n * sizeof(T)));
+ if (!start_) abort();
+ finish_ = start_;
+ end_of_storage_ = start_ + n;
+ }
+
+ ~vector_base() { ::operator delete(start_); }
+
+ void Swap(vector_base& that)
+ {
+ swap(start_, that.start_);
+ swap(finish_, that.finish_);
+ swap(end_of_storage_, that.end_of_storage_);
+ }
+};
+
+
+
+template <typename T>
+class vector {
+public:
+ vector() {}
+ explicit vector(size_t n) : vec_(n)
+ {
+ vec_.finish_ = uninit_fill_n(vec_.start_, n, T());
+ }
+
+ ~vector() { destroy(vec_.start_, vec_.finish_); }
+
+ vector(const vector& other) : vec_(other.size())
+ {
+ vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_,
+ vec_.start_);
+ }
+
+ size_t capacity() const { return vec_.end_of_storage_ - vec_.start_; }
+
+ size_t size() const { return vec_.finish_ - vec_.start_; }
+
+ T& operator[](size_t idx) { return *(vec_.start_ + idx); }
+ const T& operator[](size_t idx) const { return *(vec_.start_ + idx); }
+
+ const T* begin() const { return vec_.start_; }
+ const T* end() const { return vec_.finish_; }
+
+ void push_back(const T& v)
+ {
+ if (vec_.finish_ != vec_.end_of_storage_) {
+ construct(vec_.finish_, v);
+ ++vec_.finish_;
+ }
+ else {
+ vector tmp(size() * 2 + 1, *this);
+ construct(tmp.vec_.finish_, v);
+ ++tmp.vec_.finish_;
+ Swap(tmp);
+ }
+ }
+
+ void resize(size_t n, const T& v)
+ {
+ if (n == size()) return;
+
+ if (n < size()) {
+ T* first = vec_.start_ + n;
+ destroy(first, vec_.finish_);
+ vec_.finish_ -= vec_.finish_ - first;
+ }
+ else {
+ vector tmp(n, *this);
+ tmp.vec_.finish_ = uninit_fill_n(tmp.vec_.finish_, n - size(), v);
+ Swap(tmp);
+ }
+ }
+
+ void reserve(size_t n)
+ {
+ if (capacity() < n) {
+ vector tmp(n, *this);
+ Swap(tmp);
+ }
+ }
+
+ void Swap(vector& that)
+ {
+ vec_.Swap(that.vec_);
+ }
+private:
+ vector_base<T> vec_;
+
+ vector& operator=(const vector&); // hide assign
+
+ // for growing, n must be bigger than other size
+ vector(size_t n, const vector& other) : vec_(n)
+ {
+ assert(n > other.size());
+ vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_,
+ vec_.start_);
+ }
+};
+
+
+
+} // namespace mySTL
+
+#endif // mySTL_VECTOR_HPP
diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am
new file mode 100644
index 00000000000..e0b8110b65c
--- /dev/null
+++ b/extra/yassl/src/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES = -I../include -I../taocrypt/include -I../mySTL
+
+noinst_LIBRARIES = libyassl.a
+libyassl_a_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \
+ handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \
+ timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp
+EXTRA_DIST = ../include/*.hpp ../include/openssl/*.h
+CXXFLAGS=`echo "@CXXFLAGS@" | sed 's/-fno-implicit-templates//'`
diff --git a/extra/yassl/src/buffer.cpp b/extra/yassl/src/buffer.cpp
new file mode 100644
index 00000000000..c97103c6f6d
--- /dev/null
+++ b/extra/yassl/src/buffer.cpp
@@ -0,0 +1,280 @@
+/* buffer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL buffer header implements input/output buffers to simulate streaming
+ * with SSL types and sockets
+ */
+
+#include "runtime.hpp"
+#include "buffer.hpp"
+#include "yassl_types.hpp"
+
+namespace yaSSL {
+
+
+
+// Checking Policy should implement a check function that tests whether the
+// index is within the size limit of the array
+
+void Check::check(uint i, uint limit)
+{
+ assert(i < limit);
+}
+
+
+void NoCheck::check(uint, uint)
+{
+}
+
+
+/* input_buffer operates like a smart c style array with a checking option,
+ * meant to be read from through [] with AUTO index or read().
+ * Should only write to at/near construction with assign() or raw (e.g., recv)
+ * followed by add_size with the number of elements added by raw write.
+ *
+ * Not using vector because need checked []access, offset, and the ability to
+ * write to the buffer bulk wise and have the correct size
+ */
+
+
+input_buffer::input_buffer()
+ : size_(0), current_(0), buffer_(0), end_(0)
+{}
+
+
+input_buffer::input_buffer(uint s)
+ : size_(0), current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{}
+
+
+// with assign
+input_buffer::input_buffer(uint s, const byte* t, uint len)
+ : size_(0), current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{
+ assign(t, len);
+}
+
+
+input_buffer::~input_buffer()
+{
+ delete [] buffer_;
+}
+
+
+// users can pass defualt zero length buffer and then allocate
+void input_buffer::allocate(uint s)
+{
+ assert(!buffer_); // find realloc error
+ buffer_ = new (ys) byte[s];
+ end_ = buffer_ + s;
+}
+
+
+// for passing to raw writing functions at beginning, then use add_size
+byte* input_buffer::get_buffer() const
+{
+ return buffer_;
+}
+
+
+// after a raw write user can set new size
+// if you know the size before the write use assign()
+void input_buffer::add_size(uint i)
+{
+ check(size_ + i-1, get_capacity());
+ size_ += i;
+}
+
+
+uint input_buffer::get_capacity() const
+{
+ return end_ - buffer_;
+}
+
+
+uint input_buffer::get_current() const
+{
+ return current_;
+}
+
+
+uint input_buffer::get_size() const
+{
+ return size_;
+}
+
+
+uint input_buffer::get_remaining() const
+{
+ return size_ - current_;
+}
+
+
+void input_buffer::set_current(uint i)
+{
+ if (i)
+ check(i - 1, size_);
+ current_ = i;
+}
+
+
+// read only access through [], advance current
+// user passes in AUTO index for ease of use
+const byte& input_buffer::operator[](uint i)
+{
+ assert (i == AUTO);
+ check(current_, size_);
+ return buffer_[current_++];
+}
+
+
+// end of input test
+bool input_buffer::eof()
+{
+ return current_ >= size_;
+}
+
+
+// peek ahead
+byte input_buffer::peek() const
+{
+ return buffer_[current_];
+}
+
+
+// write function, should use at/near construction
+void input_buffer::assign(const byte* t, uint s)
+{
+ check(current_, get_capacity());
+ add_size(s);
+ memcpy(&buffer_[current_], t, s);
+}
+
+
+// use read to query input, adjusts current
+void input_buffer::read(byte* dst, uint length)
+{
+ check(current_ + length - 1, size_);
+ memcpy(dst, &buffer_[current_], length);
+ current_ += length;
+}
+
+
+
+/* output_buffer operates like a smart c style array with a checking option.
+ * Meant to be written to through [] with AUTO index or write().
+ * Size (current) counter increases when written to. Can be constructed with
+ * zero length buffer but be sure to allocate before first use.
+ * Don't use add write for a couple bytes, use [] instead, way less overhead.
+ *
+ * Not using vector because need checked []access and the ability to
+ * write to the buffer bulk wise and retain correct size
+ */
+
+
+output_buffer::output_buffer()
+ : current_(0), buffer_(0), end_(0)
+{}
+
+
+// with allocate
+output_buffer::output_buffer(uint s)
+ : current_(0), buffer_(new (ys) byte[s]), end_(buffer_ + s)
+{}
+
+
+// with assign
+output_buffer::output_buffer(uint s, const byte* t, uint len)
+ : current_(0), buffer_(new (ys) byte[s]), end_(buffer_+ s)
+{
+ write(t, len);
+}
+
+
+output_buffer::~output_buffer()
+{
+ delete [] buffer_;
+}
+
+
+uint output_buffer::get_size() const
+{
+ return current_;
+}
+
+
+uint output_buffer::get_capacity() const
+{
+ return end_ - buffer_;
+}
+
+
+void output_buffer::set_current(uint c)
+{
+ check(c, get_capacity());
+ current_ = c;
+}
+
+
+// users can pass defualt zero length buffer and then allocate
+void output_buffer::allocate(uint s)
+{
+ assert(!buffer_); // find realloc error
+ buffer_ = new (ys) byte[s]; end_ = buffer_ + s;
+}
+
+
+// for passing to reading functions when finished
+const byte* output_buffer::get_buffer() const
+{
+ return buffer_;
+}
+
+
+// allow write access through [], update current
+// user passes in AUTO as index for ease of use
+byte& output_buffer::operator[](uint i)
+{
+ assert(i == AUTO);
+ check(current_, get_capacity());
+ return buffer_[current_++];
+}
+
+
+// end of output test
+bool output_buffer::eof()
+{
+ return current_ >= get_capacity();
+}
+
+
+void output_buffer::write(const byte* t, uint s)
+{
+ check(current_ + s - 1, get_capacity());
+ memcpy(&buffer_[current_], t, s);
+ current_ += s;
+}
+
+
+
+} // naemspace
+
diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp
new file mode 100644
index 00000000000..ab3cb471990
--- /dev/null
+++ b/extra/yassl/src/cert_wrapper.cpp
@@ -0,0 +1,318 @@
+/* cert_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The certificate wrapper source implements certificate management functions
+ *
+ */
+
+#include "runtime.hpp"
+#include "cert_wrapper.hpp"
+#include "yassl_int.hpp"
+
+#if defined(USE_CML_LIB)
+ #include "cmapi_cpp.h"
+#else
+ #include "asn.hpp"
+ #include "file.hpp"
+#endif // USE_CML_LIB
+
+
+namespace yaSSL {
+
+
+x509::x509(uint sz) : length_(sz), buffer_(new (ys) opaque[sz])
+{
+}
+
+
+x509::~x509()
+{
+ delete [] buffer_;
+}
+
+
+x509::x509(const x509& that) : length_(that.length_),
+ buffer_(new (ys) opaque[length_])
+{
+ memcpy(buffer_, that.buffer_, length_);
+}
+
+
+void x509::Swap(x509& that)
+{
+ mySTL::swap(length_, that.length_);
+ mySTL::swap(buffer_, that.buffer_);
+}
+
+
+x509& x509::operator=(const x509& that)
+{
+ x509 temp(that);
+ Swap(temp);
+ return *this;
+}
+
+
+uint x509::get_length() const
+{
+ return length_;
+}
+
+
+const opaque* x509::get_buffer() const
+{
+ return buffer_;
+}
+
+
+opaque* x509::use_buffer()
+{
+ return buffer_;
+}
+
+
+//CertManager
+CertManager::CertManager()
+ : peerX509_(0), verifyPeer_(false), failNoCert_(false), sendVerify_(false)
+{}
+
+
+CertManager::~CertManager()
+{
+ delete peerX509_;
+
+ mySTL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ;
+
+ mySTL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ;
+
+ mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ;
+}
+
+
+bool CertManager::verifyPeer() const
+{
+ return verifyPeer_;
+}
+
+
+bool CertManager::failNoCert() const
+{
+ return failNoCert_;
+}
+
+
+bool CertManager::sendVerify() const
+{
+ return sendVerify_;
+}
+
+
+void CertManager::setVerifyPeer()
+{
+ verifyPeer_ = true;
+}
+
+
+void CertManager::setFailNoCert()
+{
+ failNoCert_ = true;
+}
+
+
+void CertManager::setSendVerify()
+{
+ sendVerify_ = true;
+}
+
+
+void CertManager::AddPeerCert(x509* x)
+{
+ peerList_.push_back(x); // take ownership
+}
+
+
+void CertManager::CopySelfCert(const x509* x)
+{
+ if (x)
+ list_.push_back(new (ys) x509(*x));
+}
+
+
+// add to signers
+int CertManager::CopyCaCert(const x509* x)
+{
+ TaoCrypt::Source source(x->get_buffer(), x->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (!cert.GetError().What()) {
+ const TaoCrypt::PublicKey& key = cert.GetPublicKey();
+ signers_.push_back(new (ys) TaoCrypt::Signer(key.GetKey(), key.size(),
+ cert.GetCommonName(), cert.GetHash()));
+ }
+ return cert.GetError().What();
+}
+
+
+const x509* CertManager::get_cert() const
+{
+ return list_.front();
+}
+
+
+const opaque* CertManager::get_peerKey() const
+{
+ return peerPublicKey_.get_buffer();
+}
+
+
+X509* CertManager::get_peerX509() const
+{
+ return peerX509_;
+}
+
+
+SignatureAlgorithm CertManager::get_peerKeyType() const
+{
+ return peerKeyType_;
+}
+
+
+SignatureAlgorithm CertManager::get_keyType() const
+{
+ return keyType_;
+}
+
+
+uint CertManager::get_peerKeyLength() const
+{
+ return peerPublicKey_.get_size();
+}
+
+
+const opaque* CertManager::get_privateKey() const
+{
+ return privateKey_.get_buffer();
+}
+
+
+uint CertManager::get_privateKeyLength() const
+{
+ return privateKey_.get_size();
+}
+
+
+// Validate the peer's certificate list, from root to peer (last to first)
+int CertManager::Validate()
+{
+ CertList::iterator last = peerList_.rbegin(); // fix this
+ int count = peerList_.size();
+
+ while ( count > 1 ) {
+ TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (int err = cert.GetError().What())
+ return err;
+
+ const TaoCrypt::PublicKey& key = cert.GetPublicKey();
+ signers_.push_back(new (ys) TaoCrypt::Signer(key.GetKey(), key.size(),
+ cert.GetCommonName(), cert.GetHash()));
+ --last;
+ --count;
+ }
+
+ if (count) {
+ // peer's is at the front
+ TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers_);
+
+ if (int err = cert.GetError().What())
+ return err;
+
+ uint sz = cert.GetPublicKey().size();
+ peerPublicKey_.allocate(sz);
+ peerPublicKey_.assign(cert.GetPublicKey().GetKey(), sz);
+
+ if (cert.GetKeyType() == TaoCrypt::RSAk)
+ peerKeyType_ = rsa_sa_algo;
+ else
+ peerKeyType_ = dsa_sa_algo;
+
+ int iSz = cert.GetIssuer() ? strlen(cert.GetIssuer()) + 1 : 0;
+ int sSz = cert.GetCommonName() ? strlen(cert.GetCommonName()) + 1 : 0;
+ peerX509_ = new (ys) X509(cert.GetIssuer(), iSz, cert.GetCommonName(),
+ sSz);
+ }
+ return 0;
+}
+
+
+// Set the private key
+int CertManager::SetPrivateKey(const x509& key)
+{
+ privateKey_.allocate(key.get_length());
+ privateKey_.assign(key.get_buffer(), key.get_length());
+
+ // set key type
+ if (x509* cert = list_.front()) {
+ TaoCrypt::Source source(cert->get_buffer(), cert->get_length());
+ TaoCrypt::CertDecoder cert(source, false);
+ cert.DecodeToKey();
+ if (int err = cert.GetError().What())
+ return err;
+ if (cert.GetKeyType() == TaoCrypt::RSAk)
+ keyType_ = rsa_sa_algo;
+ else
+ keyType_ = dsa_sa_algo;
+ }
+ return 0;
+}
+
+
+#if defined(USE_CML_LIB)
+
+// Get the peer's certificate, extract and save public key
+void CertManager::SetPeerKey()
+{
+ // first cert is the peer's
+ x509* main = peerList_.front();
+
+ Bytes_struct cert;
+ cert.num = main->get_length();
+ cert.data = main->set_buffer();
+
+ CML::Certificate cm(cert);
+ const CML::ASN::Cert& raw = cm.base();
+ CTIL::CSM_Buffer key = raw.pubKeyInfo.key;
+
+ uint sz;
+ opaque* key_buffer = reinterpret_cast<opaque*>(key.Get(sz));
+ peerPublicKey_.allocate(sz);
+ peerPublicKey_.assign(key_buffer, sz);
+}
+
+
+#endif // USE_CML_LIB
+
+
+
+} // namespace
diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp
new file mode 100644
index 00000000000..72822430a51
--- /dev/null
+++ b/extra/yassl/src/crypto_wrapper.cpp
@@ -0,0 +1,970 @@
+/* crypto_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* The crypto wrapper source implements the policies for the cipher
+ * components used by SSL.
+ *
+ * The implementation relies on a specfic library, taoCrypt.
+ */
+
+#if !defined(USE_CRYPTOPP_LIB)
+
+#include "runtime.hpp"
+#include "crypto_wrapper.hpp"
+#include "cert_wrapper.hpp"
+
+#include "md5.hpp"
+#include "sha.hpp"
+#include "ripemd.hpp"
+#include "hmac.hpp"
+#include "modes.hpp"
+#include "des.hpp"
+#include "arc4.hpp"
+#include "aes.hpp"
+#include "rsa.hpp"
+#include "dsa.hpp"
+#include "dh.hpp"
+#include "random.hpp"
+#include "file.hpp"
+#include "coding.hpp"
+
+
+namespace yaSSL {
+
+
+// MD5 Implementation
+struct MD5::MD5Impl {
+ TaoCrypt::MD5 md5_;
+ MD5Impl() {}
+ explicit MD5Impl(const TaoCrypt::MD5& md5) : md5_(md5) {}
+};
+
+
+MD5::MD5() : pimpl_(new (ys) MD5Impl) {}
+
+
+MD5::~MD5() { delete pimpl_; }
+
+
+MD5::MD5(const MD5& that) : Digest(), pimpl_(new (ys)
+ MD5Impl(that.pimpl_->md5_)) {}
+
+
+MD5& MD5::operator=(const MD5& that)
+{
+ pimpl_->md5_ = that.pimpl_->md5_;
+ return *this;
+}
+
+
+uint MD5::get_digestSize() const
+{
+ return MD5_LEN;
+}
+
+
+uint MD5::get_padSize() const
+{
+ return PAD_MD5;
+}
+
+
+// Fill out with MD5 digest from in that is sz bytes, out must be >= digest sz
+void MD5::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->md5_.Update(in, sz);
+ pimpl_->md5_.Final(out);
+}
+
+// Fill out with MD5 digest from previous updates
+void MD5::get_digest(byte* out)
+{
+ pimpl_->md5_.Final(out);
+}
+
+
+// Update the current digest
+void MD5::update(const byte* in, unsigned int sz)
+{
+ pimpl_->md5_.Update(in, sz);
+}
+
+
+// SHA Implementation
+struct SHA::SHAImpl {
+ TaoCrypt::SHA sha_;
+ SHAImpl() {}
+ explicit SHAImpl(const TaoCrypt::SHA& sha) : sha_(sha) {}
+};
+
+
+SHA::SHA() : pimpl_(new (ys) SHAImpl) {}
+
+
+SHA::~SHA() { delete pimpl_; }
+
+
+SHA::SHA(const SHA& that) : Digest(), pimpl_(new (ys)
+ SHAImpl(that.pimpl_->sha_)) {}
+
+SHA& SHA::operator=(const SHA& that)
+{
+ pimpl_->sha_ = that.pimpl_->sha_;
+ return *this;
+}
+
+
+uint SHA::get_digestSize() const
+{
+ return SHA_LEN;
+}
+
+
+uint SHA::get_padSize() const
+{
+ return PAD_SHA;
+}
+
+
+// Fill out with SHA digest from in that is sz bytes, out must be >= digest sz
+void SHA::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->sha_.Update(in, sz);
+ pimpl_->sha_.Final(out);
+}
+
+
+// Fill out with SHA digest from previous updates
+void SHA::get_digest(byte* out)
+{
+ pimpl_->sha_.Final(out);
+}
+
+
+// Update the current digest
+void SHA::update(const byte* in, unsigned int sz)
+{
+ pimpl_->sha_.Update(in, sz);
+}
+
+
+// RMD-160 Implementation
+struct RMD::RMDImpl {
+ TaoCrypt::RIPEMD160 rmd_;
+ RMDImpl() {}
+ explicit RMDImpl(const TaoCrypt::RIPEMD160& rmd) : rmd_(rmd) {}
+};
+
+
+RMD::RMD() : pimpl_(new (ys) RMDImpl) {}
+
+
+RMD::~RMD() { delete pimpl_; }
+
+
+RMD::RMD(const RMD& that) : Digest(), pimpl_(new (ys)
+ RMDImpl(that.pimpl_->rmd_)) {}
+
+RMD& RMD::operator=(const RMD& that)
+{
+ pimpl_->rmd_ = that.pimpl_->rmd_;
+ return *this;
+}
+
+
+uint RMD::get_digestSize() const
+{
+ return RMD_LEN;
+}
+
+
+uint RMD::get_padSize() const
+{
+ return PAD_RMD;
+}
+
+
+// Fill out with RMD digest from in that is sz bytes, out must be >= digest sz
+void RMD::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->rmd_.Update(in, sz);
+ pimpl_->rmd_.Final(out);
+}
+
+
+// Fill out with RMD digest from previous updates
+void RMD::get_digest(byte* out)
+{
+ pimpl_->rmd_.Final(out);
+}
+
+
+// Update the current digest
+void RMD::update(const byte* in, unsigned int sz)
+{
+ pimpl_->rmd_.Update(in, sz);
+}
+
+
+// HMAC_MD5 Implementation
+struct HMAC_MD5::HMAC_MD5Impl {
+ TaoCrypt::HMAC<TaoCrypt::MD5> mac_;
+ HMAC_MD5Impl() {}
+};
+
+
+HMAC_MD5::HMAC_MD5(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_MD5Impl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_MD5::~HMAC_MD5() { delete pimpl_; }
+
+
+uint HMAC_MD5::get_digestSize() const
+{
+ return MD5_LEN;
+}
+
+
+uint HMAC_MD5::get_padSize() const
+{
+ return PAD_MD5;
+}
+
+
+// Fill out with MD5 digest from in that is sz bytes, out must be >= digest sz
+void HMAC_MD5::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with MD5 digest from previous updates
+void HMAC_MD5::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_MD5::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+// HMAC_SHA Implementation
+struct HMAC_SHA::HMAC_SHAImpl {
+ TaoCrypt::HMAC<TaoCrypt::SHA> mac_;
+ HMAC_SHAImpl() {}
+};
+
+
+HMAC_SHA::HMAC_SHA(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_SHAImpl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_SHA::~HMAC_SHA() { delete pimpl_; }
+
+
+uint HMAC_SHA::get_digestSize() const
+{
+ return SHA_LEN;
+}
+
+
+uint HMAC_SHA::get_padSize() const
+{
+ return PAD_SHA;
+}
+
+
+// Fill out with SHA digest from in that is sz bytes, out must be >= digest sz
+void HMAC_SHA::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with SHA digest from previous updates
+void HMAC_SHA::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_SHA::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+
+// HMAC_RMD Implementation
+struct HMAC_RMD::HMAC_RMDImpl {
+ TaoCrypt::HMAC<TaoCrypt::RIPEMD160> mac_;
+ HMAC_RMDImpl() {}
+};
+
+
+HMAC_RMD::HMAC_RMD(const byte* secret, unsigned int len)
+ : pimpl_(new (ys) HMAC_RMDImpl)
+{
+ pimpl_->mac_.SetKey(secret, len);
+}
+
+
+HMAC_RMD::~HMAC_RMD() { delete pimpl_; }
+
+
+uint HMAC_RMD::get_digestSize() const
+{
+ return RMD_LEN;
+}
+
+
+uint HMAC_RMD::get_padSize() const
+{
+ return PAD_RMD;
+}
+
+
+// Fill out with RMD digest from in that is sz bytes, out must be >= digest sz
+void HMAC_RMD::get_digest(byte* out, const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+ pimpl_->mac_.Final(out);
+}
+
+// Fill out with RMD digest from previous updates
+void HMAC_RMD::get_digest(byte* out)
+{
+ pimpl_->mac_.Final(out);
+}
+
+
+// Update the current digest
+void HMAC_RMD::update(const byte* in, unsigned int sz)
+{
+ pimpl_->mac_.Update(in, sz);
+}
+
+
+struct DES::DESImpl {
+ TaoCrypt::DES_CBC_Encryption encryption;
+ TaoCrypt::DES_CBC_Decryption decryption;
+};
+
+
+DES::DES() : pimpl_(new (ys) DESImpl) {}
+
+DES::~DES() { delete pimpl_; }
+
+
+void DES::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, DES_KEY_SZ, iv);
+}
+
+
+void DES::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, DES_KEY_SZ, iv);
+}
+
+// DES encrypt plain of length sz into cipher
+void DES::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// DES decrypt cipher of length sz into plain
+void DES::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+struct DES_EDE::DES_EDEImpl {
+ TaoCrypt::DES_EDE3_CBC_Encryption encryption;
+ TaoCrypt::DES_EDE3_CBC_Decryption decryption;
+};
+
+
+DES_EDE::DES_EDE() : pimpl_(new (ys) DES_EDEImpl) {}
+
+DES_EDE::~DES_EDE() { delete pimpl_; }
+
+
+void DES_EDE::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, DES_EDE_KEY_SZ, iv);
+}
+
+
+void DES_EDE::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, DES_EDE_KEY_SZ, iv);
+}
+
+
+// 3DES encrypt plain of length sz into cipher
+void DES_EDE::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// 3DES decrypt cipher of length sz into plain
+void DES_EDE::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+// Implementation of alledged RC4
+struct RC4::RC4Impl {
+ TaoCrypt::ARC4::Encryption encryption;
+ TaoCrypt::ARC4::Decryption decryption;
+};
+
+
+RC4::RC4() : pimpl_(new (ys) RC4Impl) {}
+
+RC4::~RC4() { delete pimpl_; }
+
+
+void RC4::set_encryptKey(const byte* k, const byte*)
+{
+ pimpl_->encryption.SetKey(k, RC4_KEY_SZ);
+}
+
+
+void RC4::set_decryptKey(const byte* k, const byte*)
+{
+ pimpl_->decryption.SetKey(k, RC4_KEY_SZ);
+}
+
+
+// RC4 encrypt plain of length sz into cipher
+void RC4::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// RC4 decrypt cipher of length sz into plain
+void RC4::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+
+// Implementation of AES
+struct AES::AESImpl {
+ TaoCrypt::AES_CBC_Encryption encryption;
+ TaoCrypt::AES_CBC_Decryption decryption;
+ unsigned int keySz_;
+
+ AESImpl(unsigned int ks) : keySz_(ks) {}
+};
+
+
+AES::AES(unsigned int ks) : pimpl_(new (ys) AESImpl(ks)) {}
+
+AES::~AES() { delete pimpl_; }
+
+
+int AES::get_keySize() const
+{
+ return pimpl_->keySz_;
+}
+
+
+void AES::set_encryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->encryption.SetKey(k, pimpl_->keySz_, iv);
+}
+
+
+void AES::set_decryptKey(const byte* k, const byte* iv)
+{
+ pimpl_->decryption.SetKey(k, pimpl_->keySz_, iv);
+}
+
+
+// AES encrypt plain of length sz into cipher
+void AES::encrypt(byte* cipher, const byte* plain, unsigned int sz)
+{
+ pimpl_->encryption.Process(cipher, plain, sz);
+}
+
+
+// AES decrypt cipher of length sz into plain
+void AES::decrypt(byte* plain, const byte* cipher, unsigned int sz)
+{
+ pimpl_->decryption.Process(plain, cipher, sz);
+}
+
+
+struct RandomPool::RandomImpl {
+ TaoCrypt::RandomNumberGenerator RNG_;
+};
+
+RandomPool::RandomPool() : pimpl_(new (ys) RandomImpl) {}
+
+RandomPool::~RandomPool() { delete pimpl_; }
+
+int RandomPool::GetError() const
+{
+ return pimpl_->RNG_.GetError();
+}
+
+void RandomPool::Fill(opaque* dst, uint sz) const
+{
+ pimpl_->RNG_.GenerateBlock(dst, sz);
+}
+
+
+// Implementation of DSS Authentication
+struct DSS::DSSImpl {
+ void SetPublic (const byte*, unsigned int);
+ void SetPrivate(const byte*, unsigned int);
+ TaoCrypt::DSA_PublicKey publicKey_;
+ TaoCrypt::DSA_PrivateKey privateKey_;
+};
+
+
+// Decode and store the public key
+void DSS::DSSImpl::SetPublic(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ publicKey_.Initialize(source);
+}
+
+
+// Decode and store the public key
+void DSS::DSSImpl::SetPrivate(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ privateKey_.Initialize(source);
+ publicKey_ = TaoCrypt::DSA_PublicKey(privateKey_);
+
+}
+
+
+// Set public or private key
+DSS::DSS(const byte* key, unsigned int sz, bool publicKey)
+ : pimpl_(new (ys) DSSImpl)
+{
+ if (publicKey)
+ pimpl_->SetPublic(key, sz);
+ else
+ pimpl_->SetPrivate(key, sz);
+}
+
+
+DSS::~DSS()
+{
+ delete pimpl_;
+}
+
+
+uint DSS::get_signatureLength() const
+{
+ return pimpl_->publicKey_.SignatureLength();
+}
+
+
+// DSS Sign message of length sz into sig
+void DSS::sign(byte* sig, const byte* sha_digest, unsigned int /* shaSz */,
+ const RandomPool& random)
+{
+ using namespace TaoCrypt;
+
+ DSA_Signer signer(pimpl_->privateKey_);
+ signer.Sign(sha_digest, sig, random.pimpl_->RNG_);
+}
+
+
+// DSS Verify message of length sz against sig, is it correct?
+bool DSS::verify(const byte* sha_digest, unsigned int /* shaSz */,
+ const byte* sig, unsigned int /* sigSz */)
+{
+ using namespace TaoCrypt;
+
+ DSA_Verifier ver(pimpl_->publicKey_);
+ return ver.Verify(sha_digest, sig);
+}
+
+
+// Implementation of RSA key interface
+struct RSA::RSAImpl {
+ void SetPublic (const byte*, unsigned int);
+ void SetPrivate(const byte*, unsigned int);
+ TaoCrypt::RSA_PublicKey publicKey_;
+ TaoCrypt::RSA_PrivateKey privateKey_;
+};
+
+
+// Decode and store the public key
+void RSA::RSAImpl::SetPublic(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ publicKey_.Initialize(source);
+}
+
+
+// Decode and store the private key
+void RSA::RSAImpl::SetPrivate(const byte* key, unsigned int sz)
+{
+ TaoCrypt::Source source(key, sz);
+ privateKey_.Initialize(source);
+ publicKey_ = TaoCrypt::RSA_PublicKey(privateKey_);
+}
+
+
+// Set public or private key
+RSA::RSA(const byte* key, unsigned int sz, bool publicKey)
+ : pimpl_(new (ys) RSAImpl)
+{
+ if (publicKey)
+ pimpl_->SetPublic(key, sz);
+ else
+ pimpl_->SetPrivate(key, sz);
+}
+
+RSA::~RSA()
+{
+ delete pimpl_;
+}
+
+
+// get cipher text length, varies on key size
+unsigned int RSA::get_cipherLength() const
+{
+ return pimpl_->publicKey_.FixedCiphertextLength();
+}
+
+
+// get signautre length, varies on key size
+unsigned int RSA::get_signatureLength() const
+{
+ return get_cipherLength();
+}
+
+
+// RSA Sign message of length sz into sig
+void RSA::sign(byte* sig, const byte* message, unsigned int sz,
+ const RandomPool& random)
+{
+ TaoCrypt::RSAES_Decryptor dec(pimpl_->privateKey_);
+ dec.SSL_Sign(message, sz, sig, random.pimpl_->RNG_);
+}
+
+
+// RSA Verify message of length sz against sig
+bool RSA::verify(const byte* message, unsigned int sz, const byte* sig,
+ unsigned int)
+{
+ TaoCrypt::RSAES_Encryptor enc(pimpl_->publicKey_);
+ return enc.SSL_Verify(message, sz, sig);
+}
+
+
+// RSA public encrypt plain of length sz into cipher
+void RSA::encrypt(byte* cipher, const byte* plain, unsigned int sz,
+ const RandomPool& random)
+{
+
+ TaoCrypt::RSAES_Encryptor enc(pimpl_->publicKey_);
+ enc.Encrypt(plain, sz, cipher, random.pimpl_->RNG_);
+}
+
+
+// RSA private decrypt cipher of length sz into plain
+void RSA::decrypt(byte* plain, const byte* cipher, unsigned int sz,
+ const RandomPool& random)
+{
+ TaoCrypt::RSAES_Decryptor dec(pimpl_->privateKey_);
+ dec.Decrypt(cipher, sz, plain, random.pimpl_->RNG_);
+}
+
+
+struct Integer::IntegerImpl {
+ TaoCrypt::Integer int_;
+
+ IntegerImpl() {}
+ explicit IntegerImpl(const TaoCrypt::Integer& i) : int_(i) {}
+};
+
+Integer::Integer() : pimpl_(new (ys) IntegerImpl) {}
+
+Integer::~Integer() { delete pimpl_; }
+
+
+
+Integer::Integer(const Integer& other) : pimpl_(new (ys)
+ IntegerImpl(other.pimpl_->int_))
+{}
+
+
+Integer& Integer::operator=(const Integer& that)
+{
+ pimpl_->int_ = that.pimpl_->int_;
+
+ return *this;
+}
+
+
+void Integer::assign(const byte* num, unsigned int sz)
+{
+ pimpl_->int_ = TaoCrypt::Integer(num, sz);
+}
+
+
+struct DiffieHellman::DHImpl {
+ TaoCrypt::DH dh_;
+ TaoCrypt::RandomNumberGenerator& ranPool_;
+ byte* publicKey_;
+ byte* privateKey_;
+ byte* agreedKey_;
+
+ DHImpl(TaoCrypt::RandomNumberGenerator& r) : ranPool_(r), publicKey_(0),
+ privateKey_(0), agreedKey_(0) {}
+ ~DHImpl() {delete[] agreedKey_; delete[] privateKey_; delete[] publicKey_;}
+
+ DHImpl(const DHImpl& that) : dh_(that.dh_), ranPool_(that.ranPool_),
+ publicKey_(0), privateKey_(0), agreedKey_(0)
+ {
+ uint length = dh_.GetByteLength();
+ AllocKeys(length, length, length);
+ }
+
+ void AllocKeys(unsigned int pubSz, unsigned int privSz, unsigned int agrSz)
+ {
+ publicKey_ = new (ys) byte[pubSz];
+ privateKey_ = new (ys) byte[privSz];
+ agreedKey_ = new (ys) byte[agrSz];
+ }
+};
+
+
+
+/*
+// server Side DH, server's view
+DiffieHellman::DiffieHellman(const char* file, const RandomPool& random)
+ : pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using namespace TaoCrypt;
+ Source source;
+ FileSource(file, source);
+ if (source.size() == 0)
+ return; // TODO add error state, and force check
+ HexDecoder hd(source);
+
+ pimpl_->dh_.Initialize(source);
+
+ uint length = pimpl_->dh_.GetByteLength();
+
+ pimpl_->AllocKeys(length, length, length);
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+*/
+
+
+// server Side DH, client's view
+DiffieHellman::DiffieHellman(const byte* p, unsigned int pSz, const byte* g,
+ unsigned int gSz, const byte* pub,
+ unsigned int pubSz, const RandomPool& random)
+ : pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using TaoCrypt::Integer;
+
+ pimpl_->dh_.Initialize(Integer(p, pSz).Ref(), Integer(g, gSz).Ref());
+ pimpl_->publicKey_ = new (ys) opaque[pubSz];
+ memcpy(pimpl_->publicKey_, pub, pubSz);
+}
+
+
+// Server Side DH, server's view
+DiffieHellman::DiffieHellman(const Integer& p, const Integer& g,
+ const RandomPool& random)
+: pimpl_(new (ys) DHImpl(random.pimpl_->RNG_))
+{
+ using TaoCrypt::Integer;
+
+ pimpl_->dh_.Initialize(p.pimpl_->int_, g.pimpl_->int_);
+
+ uint length = pimpl_->dh_.GetByteLength();
+
+ pimpl_->AllocKeys(length, length, length);
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+
+DiffieHellman::~DiffieHellman() { delete pimpl_; }
+
+
+// Client side and view, use server that for p and g
+DiffieHellman::DiffieHellman(const DiffieHellman& that)
+ : pimpl_(new (ys) DHImpl(*that.pimpl_))
+{
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+}
+
+
+DiffieHellman& DiffieHellman::operator=(const DiffieHellman& that)
+{
+ pimpl_->dh_ = that.pimpl_->dh_;
+ pimpl_->dh_.GenerateKeyPair(pimpl_->ranPool_, pimpl_->privateKey_,
+ pimpl_->publicKey_);
+ return *this;
+}
+
+
+void DiffieHellman::makeAgreement(const byte* other)
+{
+ pimpl_->dh_.Agree(pimpl_->agreedKey_, pimpl_->privateKey_, other);
+}
+
+
+uint DiffieHellman::get_agreedKeyLength() const
+{
+ return pimpl_->dh_.GetByteLength();
+}
+
+
+const byte* DiffieHellman::get_agreedKey() const
+{
+ return pimpl_->agreedKey_;
+}
+
+
+const byte* DiffieHellman::get_publicKey() const
+{
+ return pimpl_->publicKey_;
+}
+
+
+void DiffieHellman::set_sizes(int& pSz, int& gSz, int& pubSz) const
+{
+ using TaoCrypt::Integer;
+ Integer p = pimpl_->dh_.GetP();
+ Integer g = pimpl_->dh_.GetG();
+
+ pSz = p.ByteCount();
+ gSz = g.ByteCount();
+ pubSz = pimpl_->dh_.GetByteLength();
+}
+
+
+void DiffieHellman::get_parms(byte* bp, byte* bg, byte* bpub) const
+{
+ using TaoCrypt::Integer;
+ Integer p = pimpl_->dh_.GetP();
+ Integer g = pimpl_->dh_.GetG();
+
+ p.Encode(bp, p.ByteCount());
+ g.Encode(bg, g.ByteCount());
+ memcpy(bpub, pimpl_->publicKey_, pimpl_->dh_.GetByteLength());
+}
+
+
+// convert PEM file to DER x509 type
+x509* PemToDer(const char* fname, CertType type)
+{
+ using namespace TaoCrypt;
+
+ char header[80];
+ char footer[80];
+
+ if (type == Cert) {
+ strncpy(header, "-----BEGIN CERTIFICATE-----", sizeof(header));
+ strncpy(footer, "-----END CERTIFICATE-----", sizeof(footer));
+ } else {
+ strncpy(header, "-----BEGIN RSA PRIVATE KEY-----", sizeof(header));
+ strncpy(footer, "-----END RSA PRIVATE KEY-----", sizeof(header));
+ }
+
+ FILE* file = fopen(fname, "rb");
+ if (!file)
+ return 0;
+
+ long begin = -1;
+ long end = 0;
+ bool foundEnd = false;
+
+ char line[80];
+
+ while(fgets(line, sizeof(line), file))
+ if (strncmp(header, line, strlen(header)) == 0) {
+ begin = ftell(file);
+ break;
+ }
+
+ while(fgets(line, sizeof(line), file))
+ if (strncmp(footer, line, strlen(footer)) == 0) {
+ foundEnd = true;
+ break;
+ }
+ else
+ end = ftell(file);
+
+ if (begin == -1 || !foundEnd) {
+ fclose(file);
+ return 0;
+ }
+
+ input_buffer tmp(end - begin);
+ fseek(file, begin, SEEK_SET);
+ size_t bytes = fread(tmp.get_buffer(), end - begin, 1, file);
+ if (bytes != 1) {
+ fclose(file);
+ return 0;
+ }
+
+ Source der(tmp.get_buffer(), end - begin);
+ Base64Decoder b64Dec(der);
+
+ uint sz = der.size();
+ mySTL::auto_ptr<x509> x(new (ys) x509(sz));
+ memcpy(x->use_buffer(), der.get_buffer(), sz);
+
+ fclose(file);
+ return x.release();
+}
+
+
+} // namespace
+
+#endif // !USE_CRYPTOPP_LIB
diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp
new file mode 100644
index 00000000000..35c4cbd4922
--- /dev/null
+++ b/extra/yassl/src/handshake.cpp
@@ -0,0 +1,1011 @@
+/* handshake.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The handshake source implements functions for creating and reading
+ * the various handshake messages.
+ */
+
+#include "runtime.hpp"
+#include "handshake.hpp"
+#include "yassl_int.hpp"
+
+
+namespace yaSSL {
+
+using mySTL::min;
+
+
+// Build a client hello message from cipher suites and compression method
+void buildClientHello(SSL& ssl, ClientHello& hello,
+ CompressionMethod compression = no_compression)
+{
+ ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
+ if (ssl.getSecurity().get_resuming()) {
+ hello.id_len_ = ID_LEN;
+ memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN);
+ }
+ else
+ hello.id_len_ = 0;
+ hello.suite_len_ = ssl.getSecurity().get_parms().suites_size_;
+ memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_,
+ hello.suite_len_);
+ hello.comp_len_ = 1;
+ hello.compression_methods_ = compression;
+
+ hello.set_length(sizeof(ProtocolVersion) +
+ RAN_LEN +
+ hello.id_len_ + sizeof(hello.id_len_) +
+ hello.suite_len_ + sizeof(hello.suite_len_) +
+ hello.comp_len_ + sizeof(hello.comp_len_));
+}
+
+
+// Build a server hello message
+void buildServerHello(SSL& ssl, ServerHello& hello)
+{
+ if (ssl.getSecurity().get_resuming()) {
+ memcpy(hello.random_,ssl.getSecurity().get_connection().server_random_,
+ RAN_LEN);
+ memcpy(hello.session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN);
+ }
+ else {
+ ssl.getCrypto().get_random().Fill(hello.random_, RAN_LEN);
+ ssl.getCrypto().get_random().Fill(hello.session_id_, ID_LEN);
+ }
+ hello.id_len_ = ID_LEN;
+ ssl.set_sessionID(hello.session_id_);
+
+ hello.cipher_suite_[0] = ssl.getSecurity().get_parms().suite_[0];
+ hello.cipher_suite_[1] = ssl.getSecurity().get_parms().suite_[1];
+ hello.compression_method_ = no_compression;
+
+ hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + ID_LEN +
+ sizeof(hello.id_len_) + SUITE_LEN + SIZEOF_ENUM);
+}
+
+
+// add handshake from buffer into md5 and sha hashes, use handshake header
+void hashHandShake(SSL& ssl, const input_buffer& input, uint sz)
+{
+ const opaque* buffer = input.get_buffer() + input.get_current() -
+ HANDSHAKE_HEADER;
+ sz += HANDSHAKE_HEADER;
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+}
+
+
+// locals
+namespace {
+
+// Write a plaintext record to buffer
+void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr,
+ const Message& msg)
+{
+ buffer.allocate(RECORD_HEADER + rlHdr.length_);
+ buffer << rlHdr << msg;
+}
+
+
+// Write a plaintext record to buffer
+void buildOutput(output_buffer& buffer, const RecordLayerHeader& rlHdr,
+ const HandShakeHeader& hsHdr, const HandShakeBase& shake)
+{
+ buffer.allocate(RECORD_HEADER + rlHdr.length_);
+ buffer << rlHdr << hsHdr << shake;
+}
+
+
+// Build Record Layer header for Message without handshake header
+void buildHeader(SSL& ssl, RecordLayerHeader& rlHeader, const Message& msg)
+{
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ rlHeader.type_ = msg.get_type();
+ rlHeader.version_.major_ = pv.major_;
+ rlHeader.version_.minor_ = pv.minor_;
+ rlHeader.length_ = msg.get_length();
+}
+
+
+// Build HandShake and RecordLayer Headers for handshake output
+void buildHeaders(SSL& ssl, HandShakeHeader& hsHeader,
+ RecordLayerHeader& rlHeader, const HandShakeBase& shake)
+{
+ int sz = shake.get_length();
+
+ hsHeader.set_type(shake.get_type());
+ hsHeader.set_length(sz);
+
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ rlHeader.type_ = handshake;
+ rlHeader.version_.major_ = pv.major_;
+ rlHeader.version_.minor_ = pv.minor_;
+ rlHeader.length_ = sz + HANDSHAKE_HEADER;
+}
+
+
+// add handshake from buffer into md5 and sha hashes, exclude record header
+void hashHandShake(SSL& ssl, const output_buffer& output)
+{
+ uint sz = output.get_size() - RECORD_HEADER;
+
+ const opaque* buffer = output.get_buffer() + RECORD_HEADER;
+
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+}
+
+
+// calculate MD5 hash for finished
+void buildMD5(SSL& ssl, Finished& fin, const opaque* sender)
+{
+
+ opaque md5_result[MD5_LEN];
+ opaque md5_inner[SIZEOF_SENDER + SECRET_LEN + PAD_MD5];
+ opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make md5 inner
+ memcpy(md5_inner, sender, SIZEOF_SENDER);
+ memcpy(&md5_inner[SIZEOF_SENDER], master_secret, SECRET_LEN);
+ memcpy(&md5_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_MD5);
+
+ ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
+ sizeof(md5_inner));
+
+ // make md5 outer
+ memcpy(md5_outer, master_secret, SECRET_LEN);
+ memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
+ memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
+
+ ssl.useHashes().use_MD5().get_digest(fin.set_md5(), md5_outer,
+ sizeof(md5_outer));
+}
+
+
+// calculate SHA hash for finished
+void buildSHA(SSL& ssl, Finished& fin, const opaque* sender)
+{
+
+ opaque sha_result[SHA_LEN];
+ opaque sha_inner[SIZEOF_SENDER + SECRET_LEN + PAD_SHA];
+ opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make sha inner
+ memcpy(sha_inner, sender, SIZEOF_SENDER);
+ memcpy(&sha_inner[SIZEOF_SENDER], master_secret, SECRET_LEN);
+ memcpy(&sha_inner[SIZEOF_SENDER + SECRET_LEN], PAD1, PAD_SHA);
+
+ ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
+ sizeof(sha_inner));
+
+ // make sha outer
+ memcpy(sha_outer, master_secret, SECRET_LEN);
+ memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
+ memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
+
+ ssl.useHashes().use_SHA().get_digest(fin.set_sha(), sha_outer,
+ sizeof(sha_outer));
+}
+
+
+// decrypt input message in place, store size in case needed later
+void decrypt_message(SSL& ssl, input_buffer& input, uint sz)
+{
+ input_buffer plain(sz);
+ opaque* cipher = input.get_buffer() + input.get_current();
+
+ ssl.useCrypto().use_cipher().decrypt(plain.get_buffer(), cipher, sz);
+ memcpy(cipher, plain.get_buffer(), sz);
+ ssl.useSecurity().use_parms().encrypt_size_ = sz;
+}
+
+
+// write headers, handshake hash, mac, pad, and encrypt
+void cipherFinished(SSL& ssl, Finished& fin, output_buffer& output)
+{
+ uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ;
+ uint sz = RECORD_HEADER + HANDSHAKE_HEADER + finishedSz + digestSz;
+ uint pad = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ sz += 1; // pad byte
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+ pad = (sz - RECORD_HEADER) % blockSz;
+ pad = blockSz - pad;
+ sz += pad;
+ }
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ buildHeaders(ssl, hsHeader, rlHeader, fin);
+ rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
+ // and pad, hanshake doesn't
+ output.allocate(sz);
+ output << rlHeader << hsHeader << fin;
+
+ hashHandShake(ssl, output);
+ opaque digest[SHA_LEN]; // max size
+ if (ssl.isTLS())
+ TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, handshake);
+ else
+ hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, handshake);
+ output.write(digest, digestSz);
+
+ if (ssl.getSecurity().get_parms().cipher_type_ == block)
+ for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets
+ // pad value too
+ input_buffer cipher(rlHeader.length_);
+ ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(),
+ output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER);
+ output.set_current(RECORD_HEADER);
+ output.write(cipher.get_buffer(), cipher.get_capacity());
+}
+
+
+// build an encrypted data or alert message for output
+void buildMessage(SSL& ssl, output_buffer& output, const Message& msg)
+{
+ uint digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ uint sz = RECORD_HEADER + msg.get_length() + digestSz;
+ uint pad = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ sz += 1; // pad byte
+ uint blockSz = ssl.getCrypto().get_cipher().get_blockSize();
+ pad = (sz - RECORD_HEADER) % blockSz;
+ pad = blockSz - pad;
+ sz += pad;
+ }
+
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, msg);
+ rlHeader.length_ = sz - RECORD_HEADER; // record header includes mac
+ // and pad, hanshake doesn't
+ output.allocate(sz);
+ output << rlHeader << msg;
+
+ opaque digest[SHA_LEN]; // max size
+ if (ssl.isTLS())
+ TLS_hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, msg.get_type());
+ else
+ hmac(ssl, digest, output.get_buffer() + RECORD_HEADER,
+ output.get_size() - RECORD_HEADER, msg.get_type());
+ output.write(digest, digestSz);
+
+ if (ssl.getSecurity().get_parms().cipher_type_ == block)
+ for (uint i = 0; i <= pad; i++) output[AUTO] = pad; // pad byte gets
+ // pad value too
+ input_buffer cipher(rlHeader.length_);
+ ssl.useCrypto().use_cipher().encrypt(cipher.get_buffer(),
+ output.get_buffer() + RECORD_HEADER, output.get_size() - RECORD_HEADER);
+ output.set_current(RECORD_HEADER);
+ output.write(cipher.get_buffer(), cipher.get_capacity());
+}
+
+
+// build alert message
+void buildAlert(SSL& ssl, output_buffer& output, const Alert& alert)
+{
+ if (ssl.getSecurity().get_parms().pending_ == false) // encrypted
+ buildMessage(ssl, output, alert);
+ else {
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, alert);
+ buildOutput(output, rlHeader, alert);
+ }
+}
+
+
+// build TLS finished message
+void buildFinishedTLS(SSL& ssl, Finished& fin, const opaque* sender)
+{
+ opaque handshake_hash[FINISHED_SZ];
+
+ ssl.useHashes().use_MD5().get_digest(handshake_hash);
+ ssl.useHashes().use_SHA().get_digest(&handshake_hash[MD5_LEN]);
+
+ const opaque* side;
+ if ( strncmp((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0)
+ side = tls_client;
+ else
+ side = tls_server;
+
+ PRF(fin.set_md5(), TLS_FINISHED_SZ,
+ ssl.getSecurity().get_connection().master_secret_, SECRET_LEN,
+ side, FINISHED_LABEL_SZ,
+ handshake_hash, FINISHED_SZ);
+
+ fin.set_length(TLS_FINISHED_SZ); // shorter length for TLS
+}
+
+
+// compute p_hash for MD5 or SHA-1 for TLSv1 PRF
+void p_hash(output_buffer& result, const output_buffer& secret,
+ const output_buffer& seed, MACAlgorithm hash)
+{
+ uint len = hash == md5 ? MD5_LEN : SHA_LEN;
+ uint times = result.get_capacity() / len;
+ uint lastLen = result.get_capacity() % len;
+ opaque previous[SHA_LEN]; // max size
+ opaque current[SHA_LEN]; // max size
+ mySTL::auto_ptr<Digest> hmac;
+
+ if (lastLen) times += 1;
+
+ if (hash == md5)
+ hmac.reset(new (ys) HMAC_MD5(secret.get_buffer(), secret.get_size()));
+ else
+ hmac.reset(new (ys) HMAC_SHA(secret.get_buffer(), secret.get_size()));
+ // A0 = seed
+ hmac->get_digest(previous, seed.get_buffer(), seed.get_size());// A1
+ uint lastTime = times - 1;
+
+ for (uint i = 0; i < times; i++) {
+ hmac->update(previous, len);
+ hmac->get_digest(current, seed.get_buffer(), seed.get_size());
+
+ if (lastLen && (i == lastTime))
+ result.write(current, lastLen);
+ else {
+ result.write(current, len);
+ //memcpy(previous, current, len);
+ hmac->get_digest(previous, previous, len);
+ }
+ }
+}
+
+
+// calculate XOR for TLSv1 PRF
+void get_xor(byte *digest, uint digLen, output_buffer& md5,
+ output_buffer& sha)
+{
+ for (uint i = 0; i < digLen; i++)
+ digest[i] = md5[AUTO] ^ sha[AUTO];
+}
+
+
+// build MD5 part of certificate verify
+void buildMD5_CertVerify(SSL& ssl, byte* digest)
+{
+ opaque md5_result[MD5_LEN];
+ opaque md5_inner[SECRET_LEN + PAD_MD5];
+ opaque md5_outer[SECRET_LEN + PAD_MD5 + MD5_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make md5 inner
+ memcpy(md5_inner, master_secret, SECRET_LEN);
+ memcpy(&md5_inner[SECRET_LEN], PAD1, PAD_MD5);
+
+ ssl.useHashes().use_MD5().get_digest(md5_result, md5_inner,
+ sizeof(md5_inner));
+
+ // make md5 outer
+ memcpy(md5_outer, master_secret, SECRET_LEN);
+ memcpy(&md5_outer[SECRET_LEN], PAD2, PAD_MD5);
+ memcpy(&md5_outer[SECRET_LEN + PAD_MD5], md5_result, MD5_LEN);
+
+ ssl.useHashes().use_MD5().get_digest(digest, md5_outer, sizeof(md5_outer));
+}
+
+
+// build SHA part of certificate verify
+void buildSHA_CertVerify(SSL& ssl, byte* digest)
+{
+ opaque sha_result[SHA_LEN];
+ opaque sha_inner[SECRET_LEN + PAD_SHA];
+ opaque sha_outer[SECRET_LEN + PAD_SHA + SHA_LEN];
+
+ const opaque* master_secret =
+ ssl.getSecurity().get_connection().master_secret_;
+
+ // make sha inner
+ memcpy(sha_inner, master_secret, SECRET_LEN);
+ memcpy(&sha_inner[SECRET_LEN], PAD1, PAD_SHA);
+
+ ssl.useHashes().use_SHA().get_digest(sha_result, sha_inner,
+ sizeof(sha_inner));
+
+ // make sha outer
+ memcpy(sha_outer, master_secret, SECRET_LEN);
+ memcpy(&sha_outer[SECRET_LEN], PAD2, PAD_SHA);
+ memcpy(&sha_outer[SECRET_LEN + PAD_SHA], sha_result, SHA_LEN);
+
+ ssl.useHashes().use_SHA().get_digest(digest, sha_outer, sizeof(sha_outer));
+}
+
+
+} // namespace for locals
+
+
+// some clients still send sslv2 client hello
+void ProcessOldClientHello(input_buffer& input, SSL& ssl)
+{
+ byte b0 = input[AUTO];
+ byte b1 = input[AUTO];
+
+ uint16 sz = ((b0 & 0x7f) << 8) | b1;
+
+ // hashHandShake manually
+ const opaque* buffer = input.get_buffer() + input.get_current();
+ ssl.useHashes().use_MD5().update(buffer, sz);
+ ssl.useHashes().use_SHA().update(buffer, sz);
+
+ b1 = input[AUTO]; // does this value mean client_hello?
+
+ ClientHello ch;
+ ch.client_version_.major_ = input[AUTO];
+ ch.client_version_.minor_ = input[AUTO];
+
+ byte len[2];
+
+ input.read(len, sizeof(len));
+ ato16(len, ch.suite_len_);
+
+ input.read(len, sizeof(len));
+ uint16 sessionLen;
+ ato16(len, sessionLen);
+ ch.id_len_ = sessionLen;
+
+ input.read(len, sizeof(len));
+ uint16 randomLen;
+ ato16(len, randomLen);
+
+ int j = 0;
+ for (uint16 i = 0; i < ch.suite_len_; i += 3) {
+ byte first = input[AUTO];
+ if (first) // sslv2 type
+ input.read(len, SUITE_LEN); // skip
+ else {
+ input.read(&ch.cipher_suites_[j], SUITE_LEN);
+ j += SUITE_LEN;
+ }
+ }
+ ch.suite_len_ = j;
+
+ if (ch.id_len_)
+ input.read(ch.session_id_, ch.id_len_);
+
+ if (randomLen < RAN_LEN)
+ memset(ch.random_, 0, RAN_LEN - randomLen);
+ input.read(&ch.random_[RAN_LEN - randomLen], randomLen);
+
+
+ ch.Process(input, ssl);
+}
+
+
+// Build a finished message, see 7.6.9
+void buildFinished(SSL& ssl, Finished& fin, const opaque* sender)
+{
+ // store current states, building requires get_digest which resets state
+ MD5 md5(ssl.getHashes().get_MD5());
+ SHA sha(ssl.getHashes().get_SHA());
+
+ if (ssl.isTLS())
+ buildFinishedTLS(ssl, fin, sender);
+ else {
+ buildMD5(ssl, fin, sender);
+ buildSHA(ssl, fin, sender);
+ }
+
+ // restore
+ ssl.useHashes().use_MD5() = md5;
+ ssl.useHashes().use_SHA() = sha;
+}
+
+
+/* compute SSLv3 HMAC into digest see
+ * buffer is of sz size and includes HandShake Header but not a Record Header
+ * verify means to check peers hmac
+*/
+void hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
+ ContentType content, bool verify)
+{
+ Digest& mac = ssl.useCrypto().use_digest();
+ opaque inner[SHA_LEN + PAD_MD5 + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ];
+ opaque outer[SHA_LEN + PAD_MD5 + SHA_LEN];
+ opaque result[SHA_LEN]; // max possible sizes
+ uint digestSz = mac.get_digestSize(); // actual sizes
+ uint padSz = mac.get_padSize();
+ uint innerSz = digestSz + padSz + SEQ_SZ + SIZEOF_ENUM + LENGTH_SZ;
+ uint outerSz = digestSz + padSz + digestSz;
+
+ // data
+ const opaque* mac_secret = ssl.get_macSecret(verify);
+ opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ opaque length[LENGTH_SZ];
+ c16toa(sz, length);
+ c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
+
+ // make inner
+ memcpy(inner, mac_secret, digestSz);
+ memcpy(&inner[digestSz], PAD1, padSz);
+ memcpy(&inner[digestSz + padSz], seq, SEQ_SZ);
+ inner[digestSz + padSz + SEQ_SZ] = content;
+ memcpy(&inner[digestSz + padSz + SEQ_SZ + SIZEOF_ENUM], length, LENGTH_SZ);
+
+ mac.update(inner, innerSz);
+ mac.get_digest(result, buffer, sz); // append content buffer
+
+ // make outer
+ memcpy(outer, mac_secret, digestSz);
+ memcpy(&outer[digestSz], PAD2, padSz);
+ memcpy(&outer[digestSz + padSz], result, digestSz);
+
+ mac.get_digest(digest, outer, outerSz);
+}
+
+
+// TLS type HAMC
+void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz,
+ ContentType content, bool verify)
+{
+ mySTL::auto_ptr<Digest> hmac;
+ opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 };
+ opaque length[LENGTH_SZ];
+ opaque inner[SIZEOF_ENUM + VERSION_SZ + LENGTH_SZ]; // type + version + len
+
+ c16toa(sz, length);
+ c32toa(ssl.get_SEQIncrement(verify), &seq[sizeof(uint32)]);
+
+ MACAlgorithm algo = ssl.getSecurity().get_parms().mac_algorithm_;
+
+ if (algo == sha)
+ hmac.reset(new (ys) HMAC_SHA(ssl.get_macSecret(verify), SHA_LEN));
+ else if (algo == rmd)
+ hmac.reset(new (ys) HMAC_RMD(ssl.get_macSecret(verify), RMD_LEN));
+ else
+ hmac.reset(new (ys) HMAC_MD5(ssl.get_macSecret(verify), MD5_LEN));
+
+ hmac->update(seq, SEQ_SZ); // seq_num
+ inner[0] = content; // type
+ inner[SIZEOF_ENUM] = ssl.getSecurity().get_connection().version_.major_;
+ inner[SIZEOF_ENUM + SIZEOF_ENUM] =
+ ssl.getSecurity().get_connection().version_.minor_; // version
+ memcpy(&inner[SIZEOF_ENUM + VERSION_SZ], length, LENGTH_SZ); // length
+ hmac->update(inner, sizeof(inner));
+ hmac->get_digest(digest, buffer, sz); // content
+}
+
+
+// compute TLSv1 PRF (pseudo random function using HMAC)
+void PRF(byte* digest, uint digLen, const byte* secret, uint secLen,
+ const byte* label, uint labLen, const byte* seed, uint seedLen)
+{
+ uint half = secLen / 2 + secLen % 2;
+
+ output_buffer md5_half(half);
+ output_buffer sha_half(half);
+ output_buffer labelSeed(labLen + seedLen);
+
+ md5_half.write(secret, half);
+ sha_half.write(secret + half - secLen % 2, half);
+ labelSeed.write(label, labLen);
+ labelSeed.write(seed, seedLen);
+
+ output_buffer md5_result(digLen);
+ output_buffer sha_result(digLen);
+
+ p_hash(md5_result, md5_half, labelSeed, md5);
+ p_hash(sha_result, sha_half, labelSeed, sha);
+
+ md5_result.set_current(0);
+ sha_result.set_current(0);
+ get_xor(digest, digLen, md5_result, sha_result);
+}
+
+
+// build certificate hashes
+void build_certHashes(SSL& ssl, Hashes& hashes)
+{
+ // store current states, building requires get_digest which resets state
+ MD5 md5(ssl.getHashes().get_MD5());
+ SHA sha(ssl.getHashes().get_SHA());
+
+ if (ssl.isTLS()) {
+ ssl.useHashes().use_MD5().get_digest(hashes.md5_);
+ ssl.useHashes().use_SHA().get_digest(hashes.sha_);
+ }
+ else {
+ buildMD5_CertVerify(ssl, hashes.md5_);
+ buildSHA_CertVerify(ssl, hashes.sha_);
+ }
+
+ // restore
+ ssl.useHashes().use_MD5() = md5;
+ ssl.useHashes().use_SHA() = sha;
+}
+
+
+mySTL::auto_ptr<input_buffer> null_buffer;
+
+// do process input requests
+mySTL::auto_ptr<input_buffer>
+DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
+{
+ ssl.getSocket().wait(); // wait for input if blocking
+ uint ready = ssl.getSocket().get_ready();
+ if (!ready) return buffered;
+
+ // add buffered data if its there
+ uint buffSz = buffered.get() ? buffered.get()->get_size() : 0;
+ input_buffer buffer(buffSz + ready);
+ if (buffSz) {
+ buffer.assign(buffered.get()->get_buffer(), buffSz);
+ buffered = null_buffer;
+ }
+
+ // add new data
+ uint read = ssl.getSocket().receive(buffer.get_buffer() + buffSz, ready);
+ buffer.add_size(read);
+ uint offset = 0;
+ const MessageFactory& mf = ssl.getFactory().getMessage();
+
+ // old style sslv2 client hello?
+ if (ssl.getSecurity().get_parms().entity_ == server_end &&
+ ssl.getStates().getServer() == clientNull)
+ if (buffer.peek() != handshake)
+ ProcessOldClientHello(buffer, ssl);
+
+ while(!buffer.eof()) {
+ // each record
+ RecordLayerHeader hdr;
+ buffer >> hdr;
+ ssl.verifyState(hdr);
+
+ // make sure we have enough input in buffer to process this record
+ if (hdr.length_ > buffer.get_remaining()) {
+ uint sz = buffer.get_remaining() + RECORD_HEADER;
+ buffered.reset(new (ys) input_buffer(sz, buffer.get_buffer() +
+ buffer.get_current() - RECORD_HEADER, sz));
+ break;
+ }
+
+ while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) {
+ // each message in record
+ if (ssl.getSecurity().get_parms().pending_ == false) // cipher on
+ decrypt_message(ssl, buffer, hdr.length_);
+ mySTL::auto_ptr<Message> msg(mf.CreateObject(hdr.type_));
+ if (!msg.get()) {
+ ssl.SetError(factory_error);
+ return buffered = null_buffer;
+ }
+ buffer >> *msg;
+ msg->Process(buffer, ssl);
+ if (ssl.GetError()) return buffered = null_buffer;
+ }
+ offset += hdr.length_ + RECORD_HEADER;
+ }
+ return buffered; // done, don't call again
+}
+
+
+// process input requests
+void processReply(SSL& ssl)
+{
+ if (ssl.GetError()) return;
+ mySTL::auto_ptr<input_buffer> buffered;
+
+ for (;;) {
+ mySTL::auto_ptr<input_buffer> tmp = DoProcessReply(ssl, buffered);
+ if (tmp.get()) // had only part of a record's data, call again
+ buffered = tmp;
+ else
+ break;
+ }
+}
+
+
+// send client_hello, no buffering
+void sendClientHello(SSL& ssl)
+{
+ ssl.verifyState(serverNull);
+ if (ssl.GetError()) return;
+
+ ClientHello ch(ssl.getSecurity().get_connection().version_);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ output_buffer out;
+
+ buildClientHello(ssl, ch);
+ ssl.set_random(ch.get_random(), client_end);
+ buildHeaders(ssl, hsHeader, rlHeader, ch);
+ buildOutput(out, rlHeader, hsHeader, ch);
+ hashHandShake(ssl, out);
+
+ ssl.Send(out.get_buffer(), out.get_size());
+}
+
+
+// send client key exchange
+void sendClientKeyExchange(SSL& ssl, BufferOutput buffer)
+{
+ ssl.verifyState(serverHelloDoneComplete);
+ if (ssl.GetError()) return;
+
+ ClientKeyExchange ck(ssl);
+ ck.build(ssl);
+ ssl.makeMasterSecret();
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+ buildHeaders(ssl, hsHeader, rlHeader, ck);
+ buildOutput(*out.get(), rlHeader, hsHeader, ck);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send server key exchange
+void sendServerKeyExchange(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+ ServerKeyExchange sk(ssl);
+ sk.build(ssl);
+
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+ buildHeaders(ssl, hsHeader, rlHeader, sk);
+ buildOutput(*out.get(), rlHeader, hsHeader, sk);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send change cipher
+void sendChangeCipher(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.getSecurity().get_parms().entity_ == server_end)
+ if (ssl.getSecurity().get_resuming())
+ ssl.verifyState(clientKeyExchangeComplete);
+ else
+ ssl.verifyState(clientFinishedComplete);
+ if (ssl.GetError()) return;
+
+ ChangeCipherSpec ccs;
+ RecordLayerHeader rlHeader;
+ buildHeader(ssl, rlHeader, ccs);
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+ buildOutput(*out.get(), rlHeader, ccs);
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send finished
+void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ Finished fin;
+ buildFinished(ssl, fin, side == client_end ? client : server);
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+ cipherFinished(ssl, fin, *out.get()); // hashes handshake
+
+ if (ssl.getSecurity().get_resuming()) {
+ if (side == server_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), client); // client
+ }
+ else {
+ GetSessions().add(ssl); // store session
+ if (side == client_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), server); // server
+ }
+ ssl.useSecurity().use_connection().CleanMaster();
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send data
+int sendData(SSL& ssl, const void* buffer, int sz)
+{
+ ssl.verfiyHandShakeComplete();
+ if (ssl.GetError()) return 0;
+ int sent = 0;
+
+ for (;;) {
+ int len = min(sz - sent, MAX_RECORD_SIZE);
+ output_buffer out;
+ const Data data(len, static_cast<const opaque*>(buffer) + sent);
+
+ buildMessage(ssl, out, data);
+ ssl.Send(out.get_buffer(), out.get_size());
+
+ if (ssl.GetError()) return 0;
+ sent += len;
+ if (sent == sz) break;
+ }
+ ssl.useLog().ShowData(sent, true);
+ return sent;
+}
+
+
+// send alert
+int sendAlert(SSL& ssl, const Alert& alert)
+{
+ output_buffer out;
+ buildAlert(ssl, out, alert);
+ ssl.Send(out.get_buffer(), out.get_size());
+
+ return alert.get_length();
+}
+
+
+// process input data
+int receiveData(SSL& ssl, Data& data)
+{
+ ssl.verfiyHandShakeComplete();
+ if (ssl.GetError()) return 0;
+
+ if (!ssl.bufferedData())
+ processReply(ssl);
+ ssl.fillData(data);
+ ssl.useLog().ShowData(data.get_length());
+
+ if (ssl.GetError()) return 0;
+ return data.get_length();
+}
+
+
+// send server hello
+void sendServerHello(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.getSecurity().get_resuming())
+ ssl.verifyState(clientKeyExchangeComplete);
+ else
+ ssl.verifyState(clientHelloComplete);
+ if (ssl.GetError()) return;
+
+ ServerHello sh(ssl.getSecurity().get_connection().version_);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildServerHello(ssl, sh);
+ ssl.set_random(sh.get_random(), server_end);
+ buildHeaders(ssl, hsHeader, rlHeader, sh);
+ buildOutput(*out.get(), rlHeader, hsHeader, sh);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send server hello done
+void sendServerHelloDone(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ ServerHelloDone shd;
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildHeaders(ssl, hsHeader, rlHeader, shd);
+ buildOutput(*out.get(), rlHeader, hsHeader, shd);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate
+void sendCertificate(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ Certificate cert(ssl.getCrypto().get_certManager().get_cert());
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildHeaders(ssl, hsHeader, rlHeader, cert);
+ buildOutput(*out.get(), rlHeader, hsHeader, cert);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate request
+void sendCertificateRequest(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ CertificateRequest request;
+ request.Build();
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildHeaders(ssl, hsHeader, rlHeader, request);
+ buildOutput(*out.get(), rlHeader, hsHeader, request);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+// send certificate verify
+void sendCertificateVerify(SSL& ssl, BufferOutput buffer)
+{
+ if (ssl.GetError()) return;
+
+ CertificateVerify verify;
+ verify.Build(ssl);
+ RecordLayerHeader rlHeader;
+ HandShakeHeader hsHeader;
+ mySTL::auto_ptr<output_buffer> out(new (ys) output_buffer);
+
+ buildHeaders(ssl, hsHeader, rlHeader, verify);
+ buildOutput(*out.get(), rlHeader, hsHeader, verify);
+ hashHandShake(ssl, *out.get());
+
+ if (buffer == buffered)
+ ssl.addBuffer(out.release());
+ else
+ ssl.Send(out->get_buffer(), out->get_size());
+}
+
+
+} // namespace
diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp
new file mode 100644
index 00000000000..221ec0cdb4f
--- /dev/null
+++ b/extra/yassl/src/lock.cpp
@@ -0,0 +1,90 @@
+/* lock.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Locking functions
+ */
+
+#include "runtime.hpp"
+#include "lock.hpp"
+
+
+namespace yaSSL {
+
+
+#ifdef MULTI_THREADED
+ #ifdef WIN32
+
+ Mutex::Mutex()
+ {
+ InitializeCriticalSection(&cs_);
+ }
+
+
+ Mutex::~Mutex()
+ {
+ DeleteCriticalSection(&cs_);
+ }
+
+
+ Mutex::Lock::Lock(Mutex& lm) : mutex_(lm)
+ {
+ EnterCriticalSection(&mutex_.cs_);
+ }
+
+
+ Mutex::Lock::~Lock()
+ {
+ LeaveCriticalSection(&mutex_.cs_);
+ }
+
+ #else // WIN32
+
+ Mutex::Mutex()
+ {
+ pthread_mutex_init(&mutex_, 0);
+ }
+
+
+ Mutex::~Mutex()
+ {
+ pthread_mutex_destroy(&mutex_);
+ }
+
+
+ Mutex::Lock::Lock(Mutex& lm) : mutex_(lm)
+ {
+ pthread_mutex_lock(&mutex_.mutex_);
+ }
+
+
+ Mutex::Lock::~Lock()
+ {
+ pthread_mutex_unlock(&mutex_.mutex_);
+ }
+
+
+ #endif // WIN32
+#endif // MULTI_THREADED
+
+
+
+} // namespace yaSSL
+
diff --git a/extra/yassl/src/log.cpp b/extra/yassl/src/log.cpp
new file mode 100644
index 00000000000..eb4776d3d19
--- /dev/null
+++ b/extra/yassl/src/log.cpp
@@ -0,0 +1,148 @@
+/* log.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* Debug logging functions
+ */
+
+#include "runtime.hpp"
+#include "log.hpp"
+
+#ifdef YASSL_LOG
+ #include <ctime>
+ #include <cstdio>
+ #include <cstring>
+#endif
+
+
+
+namespace yaSSL {
+
+
+#ifdef YASSL_LOG
+
+ enum { MAX_MSG = 81 };
+
+ Log::Log(const char* str)
+ {
+ log_ = fopen(str, "w");
+ Trace("********** Logger Attached **********");
+ }
+
+
+ Log::~Log()
+ {
+ Trace("********** Logger Detached **********");
+ fclose(log_);
+ }
+
+
+ // Trace a message
+ void Log::Trace(const char* str)
+ {
+ if (!log_) return;
+
+ time_t clicks = time(0);
+ char timeStr[32];
+
+ // get rid of newline
+ strncpy(timeStr, ctime(&clicks), sizeof(timeStr));
+ unsigned int len = strlen(timeStr);
+ timeStr[len - 1] = 0;
+
+ char msg[MAX_MSG];
+
+ strncpy(msg, timeStr, sizeof(timeStr));
+ strncat(msg, ":", 1);
+ strncat(msg, str, MAX_MSG - sizeof(timeStr) - 2);
+ strncat(msg, "\n", 1);
+ msg[MAX_MSG - 1] = 0;
+
+ fputs(msg, log_);
+ }
+
+
+ #if defined(WIN32) || defined(__MACH__) || defined(__hpux__)
+ typedef int socklen_t;
+ #endif
+
+
+ // write tcp address
+ void Log::ShowTCP(socket_t fd, bool ended)
+ {
+ sockaddr_in peeraddr;
+ socklen_t len = sizeof(peeraddr);
+ if (getpeername(fd, (sockaddr*)&peeraddr, &len) != 0)
+ return;
+
+ const char* p = reinterpret_cast<const char*>(&peeraddr.sin_addr);
+ char msg[MAX_MSG];
+ char number[16];
+
+ if (ended)
+ strncpy(msg, "yaSSL conn DONE w/ peer ", 26);
+ else
+ strncpy(msg, "yaSSL conn BEGUN w/ peer ", 26);
+ for (int i = 0; i < 4; ++i) {
+ sprintf(number, "%u", static_cast<unsigned short>(p[i]));
+ strncat(msg, number, 8);
+ if (i < 3)
+ strncat(msg, ".", 1);
+ }
+ strncat(msg, " port ", 8);
+ sprintf(number, "%d", htons(peeraddr.sin_port));
+ strncat(msg, number, 8);
+
+ msg[MAX_MSG - 1] = 0;
+ Trace(msg);
+ }
+
+
+ // log processed data
+ void Log::ShowData(uint bytes, bool sent)
+ {
+ char msg[MAX_MSG];
+ char number[16];
+
+ if (sent)
+ strncpy(msg, "Sent ", 10);
+ else
+ strncpy(msg, "Received ", 10);
+ sprintf(number, "%u", bytes);
+ strncat(msg, number, 8);
+ strncat(msg, " bytes of application data", 27);
+
+ msg[MAX_MSG - 1] = 0;
+ Trace(msg);
+ }
+
+
+#else // no YASSL_LOG
+
+
+ Log::Log(const char*) {}
+ Log::~Log() {}
+ void Log::Trace(const char*) {}
+ void Log::ShowTCP(socket_t, bool) {}
+ void Log::ShowData(uint, bool) {}
+
+
+#endif // YASSL_LOG
+} // namespace
diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp
new file mode 100644
index 00000000000..0dd30e6b696
--- /dev/null
+++ b/extra/yassl/src/socket_wrapper.cpp
@@ -0,0 +1,168 @@
+/* socket_wrapper.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* The socket wrapper source implements a Socket class that hides the
+ * differences between Berkely style sockets and Windows sockets, allowing
+ * transparent TCP access.
+ */
+
+
+#include "runtime.hpp"
+#include "socket_wrapper.hpp"
+#include "yassl_error.hpp"
+
+#ifndef WIN32
+ #include <errno.h>
+ #include <netdb.h>
+ #include <unistd.h>
+ #include <arpa/inet.h>
+ #include <netinet/in.h>
+ #include <sys/ioctl.h>
+ #include <string.h>
+#endif // WIN32
+
+#ifdef __sun
+ #include <sys/filio.h>
+#endif
+
+#ifdef WIN32
+ const int SOCKET_EINVAL = WSAEINVAL;
+ const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
+#else
+ const int SOCKET_EINVAL = EINVAL;
+ const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
+#endif // WIN32
+
+
+namespace yaSSL {
+
+
+Socket::Socket(socket_t s)
+ : socket_(s)
+{}
+
+
+void Socket::set_fd(socket_t s)
+{
+ socket_ = s;
+}
+
+
+socket_t Socket::get_fd() const
+{
+ return socket_;
+}
+
+
+Socket::~Socket()
+{
+ closeSocket();
+}
+
+
+void Socket::closeSocket()
+{
+ if (socket_ != INVALID_SOCKET) {
+#ifdef WIN32
+ closesocket(socket_);
+#else
+ close(socket_);
+#endif
+ socket_ = INVALID_SOCKET;
+ }
+}
+
+
+uint Socket::get_ready() const
+{
+ unsigned long ready = 0;
+
+#ifdef WIN32
+ ioctlsocket(socket_, FIONREAD, &ready);
+#else
+ ioctl(socket_, FIONREAD, &ready);
+#endif
+
+ return ready;
+}
+
+
+uint Socket::send(const byte* buf, unsigned int sz, int flags) const
+{
+ assert(socket_ != INVALID_SOCKET);
+ int sent = ::send(socket_, reinterpret_cast<const char *>(buf), sz, flags);
+
+ if (sent == -1)
+ return 0;
+
+ return sent;
+}
+
+
+uint Socket::receive(byte* buf, unsigned int sz, int flags) const
+{
+ assert(socket_ != INVALID_SOCKET);
+ int recvd = ::recv(socket_, reinterpret_cast<char *>(buf), sz, flags);
+
+ if (recvd == -1)
+ return 0;
+
+ return recvd;
+}
+
+
+// wait if blocking for input, or error
+void Socket::wait() const
+{
+ byte b;
+ receive(&b, 1, MSG_PEEK);
+}
+
+
+void Socket::shutDown(int how)
+{
+ assert(socket_ != INVALID_SOCKET);
+ shutdown(socket_, how);
+}
+
+
+int Socket::get_lastError()
+{
+#ifdef WIN32
+ return WSAGetLastError();
+#else
+ return errno;
+#endif
+}
+
+
+void Socket::set_lastError(int errorCode)
+{
+#ifdef WIN32
+ WSASetLastError(errorCode);
+#else
+ errno = errorCode;
+#endif
+}
+
+
+} // namespace
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
new file mode 100644
index 00000000000..065b3c260bf
--- /dev/null
+++ b/extra/yassl/src/ssl.cpp
@@ -0,0 +1,1039 @@
+/* ssl.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* SSL source implements all openssl compatibility API functions
+ *
+ * TODO: notes are mostly api additions to allow compilation with mysql
+ * they don't affect normal modes but should be provided for completeness
+
+ * stunnel functions at end of file
+ */
+
+
+
+
+/* see man pages for function descriptions */
+
+#include "runtime.hpp"
+#include "openssl/ssl.h"
+#include "handshake.hpp"
+#include "yassl_int.hpp"
+#include <cstdio>
+
+
+namespace yaSSL {
+
+using mySTL::min;
+
+
+SSL_METHOD* SSLv3_method()
+{
+ return SSLv3_client_method();
+}
+
+
+SSL_METHOD* SSLv3_server_method()
+{
+ return new SSL_METHOD(server_end, ProtocolVersion(3,0));
+}
+
+
+SSL_METHOD* SSLv3_client_method()
+{
+ return new SSL_METHOD(client_end, ProtocolVersion(3,0));
+}
+
+
+SSL_METHOD* TLSv1_server_method()
+{
+ return new SSL_METHOD(server_end, ProtocolVersion(3,1));
+}
+
+
+SSL_METHOD* TLSv1_client_method()
+{
+ return new SSL_METHOD(client_end, ProtocolVersion(3,1));
+}
+
+
+SSL_METHOD* SSLv23_server_method()
+{
+ // compatibility only, no version 2 support
+ return SSLv3_server_method();
+}
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD* method)
+{
+ return new SSL_CTX(method);
+}
+
+
+void SSL_CTX_free(SSL_CTX* ctx)
+{
+ delete ctx;
+}
+
+
+SSL* SSL_new(SSL_CTX* ctx)
+{
+ return new SSL(ctx);
+}
+
+
+void SSL_free(SSL* ssl)
+{
+ delete ssl;
+}
+
+
+int SSL_set_fd(SSL* ssl, int fd)
+{
+ ssl->useSocket().set_fd(fd);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_connect(SSL* ssl)
+{
+ sendClientHello(*ssl);
+ processReply(*ssl);
+
+ if(ssl->getCrypto().get_certManager().sendVerify())
+ sendCertificate(*ssl);
+
+ if (!ssl->getSecurity().get_resuming())
+ sendClientKeyExchange(*ssl);
+
+ if(ssl->getCrypto().get_certManager().sendVerify())
+ sendCertificateVerify(*ssl);
+
+ sendChangeCipher(*ssl);
+ sendFinished(*ssl, client_end);
+ ssl->flushBuffer();
+ if (!ssl->getSecurity().get_resuming())
+ processReply(*ssl);
+
+ ssl->verifyState(serverFinishedComplete);
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
+
+ if (ssl->GetError())
+ return SSL_FATAL_ERROR;
+ return SSL_SUCCESS;
+}
+
+
+int SSL_write(SSL* ssl, const void* buffer, int sz)
+{
+ return sendData(*ssl, buffer, sz);
+}
+
+
+int SSL_read(SSL* ssl, void* buffer, int sz)
+{
+ Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
+ return receiveData(*ssl, data);
+}
+
+
+int SSL_accept(SSL* ssl)
+{
+ processReply(*ssl);
+ sendServerHello(*ssl);
+
+ if (!ssl->getSecurity().get_resuming()) {
+ sendCertificate(*ssl);
+
+ if (ssl->getSecurity().get_connection().send_server_key_)
+ sendServerKeyExchange(*ssl);
+
+ if(ssl->getCrypto().get_certManager().verifyPeer())
+ sendCertificateRequest(*ssl);
+
+ sendServerHelloDone(*ssl);
+ ssl->flushBuffer();
+
+ processReply(*ssl);
+ }
+ sendChangeCipher(*ssl);
+ sendFinished(*ssl, server_end);
+ ssl->flushBuffer();
+ if (ssl->getSecurity().get_resuming())
+ processReply(*ssl);
+
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
+
+ if (ssl->GetError())
+ return SSL_FATAL_ERROR;
+ return SSL_SUCCESS;
+}
+
+
+int SSL_do_handshake(SSL* ssl)
+{
+ if (ssl->getSecurity().get_parms().entity_ == client_end)
+ return SSL_connect(ssl);
+ else
+ return SSL_accept(ssl);
+}
+
+
+int SSL_clear(SSL* ssl)
+{
+ ssl->useSocket().closeSocket();
+ return SSL_SUCCESS;
+}
+
+
+int SSL_shutdown(SSL* ssl)
+{
+ Alert alert(warning, close_notify);
+ sendAlert(*ssl, alert);
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true);
+ ssl->useSocket().closeSocket();
+
+ return SSL_SUCCESS;
+}
+
+
+SSL_SESSION* SSL_get_session(SSL* ssl)
+{
+ return GetSessions().lookup(
+ ssl->getSecurity().get_connection().sessionID_);
+}
+
+
+int SSL_set_session(SSL* ssl, SSL_SESSION* session)
+{
+ ssl->set_session(session);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_session_reused(SSL* ssl)
+{
+ return ssl->getSecurity().get_resuming();
+}
+
+
+long SSL_SESSION_set_timeout(SSL_SESSION* sess, long t)
+{
+ if (!sess)
+ return SSL_ERROR_NONE;
+
+ sess->SetTimeOut(t);
+ return SSL_SUCCESS;
+}
+
+
+long SSL_get_default_timeout(SSL* /*ssl*/)
+{
+ return DEFAULT_TIMEOUT;
+}
+
+
+const char* SSL_get_cipher_name(SSL* ssl)
+{
+ return SSL_get_cipher(ssl);
+}
+
+
+const char* SSL_get_cipher(SSL* ssl)
+{
+ return ssl->getSecurity().get_parms().cipher_name_;
+}
+
+
+// SSLv2 only, not implemented
+char* SSL_get_shared_ciphers(SSL* /*ssl*/, char* buf, int len)
+{
+ return strncpy(buf, "Not Implemented, SSLv2 only", len);
+}
+
+
+const char* SSL_get_cipher_list(SSL* ssl, int /*priority */)
+{
+ return ssl->getSecurity().get_parms().cipher_list_;
+}
+
+
+int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
+{
+ if (ctx->SetCipherList(list))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+const char* SSL_get_version(SSL* ssl)
+{
+ static const char* version3 = "SSLv3";
+ static const char* version31 = "TLSv1";
+
+ return ssl->isTLS() ? version31 : version3;
+}
+
+const char* SSLeay_version(int)
+{
+ static const char* version = "SSLeay yaSSL compatibility";
+ return version;
+}
+
+
+int SSL_get_error(SSL* ssl, int /*previous*/)
+{
+ return ssl->getStates().What();
+}
+
+
+X509* SSL_get_peer_certificate(SSL* ssl)
+{
+ return ssl->getCrypto().get_certManager().get_peerX509();
+}
+
+
+void X509_free(X509* /*x*/)
+{
+ // peer cert set for deletion during destruction
+ // no need to delete now
+}
+
+
+X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX* ctx)
+{
+ return ctx->current_cert;
+}
+
+
+int X509_STORE_CTX_get_error(X509_STORE_CTX* ctx)
+{
+ return ctx->error;
+}
+
+
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX* ctx)
+{
+ return ctx->error_depth;
+}
+
+
+// copy name into buffer, at most sz bytes, if buffer is null
+// will malloc buffer, caller responsible for freeing
+char* X509_NAME_oneline(X509_NAME* name, char* buffer, int sz)
+{
+ if (!name->GetName()) return buffer;
+
+ int len = strlen(name->GetName()) + 1;
+ int copySz = min(len, sz);
+
+ if (!buffer) {
+ buffer = (char*)malloc(len);
+ if (!buffer) return buffer;
+ copySz = len;
+ }
+
+ if (copySz == 0)
+ return buffer;
+
+ memcpy(buffer, name->GetName(), copySz - 1);
+ buffer[copySz - 1] = 0;
+
+ return buffer;
+}
+
+
+X509_NAME* X509_get_issuer_name(X509* x)
+{
+ return x->GetIssuer();
+}
+
+
+X509_NAME* X509_get_subject_name(X509* x)
+{
+ return x->GetSubject();
+}
+
+
+void SSL_load_error_strings() // compatibility only
+{}
+
+
+void SSL_set_connect_state(SSL*)
+{
+ // already a client by default
+}
+
+
+void SSL_set_accept_state(SSL* ssl)
+{
+ ssl->useSecurity().use_parms().entity_ = server_end;
+}
+
+
+long SSL_get_verify_result(SSL*)
+{
+ // won't get here if not OK
+ return X509_V_OK;
+}
+
+
+long SSL_CTX_sess_set_cache_size(SSL_CTX* /*ctx*/, long /*sz*/)
+{
+ // unlimited size, can't set for now
+ return 0;
+}
+
+
+long SSL_CTX_get_session_cache_mode(SSL_CTX*)
+{
+ // always 0, unlimited size for now
+ return 0;
+}
+
+
+long SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH* dh)
+{
+ if (ctx->SetDH(*dh))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+int read_file(SSL_CTX* ctx, const char* file, int format, CertType type)
+{
+ if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)
+ return SSL_BAD_FILETYPE;
+
+ FILE* input = fopen(file, "rb");
+ if (!input)
+ return SSL_BAD_FILE;
+
+ if (type == CA) {
+ x509* ptr = PemToDer(file, Cert);
+ if (!ptr) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ ctx->AddCA(ptr); // takes ownership
+ }
+ else {
+ x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_;
+
+ if (format == SSL_FILETYPE_ASN1) {
+ fseek(input, 0, SEEK_END);
+ long sz = ftell(input);
+ rewind(input);
+ x = new (ys) x509(sz); // takes ownership
+ size_t bytes = fread(x->use_buffer(), sz, 1, input);
+ if (bytes != 1) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ }
+ else {
+ x = PemToDer(file, type);
+ if (!x) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ }
+ }
+ fclose(input);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format)
+{
+ return read_file(ctx, file, format, Cert);
+}
+
+
+int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx, const char* file, int format)
+{
+ return read_file(ctx, file, format, PrivateKey);
+}
+
+
+void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback /*vc*/)
+{
+ if (mode & SSL_VERIFY_PEER)
+ ctx->setVerifyPeer();
+
+ if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+ ctx->setFailNoCert();
+}
+
+
+int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
+ const char* /*path*/)
+{
+ // just files for now
+ return read_file(ctx, file, SSL_FILETYPE_PEM, CA);
+}
+
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX* /*ctx*/)
+{
+ // TODO: figure out way to set/store default path, then call load_verify
+ return SSL_NOT_IMPLEMENTED;
+}
+
+
+int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
+ unsigned int)
+{
+ // No application specific context needed for yaSSL
+ return SSL_SUCCESS;
+}
+
+
+int SSL_CTX_check_private_key(SSL_CTX* /*ctx*/)
+{
+ // TODO: check private against public for RSA match
+ return SSL_NOT_IMPLEMENTED;
+}
+
+
+// TODO: all session stats
+long SSL_CTX_sess_accept(SSL_CTX* ctx)
+{
+ return ctx->GetStats().accept_;
+}
+
+
+long SSL_CTX_sess_connect(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connect_;
+}
+
+
+long SSL_CTX_sess_accept_good(SSL_CTX* ctx)
+{
+ return ctx->GetStats().acceptGood_;
+}
+
+
+long SSL_CTX_sess_connect_good(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connectGood_;
+}
+
+
+long SSL_CTX_sess_accept_renegotiate(SSL_CTX* ctx)
+{
+ return ctx->GetStats().acceptRenegotiate_;
+}
+
+
+long SSL_CTX_sess_connect_renegotiate(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connectRenegotiate_;
+}
+
+
+long SSL_CTX_sess_hits(SSL_CTX* ctx)
+{
+ return ctx->GetStats().hits_;
+}
+
+
+long SSL_CTX_sess_cb_hits(SSL_CTX* ctx)
+{
+ return ctx->GetStats().cbHits_;
+}
+
+
+long SSL_CTX_sess_cache_full(SSL_CTX* ctx)
+{
+ return ctx->GetStats().cacheFull_;
+}
+
+
+long SSL_CTX_sess_misses(SSL_CTX* ctx)
+{
+ return ctx->GetStats().misses_;
+}
+
+
+long SSL_CTX_sess_timeouts(SSL_CTX* ctx)
+{
+ return ctx->GetStats().timeouts_;
+}
+
+
+long SSL_CTX_sess_number(SSL_CTX* ctx)
+{
+ return ctx->GetStats().number_;
+}
+
+
+long SSL_CTX_sess_get_cache_size(SSL_CTX* ctx)
+{
+ return ctx->GetStats().getCacheSize_;
+}
+// end session stats TODO:
+
+
+int SSL_CTX_get_verify_mode(SSL_CTX* ctx)
+{
+ return ctx->GetStats().verifyMode_;
+}
+
+
+int SSL_get_verify_mode(SSL* ssl)
+{
+ return ssl->getSecurity().GetContext()->GetStats().verifyMode_;
+}
+
+
+int SSL_CTX_get_verify_depth(SSL_CTX* ctx)
+{
+ return ctx->GetStats().verifyDepth_;
+}
+
+
+int SSL_get_verify_depth(SSL* ssl)
+{
+ return ssl->getSecurity().GetContext()->GetStats().verifyDepth_;
+}
+
+
+long SSL_CTX_set_options(SSL_CTX*, long)
+{
+ // TDOD:
+ return SSL_SUCCESS;
+}
+
+
+void SSL_CTX_set_info_callback(SSL_CTX*, void (*)())
+{
+ // TDOD:
+}
+
+
+void OpenSSL_add_all_algorithms() // compatibility only
+{}
+
+
+DH* DH_new(void)
+{
+ DH* dh = new DH;
+ if (dh)
+ dh->p = dh->g = 0;
+ return dh;
+}
+
+
+void DH_free(DH* dh)
+{
+ delete dh->g;
+ delete dh->p;
+ delete dh;
+}
+
+
+// convert positive big-endian num of length sz into retVal, which may need to
+// be created
+BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal)
+{
+ using mySTL::auto_ptr;
+ bool created = false;
+ auto_ptr<BIGNUM> bn;
+
+ if (!retVal) {
+ created = true;
+ bn.reset(new (ys) BIGNUM);
+ retVal = bn.get();
+ }
+
+ retVal->assign(num, sz);
+
+ if (created)
+ return bn.release();
+ else
+ return retVal;
+}
+
+
+unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *)
+{
+ //return SSL_NOT_IMPLEMENTED;
+ return 0;
+}
+
+
+void ERR_print_errors_fp(FILE* /*fp*/)
+{
+ // need ssl access to implement TODO:
+ //fprintf(fp, "%s", ssl.get_states().errorString_.c_str());
+}
+
+
+char* ERR_error_string(unsigned long /*err*/, char* buffer)
+{
+ // TODO:
+ static char* msg = "Not Implemented";
+ if (buffer)
+ return strncpy(buffer, msg, strlen(msg));
+
+ return msg;
+}
+
+
+const char* X509_verify_cert_error_string(long /* error */)
+{
+ // TODO:
+ static const char* msg = "Not Implemented";
+ return msg;
+}
+
+
+const EVP_MD* EVP_md5(void)
+{
+ // TODO: FIX add to some list for destruction
+ return new MD5;
+}
+
+
+const EVP_CIPHER* EVP_des_ede3_cbc(void)
+{
+ // TODO: FIX add to some list for destruction
+ return new DES_EDE;
+}
+
+
+int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt,
+ const byte* data, int sz, int count, byte* key, byte* iv)
+{
+ EVP_MD* myMD = const_cast<EVP_MD*>(md);
+ uint digestSz = myMD->get_digestSize();
+ byte digest[SHA_LEN]; // max size
+
+ int keyLen = type->get_keySize();
+ int ivLen = type->get_ivSize();
+ int keyLeft = keyLen;
+ int ivLeft = ivLen;
+ int keyOutput = 0;
+
+ while (keyOutput < (keyLen + ivLen)) {
+ int digestLeft = digestSz;
+ // D_(i - 1)
+ if (keyOutput) // first time D_0 is empty
+ myMD->update(digest, digestSz);
+ // data
+ myMD->update(data, sz);
+ // salt
+ if (salt)
+ myMD->update(salt, EVP_SALT_SZ);
+ myMD->get_digest(digest);
+ // count
+ for (int j = 1; j < count; j++) {
+ myMD->update(digest, digestSz);
+ myMD->get_digest(digest);
+ }
+
+ if (keyLeft) {
+ int store = min(keyLeft, static_cast<int>(digestSz));
+ memcpy(&key[keyLen - keyLeft], digest, store);
+
+ keyOutput += store;
+ keyLeft -= store;
+ digestLeft -= store;
+ }
+
+ if (ivLeft && digestLeft) {
+ int store = min(ivLeft, digestLeft);
+ memcpy(&iv[ivLen - ivLeft], digest, store);
+
+ keyOutput += store;
+ ivLeft -= store;
+ }
+ }
+ assert(keyOutput == (keyLen + ivLen));
+ return keyOutput;
+}
+
+
+
+void DES_set_key_unchecked(const_DES_cblock* key, DES_key_schedule* schedule)
+{
+ memcpy(schedule, key, sizeof(const_DES_cblock));
+}
+
+
+void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz,
+ DES_key_schedule* ks1, DES_key_schedule* ks2,
+ DES_key_schedule* ks3, DES_cblock* ivec, int enc)
+{
+ DES_EDE des;
+ byte key[DES_EDE_KEY_SZ];
+
+ memcpy(key, *ks1, DES_BLOCK);
+ memcpy(&key[DES_BLOCK], *ks2, DES_BLOCK);
+ memcpy(&key[DES_BLOCK * 2], *ks3, DES_BLOCK);
+
+ if (enc) {
+ des.set_encryptKey(key, *ivec);
+ des.encrypt(output, input, sz);
+ }
+ else {
+ des.set_decryptKey(key, *ivec);
+ des.decrypt(output, input, sz);
+ }
+}
+
+
+ // functions for stunnel
+
+ void RAND_screen()
+ {
+ // TODO:
+ }
+
+
+ const char* RAND_file_name(char*, size_t)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int RAND_write_file(const char*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int RAND_load_file(const char*, long)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void RSA_free(RSA*)
+ {
+ // TODO:
+ }
+
+
+ RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_file(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*, X509_OBJECT*)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ X509_STORE* X509_STORE_new(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+ char* SSL_alert_type_string_long(int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_alert_desc_string_long(int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_state_string_long(SSL*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int))
+ {
+ // TDOD:
+ }
+
+
+ long SSL_CTX_set_session_cache_mode(SSL_CTX*, long)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ long SSL_CTX_set_timeout(SSL_CTX*, long)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb)
+ {
+ // TDOD:
+ }
+
+
+ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_set_rfd(SSL*, int)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_set_wfd(SSL*, int)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_pending(SSL*)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_want_read(SSL*)
+ {
+ return 0; // TODO:
+ }
+
+
+ int SSL_want_write(SSL*)
+ {
+ return 0; // TODO:
+ }
+
+
+ void SSL_set_shutdown(SSL*, int)
+ {
+ // TODO:
+ }
+
+
+ SSL_CIPHER* SSL_get_current_cipher(SSL*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_CIPHER_description(SSL_CIPHER*, char*, int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void SSLeay_add_ssl_algorithms() // compatibility only
+ {}
+
+
+ void ERR_remove_state(unsigned long)
+ {
+ // TODO:
+ }
+
+
+ int ERR_GET_REASON(int l)
+ {
+ return l & 0xfff;
+ }
+
+
+ unsigned long ERR_peek_error()
+ {
+ return 0; // TODO:
+ }
+
+
+ unsigned long ERR_get_error()
+ {
+ return ERR_peek_error();
+ }
+
+
+ // end stunnel needs
+
+
+} // namespace
diff --git a/extra/yassl/src/timer.cpp b/extra/yassl/src/timer.cpp
new file mode 100644
index 00000000000..49e7bb36776
--- /dev/null
+++ b/extra/yassl/src/timer.cpp
@@ -0,0 +1,82 @@
+ /* timer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* timer.cpp implements a high res and low res timer
+ *
+*/
+
+#include "runtime.hpp"
+#include "timer.hpp"
+
+namespace yaSSL {
+
+#ifdef WIN32
+
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+
+ timer_d timer()
+ {
+ static bool init(false);
+ static LARGE_INTEGER freq;
+
+ if (!init) {
+ QueryPerformanceFrequency(&freq);
+ init = true;
+ }
+
+ LARGE_INTEGER count;
+ QueryPerformanceCounter(&count);
+
+ return static_cast<double>(count.QuadPart) / freq.QuadPart;
+ }
+
+
+ uint lowResTimer()
+ {
+ return static_cast<uint>(timer());
+ }
+
+#else // WIN32
+
+ #include <sys/time.h>
+
+ timer_d timer()
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ return static_cast<double>(tv.tv_sec)
+ + static_cast<double>(tv.tv_usec) / 1000000;
+ }
+
+
+ uint lowResTimer()
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ return tv.tv_sec;
+ }
+
+
+#endif // WIN32
+} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp
new file mode 100644
index 00000000000..c53aef2068d
--- /dev/null
+++ b/extra/yassl/src/yassl_error.cpp
@@ -0,0 +1,53 @@
+/* yassl_error.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL error implements and an exception class
+ */
+
+#include "runtime.hpp"
+#include "yassl_error.hpp"
+
+namespace yaSSL {
+
+
+Error::Error(const char* s, YasslError e, Library l)
+ : mySTL::runtime_error(s), error_(e), lib_(l)
+{
+}
+
+
+YasslError Error::get_number() const
+{
+ return error_;
+}
+
+
+Library Error::get_lib() const
+{
+
+ return lib_;
+}
+
+
+
+
+} // namespace yaSSL
diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp
new file mode 100644
index 00000000000..07310546b4c
--- /dev/null
+++ b/extra/yassl/src/yassl_imp.cpp
@@ -0,0 +1,2093 @@
+/* yassl_imp.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* yaSSL source implements all SSL.v3 secification structures.
+ */
+
+#include "runtime.hpp"
+#include "yassl_int.hpp"
+#include "handshake.hpp"
+
+#include "asn.hpp" // provide crypto wrapper??
+
+
+namespace yaSSL {
+
+
+namespace { // locals
+
+bool isTLS(ProtocolVersion pv)
+{
+ if (pv.major_ >= 3 && pv.minor_ >= 1)
+ return true;
+
+ return false;
+}
+
+
+} // namespace (locals)
+
+
+void hashHandShake(SSL&, const input_buffer&, uint);
+
+
+ProtocolVersion::ProtocolVersion(uint8 maj, uint8 min)
+ : major_(maj), minor_(min)
+{}
+
+
+// construct key exchange with known ssl parms
+void ClientKeyExchange::createKey(SSL& ssl)
+{
+ const ClientKeyFactory& ckf = ssl.getFactory().getClientKey();
+ client_key_ = ckf.CreateObject(ssl.getSecurity().get_parms().kea_);
+
+ if (!client_key_)
+ ssl.SetError(factory_error);
+}
+
+
+// construct key exchange with known ssl parms
+void ServerKeyExchange::createKey(SSL& ssl)
+{
+ const ServerKeyFactory& skf = ssl.getFactory().getServerKey();
+ server_key_ = skf.CreateObject(ssl.getSecurity().get_parms().kea_);
+
+ if (!server_key_)
+ ssl.SetError(factory_error);
+}
+
+
+// build/set PreMaster secret and encrypt, client side
+void EncryptedPreMasterSecret::build(SSL& ssl)
+{
+ opaque tmp[SECRET_LEN];
+ memset(tmp, 0, sizeof(tmp));
+ ssl.getCrypto().get_random().Fill(tmp, SECRET_LEN);
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ tmp[0] = pv.major_;
+ tmp[1] = pv.minor_;
+ ssl.set_preMaster(tmp, SECRET_LEN);
+
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+ bool tls = ssl.isTLS(); // if TLS, put length for encrypted data
+ alloc(rsa.get_cipherLength() + (tls ? 2 : 0));
+ byte* holder = secret_;
+ if (tls) {
+ byte len[2];
+ c16toa(rsa.get_cipherLength(), len);
+ memcpy(secret_, len, sizeof(len));
+ holder += 2;
+ }
+ rsa.encrypt(holder, tmp, SECRET_LEN, ssl.getCrypto().get_random());
+}
+
+
+// build/set premaster and Client Public key, client side
+void ClientDiffieHellmanPublic::build(SSL& ssl)
+{
+ DiffieHellman& dhServer = ssl.useCrypto().use_dh();
+ DiffieHellman dhClient(dhServer);
+
+ uint keyLength = dhClient.get_agreedKeyLength(); // pub and agree same
+
+ alloc(keyLength, true);
+ dhClient.makeAgreement(dhServer.get_publicKey());
+ c16toa(keyLength, Yc_);
+ memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength);
+
+ ssl.set_preMaster(dhClient.get_agreedKey(), keyLength);
+}
+
+
+// build server exhange, server side
+void DH_Server::build(SSL& ssl)
+{
+ DiffieHellman& dhServer = ssl.useCrypto().use_dh();
+
+ int pSz, gSz, pubSz;
+ dhServer.set_sizes(pSz, gSz, pubSz);
+ dhServer.get_parms(parms_.alloc_p(pSz), parms_.alloc_g(gSz),
+ parms_.alloc_pub(pubSz));
+
+ short sigSz = 0;
+ mySTL::auto_ptr<Auth> auth;
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo)
+ auth.reset(new (ys) RSA(cert.get_privateKey(),
+ cert.get_privateKeyLength(), false));
+ else {
+ auth.reset(new (ys) DSS(cert.get_privateKey(),
+ cert.get_privateKeyLength(), false));
+ sigSz += DSS_ENCODED_EXTRA;
+ }
+
+
+ sigSz += auth->get_signatureLength();
+
+
+ length_ = 8; // pLen + gLen + YsLen + SigLen
+ length_ += pSz + gSz + pubSz + sigSz;
+
+ output_buffer tmp(length_);
+ byte len[2];
+ // P
+ c16toa(pSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_p(), pSz);
+ // G
+ c16toa(gSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_g(), gSz);
+ // Ys
+ c16toa(pubSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(parms_.get_pub(), pubSz);
+
+ // Sig
+ byte hash[FINISHED_SZ];
+ MD5 md5;
+ SHA sha;
+ signature_ = new (ys) byte[sigSz];
+
+ const Connection& conn = ssl.getSecurity().get_connection();
+ // md5
+ md5.update(conn.client_random_, RAN_LEN);
+ md5.update(conn.server_random_, RAN_LEN);
+ md5.update(tmp.get_buffer(), tmp.get_size());
+ md5.get_digest(hash);
+
+ // sha
+ sha.update(conn.client_random_, RAN_LEN);
+ sha.update(conn.server_random_, RAN_LEN);
+ sha.update(tmp.get_buffer(), tmp.get_size());
+ sha.get_digest(&hash[MD5_LEN]);
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo)
+ auth->sign(signature_, hash, sizeof(hash),
+ ssl.getCrypto().get_random());
+ else {
+ auth->sign(signature_, &hash[MD5_LEN], SHA_LEN,
+ ssl.getCrypto().get_random());
+ byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA];
+ TaoCrypt::EncodeDSA_Signature(signature_, encoded);
+ memcpy(signature_, encoded, sizeof(encoded));
+ }
+
+ c16toa(sigSz, len);
+ tmp.write(len, sizeof(len));
+ tmp.write(signature_, sigSz);
+
+ // key message
+ keyMessage_ = new (ys) opaque[length_];
+ memcpy(keyMessage_, tmp.get_buffer(), tmp.get_size());
+}
+
+
+// read PreMaster secret and decrypt, server side
+void EncryptedPreMasterSecret::read(SSL& ssl, input_buffer& input)
+{
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+ uint16 cipherLen = rsa.get_cipherLength();
+ if (ssl.isTLS()) {
+ byte len[2];
+ input.read(len, sizeof(len));
+ ato16(len, cipherLen);
+ }
+ alloc(cipherLen);
+ input.read(secret_, length_);
+
+ opaque preMasterSecret[SECRET_LEN];
+ rsa.decrypt(preMasterSecret, secret_, length_,
+ ssl.getCrypto().get_random());
+
+ ssl.set_preMaster(preMasterSecret, SECRET_LEN);
+ ssl.makeMasterSecret();
+}
+
+
+EncryptedPreMasterSecret::EncryptedPreMasterSecret()
+ : secret_(0), length_(0)
+{}
+
+
+EncryptedPreMasterSecret::~EncryptedPreMasterSecret()
+{
+ delete[] secret_;
+}
+
+
+int EncryptedPreMasterSecret::get_length() const
+{
+ return length_;
+}
+
+
+opaque* EncryptedPreMasterSecret::get_clientKey() const
+{
+ return secret_;
+}
+
+
+void EncryptedPreMasterSecret::alloc(int sz)
+{
+ length_ = sz;
+ secret_ = new (ys) opaque[sz];
+}
+
+
+// read client's public key, server side
+void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input)
+{
+ DiffieHellman& dh = ssl.useCrypto().use_dh();
+
+ uint16 keyLength;
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, keyLength);
+
+ alloc(keyLength);
+ input.read(Yc_, length_);
+ dh.makeAgreement(Yc_);
+
+ ssl.set_preMaster(dh.get_agreedKey(), keyLength);
+ ssl.makeMasterSecret();
+}
+
+
+ClientDiffieHellmanPublic::ClientDiffieHellmanPublic()
+ : length_(0), Yc_(0)
+{}
+
+
+ClientDiffieHellmanPublic::~ClientDiffieHellmanPublic()
+{
+ delete[] Yc_;
+}
+
+
+int ClientDiffieHellmanPublic::get_length() const
+{
+ return length_;
+}
+
+
+opaque* ClientDiffieHellmanPublic::get_clientKey() const
+{
+ return Yc_;
+}
+
+
+void ClientDiffieHellmanPublic::alloc(int sz, bool offset)
+{
+ length_ = sz + (offset ? KEY_OFFSET : 0);
+ Yc_ = new (ys) opaque[length_];
+}
+
+
+// read server's p, g, public key and sig, client side
+void DH_Server::read(SSL& ssl, input_buffer& input)
+{
+ uint16 length, messageTotal = 6; // pSz + gSz + pubSz
+ byte tmp[2];
+
+ // p
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_p(length), length);
+
+ // g
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_g(length), length);
+
+ // pub
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+ messageTotal += length;
+
+ input.read(parms_.alloc_pub(length), length);
+
+ // save message for hash verify
+ input_buffer message(messageTotal);
+ input.set_current(input.get_current() - messageTotal);
+ input.read(message.get_buffer(), messageTotal);
+ message.add_size(messageTotal);
+
+ // signature
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, length);
+
+ signature_ = new (ys) byte[length];
+ input.read(signature_, length);
+
+ // verify signature
+ byte hash[FINISHED_SZ];
+ MD5 md5;
+ SHA sha;
+
+ const Connection& conn = ssl.getSecurity().get_connection();
+ // md5
+ md5.update(conn.client_random_, RAN_LEN);
+ md5.update(conn.server_random_, RAN_LEN);
+ md5.update(message.get_buffer(), message.get_size());
+ md5.get_digest(hash);
+
+ // sha
+ sha.update(conn.client_random_, RAN_LEN);
+ sha.update(conn.server_random_, RAN_LEN);
+ sha.update(message.get_buffer(), message.get_size());
+ sha.get_digest(&hash[MD5_LEN]);
+
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) {
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!rsa.verify(hash, sizeof(hash), signature_, length))
+ ssl.SetError(verify_error);
+ }
+ else {
+ byte decodedSig[DSS_SIG_SZ];
+ length = TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, length);
+
+ DSS dss(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!dss.verify(&hash[MD5_LEN], SHA_LEN, decodedSig, length))
+ ssl.SetError(verify_error);
+ }
+
+ // save input
+ ssl.useCrypto().SetDH(new (ys) DiffieHellman(parms_.get_p(),
+ parms_.get_pSize(), parms_.get_g(), parms_.get_gSize(),
+ parms_.get_pub(), parms_.get_pubSize(),
+ ssl.getCrypto().get_random()));
+}
+
+
+DH_Server::DH_Server()
+ : signature_(0), length_(0), keyMessage_(0)
+{}
+
+
+DH_Server::~DH_Server()
+{
+ delete[] keyMessage_;
+ delete[] signature_;
+}
+
+
+int DH_Server::get_length() const
+{
+ return length_;
+}
+
+
+opaque* DH_Server::get_serverKey() const
+{
+ return keyMessage_;
+}
+
+
+// set available suites
+Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers,
+ ProtocolVersion pv) : entity_(ce)
+{
+ pending_ = true; // suite not set yet
+
+ if (ciphers.setSuites_) { // use user set list
+ suites_size_ = ciphers.suiteSz_;
+ memcpy(suites_, ciphers.suites_, ciphers.suiteSz_);
+ SetCipherNames();
+ }
+ else
+ SetSuites(pv); // defaults
+}
+
+
+void Parameters::SetSuites(ProtocolVersion pv)
+{
+ int i = 0;
+ // available suites, best first
+ // when adding more, make sure cipher_names is updated and
+ // MAX_CIPHER_LIST is big enough
+
+ if (isTLS(pv)) {
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_256_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_128_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_RSA_WITH_3DES_EDE_CBC_RMD160;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_RMD160;
+ suites_[i++] = 0x00;
+ suites_[i++] = TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160;
+ }
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_RC4_128_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_RC4_128_MD5;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_RSA_WITH_DES_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_RSA_WITH_DES_CBC_SHA;
+ suites_[i++] = 0x00;
+ suites_[i++] = SSL_DHE_DSS_WITH_DES_CBC_SHA;
+
+ suites_size_ = i;
+
+ SetCipherNames();
+}
+
+
+void Parameters::SetCipherNames()
+{
+ const int suites = suites_size_ / 2;
+ int pos = 0;
+
+ for (int j = 0; j < suites; j++) {
+ int index = suites_[j*2 + 1]; // every other suite is suite id
+ int len = strlen(cipher_names[index]);
+ memcpy(&cipher_list_[pos], cipher_names[index], len);
+ pos += len;
+ cipher_list_[pos++] = ':';
+ }
+ if (suites)
+ cipher_list_[--pos] = 0;
+}
+
+
+// input operator for RecordLayerHeader, adjust stream
+input_buffer& operator>>(input_buffer& input, RecordLayerHeader& hdr)
+{
+ hdr.type_ = ContentType(input[AUTO]);
+ hdr.version_.major_ = input[AUTO];
+ hdr.version_.minor_ = input[AUTO];
+
+ // length
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, hdr.length_);
+
+ return input;
+}
+
+
+// output operator for RecordLayerHeader
+output_buffer& operator<<(output_buffer& output, const RecordLayerHeader& hdr)
+{
+ output[AUTO] = hdr.type_;
+ output[AUTO] = hdr.version_.major_;
+ output[AUTO] = hdr.version_.minor_;
+
+ // length
+ byte tmp[2];
+ c16toa(hdr.length_, tmp);
+ output[AUTO] = tmp[0];
+ output[AUTO] = tmp[1];
+
+ return output;
+}
+
+
+// virtual input operator for Messages
+input_buffer& operator>>(input_buffer& input, Message& msg)
+{
+ return msg.set(input);
+}
+
+// virtual output operator for Messages
+output_buffer& operator<<(output_buffer& output, const Message& msg)
+{
+ return msg.get(output);
+}
+
+
+// input operator for HandShakeHeader
+input_buffer& operator>>(input_buffer& input, HandShakeHeader& hs)
+{
+ hs.type_ = HandShakeType(input[AUTO]);
+
+ hs.length_[0] = input[AUTO];
+ hs.length_[1] = input[AUTO];
+ hs.length_[2] = input[AUTO];
+
+ return input;
+}
+
+
+// output operator for HandShakeHeader
+output_buffer& operator<<(output_buffer& output, const HandShakeHeader& hdr)
+{
+ output[AUTO] = hdr.type_;
+ output.write(hdr.length_, sizeof(hdr.length_));
+ return output;
+}
+
+
+// HandShake Header Processing function
+void HandShakeHeader::Process(input_buffer& input, SSL& ssl)
+{
+ ssl.verifyState(*this);
+ const HandShakeFactory& hsf = ssl.getFactory().getHandShake();
+ mySTL::auto_ptr<HandShakeBase> hs(hsf.CreateObject(type_));
+ if (!hs.get()) {
+ ssl.SetError(factory_error);
+ return;
+ }
+ hashHandShake(ssl, input, c24to32(length_));
+
+ input >> *hs;
+ hs->Process(input, ssl);
+}
+
+
+ContentType HandShakeHeader::get_type() const
+{
+ return handshake;
+}
+
+
+uint16 HandShakeHeader::get_length() const
+{
+ return c24to32(length_);
+}
+
+
+HandShakeType HandShakeHeader::get_handshakeType() const
+{
+ return type_;
+}
+
+
+void HandShakeHeader::set_type(HandShakeType hst)
+{
+ type_ = hst;
+}
+
+
+void HandShakeHeader::set_length(uint32 u32)
+{
+ c32to24(u32, length_);
+}
+
+
+input_buffer& HandShakeHeader::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& HandShakeHeader::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+
+int HandShakeBase::get_length() const
+{
+ return length_;
+}
+
+
+void HandShakeBase::set_length(int l)
+{
+ length_ = l;
+}
+
+
+// for building buffer's type field
+HandShakeType HandShakeBase::get_type() const
+{
+ return no_shake;
+}
+
+
+input_buffer& HandShakeBase::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& HandShakeBase::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+void HandShakeBase::Process(input_buffer&, SSL&)
+{}
+
+
+input_buffer& HelloRequest::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& HelloRequest::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+void HelloRequest::Process(input_buffer&, SSL&)
+{}
+
+
+HandShakeType HelloRequest::get_type() const
+{
+ return hello_request;
+}
+
+
+// input operator for CipherSpec
+input_buffer& operator>>(input_buffer& input, ChangeCipherSpec& cs)
+{
+ cs.type_ = CipherChoice(input[AUTO]);
+ return input;
+}
+
+// output operator for CipherSpec
+output_buffer& operator<<(output_buffer& output, const ChangeCipherSpec& cs)
+{
+ output[AUTO] = cs.type_;
+ return output;
+}
+
+
+ChangeCipherSpec::ChangeCipherSpec()
+ : type_(change_cipher_spec_choice)
+{}
+
+
+input_buffer& ChangeCipherSpec::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ChangeCipherSpec::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+ContentType ChangeCipherSpec::get_type() const
+{
+ return change_cipher_spec;
+}
+
+
+uint16 ChangeCipherSpec::get_length() const
+{
+ return SIZEOF_ENUM;
+}
+
+
+// CipherSpec processing handler
+void ChangeCipherSpec::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useSecurity().use_parms().pending_ = false;
+ if (ssl.getSecurity().get_resuming()) {
+ if (ssl.getSecurity().get_parms().entity_ == client_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), server); // server
+ }
+ else if (ssl.getSecurity().get_parms().entity_ == server_end)
+ buildFinished(ssl, ssl.useHashes().use_verify(), client); // client
+}
+
+
+Alert::Alert(AlertLevel al, AlertDescription ad)
+ : level_(al), description_(ad)
+{}
+
+
+ContentType Alert::get_type() const
+{
+ return alert;
+}
+
+
+uint16 Alert::get_length() const
+{
+ return SIZEOF_ENUM * 2;
+}
+
+
+input_buffer& Alert::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& Alert::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for Alert
+input_buffer& operator>>(input_buffer& input, Alert& a)
+{
+ a.level_ = AlertLevel(input[AUTO]);
+ a.description_ = AlertDescription(input[AUTO]);
+
+ return input;
+}
+
+
+// output operator for Alert
+output_buffer& operator<<(output_buffer& output, const Alert& a)
+{
+ output[AUTO] = a.level_;
+ output[AUTO] = a.description_;
+ return output;
+}
+
+
+// Alert processing handler
+void Alert::Process(input_buffer& input, SSL& ssl)
+{
+ if (ssl.getSecurity().get_parms().pending_ == false) { // encrypted alert
+ int aSz = get_length(); // alert size already read on input
+ opaque verify[SHA_LEN];
+ const opaque* data = input.get_buffer() + input.get_current() - aSz;
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verify, data, aSz, alert, true);
+ else
+ hmac(ssl, verify, data, aSz, alert, true);
+
+ // read mac and fill
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ opaque mac[SHA_LEN];
+ input.read(mac, digestSz);
+
+ opaque fill;
+ int padSz = ssl.getSecurity().get_parms().encrypt_size_ - aSz -
+ digestSz;
+ for (int i = 0; i < padSz; i++)
+ fill = input[AUTO];
+
+ // verify
+ if (memcmp(mac, verify, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+ }
+ if (level_ == fatal) {
+ ssl.useStates().useRecord() = recordNotReady;
+ ssl.useStates().useHandShake() = handShakeNotReady;
+ ssl.SetError(YasslError(description_));
+ }
+}
+
+
+Data::Data()
+ : length_(0), buffer_(0), write_buffer_(0)
+{}
+
+
+Data::Data(uint16 len, opaque* b)
+ : length_(len), buffer_(b), write_buffer_(0)
+{}
+
+
+Data::Data(uint16 len, const opaque* w)
+ : length_(len), buffer_(0), write_buffer_(w)
+{}
+
+input_buffer& Data::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& Data::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+ContentType Data::get_type() const
+{
+ return application_data;
+}
+
+
+uint16 Data::get_length() const
+{
+ return length_;
+}
+
+
+const opaque* Data::get_buffer() const
+{
+ return write_buffer_;
+}
+
+
+void Data::set_length(uint16 l)
+{
+ length_ = l;
+}
+
+opaque* Data::set_buffer()
+{
+ return buffer_;
+}
+
+
+// output operator for Data
+output_buffer& operator<<(output_buffer& output, const Data& data)
+{
+ output.write(data.write_buffer_, data.length_);
+ return output;
+}
+
+
+// Process handler for Data
+void Data::Process(input_buffer& input, SSL& ssl)
+{
+ int msgSz = ssl.getSecurity().get_parms().encrypt_size_;
+ int pad = 0, padByte = 0;
+ if (ssl.getSecurity().get_parms().cipher_type_ == block) {
+ pad = *(input.get_buffer() + input.get_current() + msgSz - 1);
+ padByte = 1;
+ }
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ int dataSz = msgSz - digestSz - pad - padByte;
+ opaque verify[SHA_LEN];
+
+ // read data
+ if (dataSz) {
+ input_buffer* data;
+ ssl.addData(data = new (ys) input_buffer(dataSz));
+ input.read(data->get_buffer(), dataSz);
+ data->add_size(dataSz);
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verify, data->get_buffer(), dataSz, application_data,
+ true);
+ else
+ hmac(ssl, verify, data->get_buffer(), dataSz, application_data,
+ true);
+ }
+
+ // read mac and fill
+ opaque mac[SHA_LEN];
+ opaque fill;
+ input.read(mac, digestSz);
+ for (int i = 0; i < pad; i++)
+ fill = input[AUTO];
+ if (padByte)
+ fill = input[AUTO];
+
+ // verify
+ if (dataSz) {
+ if (memcmp(mac, verify, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+ }
+ else
+ ssl.get_SEQIncrement(true); // even though no data, increment verify
+}
+
+
+// virtual input operator for HandShakes
+input_buffer& operator>>(input_buffer& input, HandShakeBase& hs)
+{
+ return hs.set(input);
+}
+
+
+// virtual output operator for HandShakes
+output_buffer& operator<<(output_buffer& output, const HandShakeBase& hs)
+{
+ return hs.get(output);
+}
+
+
+Certificate::Certificate(const x509* cert) : cert_(cert)
+{
+ set_length(cert_->get_length() + 2 * CERT_HEADER); // list and cert size
+}
+
+
+const opaque* Certificate::get_buffer() const
+{
+ return cert_->get_buffer();
+}
+
+
+// output operator for Certificate
+output_buffer& operator<<(output_buffer& output, const Certificate& cert)
+{
+ uint sz = cert.get_length() - 2 * CERT_HEADER;
+ opaque tmp[CERT_HEADER];
+
+ c32to24(sz + CERT_HEADER, tmp);
+ output.write(tmp, CERT_HEADER);
+ c32to24(sz, tmp);
+ output.write(tmp, CERT_HEADER);
+ output.write(cert.get_buffer(), sz);
+
+ return output;
+}
+
+
+// certificate processing handler
+void Certificate::Process(input_buffer& input, SSL& ssl)
+{
+ CertManager& cm = ssl.useCrypto().use_certManager();
+
+ uint32 list_sz;
+ byte tmp[3];
+
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ tmp[2] = input[AUTO];
+ c24to32(tmp, list_sz);
+
+ while (list_sz) {
+ // cert size
+ uint32 cert_sz;
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ tmp[2] = input[AUTO];
+ c24to32(tmp, cert_sz);
+
+ x509* myCert;
+ cm.AddPeerCert(myCert = new (ys) x509(cert_sz));
+ input.read(myCert->use_buffer(), myCert->get_length());
+
+ list_sz -= cert_sz + CERT_HEADER;
+ }
+ if (int err = cm.Validate())
+ ssl.SetError(YasslError(err));
+ else if (ssl.getSecurity().get_parms().entity_ == client_end)
+ ssl.useStates().useClient() = serverCertComplete;
+}
+
+
+Certificate::Certificate()
+ : cert_(0)
+{}
+
+
+input_buffer& Certificate::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& Certificate::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType Certificate::get_type() const
+{
+ return certificate;
+}
+
+
+ServerDHParams::ServerDHParams()
+ : pSz_(0), gSz_(0), pubSz_(0), p_(0), g_(0), Ys_(0)
+{}
+
+
+ServerDHParams::~ServerDHParams()
+{
+ delete[] Ys_;
+ delete[] g_;
+ delete[] p_;
+}
+
+
+int ServerDHParams::get_pSize() const
+{
+ return pSz_;
+}
+
+
+int ServerDHParams::get_gSize() const
+{
+ return gSz_;
+}
+
+
+int ServerDHParams::get_pubSize() const
+{
+ return pubSz_;
+}
+
+
+const opaque* ServerDHParams::get_p() const
+{
+ return p_;
+}
+
+
+const opaque* ServerDHParams::get_g() const
+{
+ return g_;
+}
+
+
+const opaque* ServerDHParams::get_pub() const
+{
+ return Ys_;
+}
+
+
+opaque* ServerDHParams::alloc_p(int sz)
+{
+ p_ = new (ys) opaque[pSz_ = sz];
+ return p_;
+}
+
+
+opaque* ServerDHParams::alloc_g(int sz)
+{
+ g_ = new (ys) opaque[gSz_ = sz];
+ return g_;
+}
+
+
+opaque* ServerDHParams::alloc_pub(int sz)
+{
+ Ys_ = new (ys) opaque[pubSz_ = sz];
+ return Ys_;
+}
+
+
+int ServerKeyBase::get_length() const
+{
+ return 0;
+}
+
+
+opaque* ServerKeyBase::get_serverKey() const
+{
+ return 0;
+}
+
+
+// input operator for ServerHello
+input_buffer& operator>>(input_buffer& input, ServerHello& hello)
+{
+ // Protocol
+ hello.server_version_.major_ = input[AUTO];
+ hello.server_version_.minor_ = input[AUTO];
+
+ // Random
+ input.read(hello.random_, RAN_LEN);
+
+ // Session
+ hello.id_len_ = input[AUTO];
+ input.read(hello.session_id_, ID_LEN);
+
+ // Suites
+ hello.cipher_suite_[0] = input[AUTO];
+ hello.cipher_suite_[1] = input[AUTO];
+
+ // Compression
+ hello.compression_method_ = CompressionMethod(input[AUTO]);
+
+ return input;
+}
+
+
+// output operator for ServerHello
+output_buffer& operator<<(output_buffer& output, const ServerHello& hello)
+{
+ // Protocol
+ output[AUTO] = hello.server_version_.major_;
+ output[AUTO] = hello.server_version_.minor_;
+
+ // Random
+ output.write(hello.random_, RAN_LEN);
+
+ // Session
+ output[AUTO] = hello.id_len_;
+ output.write(hello.session_id_, ID_LEN);
+
+ // Suites
+ output[AUTO] = hello.cipher_suite_[0];
+ output[AUTO] = hello.cipher_suite_[1];
+
+ // Compression
+ output[AUTO] = hello.compression_method_;
+
+ return output;
+}
+
+
+// Server Hello processing handler
+void ServerHello::Process(input_buffer&, SSL& ssl)
+{
+ ssl.set_pending(cipher_suite_[1]);
+ ssl.set_random(random_, server_end);
+ ssl.set_sessionID(session_id_);
+
+ if (ssl.getSecurity().get_resuming())
+ if (memcmp(session_id_, ssl.getSecurity().get_resume().GetID(),
+ ID_LEN) == 0) {
+ ssl.set_masterSecret(ssl.getSecurity().get_resume().GetSecret());
+ if (ssl.isTLS())
+ ssl.deriveTLSKeys();
+ else
+ ssl.deriveKeys();
+ ssl.useStates().useClient() = serverHelloDoneComplete;
+ return;
+ }
+ else {
+ ssl.useSecurity().set_resuming(false);
+ ssl.useLog().Trace("server denied resumption");
+ }
+ ssl.useStates().useClient() = serverHelloComplete;
+}
+
+
+ServerHello::ServerHello()
+{
+ memset(random_, 0, RAN_LEN);
+ memset(session_id_, 0, ID_LEN);
+}
+
+
+ServerHello::ServerHello(ProtocolVersion pv)
+ : server_version_(pv)
+{
+ memset(random_, 0, RAN_LEN);
+ memset(session_id_, 0, ID_LEN);
+}
+
+
+input_buffer& ServerHello::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ServerHello::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ServerHello::get_type() const
+{
+ return server_hello;
+}
+
+
+const opaque* ServerHello::get_random() const
+{
+ return random_;
+}
+
+
+// Server Hello Done processing handler
+void ServerHelloDone::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useStates().useClient() = serverHelloDoneComplete;
+}
+
+
+ServerHelloDone::ServerHelloDone()
+{
+ set_length(0);
+}
+
+
+input_buffer& ServerHelloDone::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& ServerHelloDone::get(output_buffer& out) const
+{
+ return out;
+}
+
+
+HandShakeType ServerHelloDone::get_type() const
+{
+ return server_hello_done;
+}
+
+
+int ClientKeyBase::get_length() const
+{
+ return 0;
+}
+
+
+opaque* ClientKeyBase::get_clientKey() const
+{
+ return 0;
+}
+
+
+// input operator for Client Hello
+input_buffer& operator>>(input_buffer& input, ClientHello& hello)
+{
+ // Protocol
+ hello.client_version_.major_ = input[AUTO];
+ hello.client_version_.minor_ = input[AUTO];
+
+ // Random
+ input.read(hello.random_, RAN_LEN);
+
+ // Session
+ hello.id_len_ = input[AUTO];
+ if (hello.id_len_) input.read(hello.session_id_, ID_LEN);
+
+ // Suites
+ byte tmp[2];
+ tmp[0] = input[AUTO];
+ tmp[1] = input[AUTO];
+ ato16(tmp, hello.suite_len_);
+ input.read(hello.cipher_suites_, hello.suite_len_);
+
+ // Compression
+ hello.comp_len_ = input[AUTO];
+ hello.compression_methods_ = CompressionMethod(input[AUTO]);
+
+ return input;
+}
+
+
+// output operaotr for Client Hello
+output_buffer& operator<<(output_buffer& output, const ClientHello& hello)
+{
+ // Protocol
+ output[AUTO] = hello.client_version_.major_;
+ output[AUTO] = hello.client_version_.minor_;
+
+ // Random
+ output.write(hello.random_, RAN_LEN);
+
+ // Session
+ output[AUTO] = hello.id_len_;
+ if (hello.id_len_) output.write(hello.session_id_, ID_LEN);
+
+ // Suites
+ byte tmp[2];
+ c16toa(hello.suite_len_, tmp);
+ output[AUTO] = tmp[0];
+ output[AUTO] = tmp[1];
+ output.write(hello.cipher_suites_, hello.suite_len_);
+
+ // Compression
+ output[AUTO] = hello.comp_len_;
+ output[AUTO] = hello.compression_methods_;
+
+ return output;
+}
+
+
+// Client Hello processing handler
+void ClientHello::Process(input_buffer&, SSL& ssl)
+{
+ if (ssl.isTLS() && client_version_.minor_ == 0) {
+ ssl.useSecurity().use_connection().TurnOffTLS();
+ ProtocolVersion pv = ssl.getSecurity().get_connection().version_;
+ ssl.useSecurity().use_parms().SetSuites(pv); // reset w/ SSL suites
+ }
+ ssl.set_random(random_, client_end);
+
+ while (id_len_) { // trying to resume
+ SSL_SESSION* session = GetSessions().lookup(session_id_);
+ if (!session) {
+ ssl.useLog().Trace("session lookup failed");
+ break;
+ }
+ ssl.set_session(session);
+ ssl.useSecurity().set_resuming(true);
+ ssl.matchSuite(session->GetSuite(), SUITE_LEN);
+ ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]);
+ ssl.set_masterSecret(session->GetSecret());
+
+ opaque serverRandom[RAN_LEN];
+ ssl.getCrypto().get_random().Fill(serverRandom, sizeof(serverRandom));
+ ssl.set_random(serverRandom, server_end);
+ if (ssl.isTLS())
+ ssl.deriveTLSKeys();
+ else
+ ssl.deriveKeys();
+ ssl.useStates().useServer() = clientKeyExchangeComplete;
+ return;
+ }
+ ssl.matchSuite(cipher_suites_, suite_len_);
+ ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]);
+
+ ssl.useStates().useServer() = clientHelloComplete;
+}
+
+
+input_buffer& ClientHello::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& ClientHello::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ClientHello::get_type() const
+{
+ return client_hello;
+}
+
+
+const opaque* ClientHello::get_random() const
+{
+ return random_;
+}
+
+
+ClientHello::ClientHello()
+{
+ memset(random_, 0, RAN_LEN);
+}
+
+
+ClientHello::ClientHello(ProtocolVersion pv)
+ : client_version_(pv)
+{
+ memset(random_, 0, RAN_LEN);
+}
+
+
+// output operator for ServerKeyExchange
+output_buffer& operator<<(output_buffer& output, const ServerKeyExchange& sk)
+{
+ output.write(sk.getKey(), sk.getKeyLength());
+ return output;
+}
+
+
+// Server Key Exchange processing handler
+void ServerKeyExchange::Process(input_buffer& input, SSL& ssl)
+{
+ createKey(ssl);
+ if (ssl.GetError()) return;
+ server_key_->read(ssl, input);
+
+ ssl.useStates().useClient() = serverKeyExchangeComplete;
+}
+
+
+ServerKeyExchange::ServerKeyExchange(SSL& ssl)
+{
+ createKey(ssl);
+}
+
+
+ServerKeyExchange::ServerKeyExchange()
+ : server_key_(0)
+{}
+
+
+ServerKeyExchange::~ServerKeyExchange()
+{
+ delete server_key_;
+}
+
+
+void ServerKeyExchange::build(SSL& ssl)
+{
+ server_key_->build(ssl);
+ set_length(server_key_->get_length());
+}
+
+
+const opaque* ServerKeyExchange::getKey() const
+{
+ return server_key_->get_serverKey();
+}
+
+
+int ServerKeyExchange::getKeyLength() const
+{
+ return server_key_->get_length();
+}
+
+
+input_buffer& ServerKeyExchange::set(input_buffer& in)
+{
+ return in; // process does
+}
+
+
+output_buffer& ServerKeyExchange::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ServerKeyExchange::get_type() const
+{
+ return server_key_exchange;
+}
+
+
+// CertificateRequest
+CertificateRequest::CertificateRequest()
+ : typeTotal_(0)
+{
+ memset(certificate_types_, 0, sizeof(certificate_types_));
+}
+
+
+CertificateRequest::~CertificateRequest()
+{
+
+ mySTL::for_each(certificate_authorities_.begin(),
+ certificate_authorities_.end(),
+ del_ptr_zero()) ;
+}
+
+
+void CertificateRequest::Build()
+{
+ certificate_types_[0] = rsa_sign;
+ certificate_types_[1] = dss_sign;
+
+ typeTotal_ = 2;
+
+ uint16 authCount = 0;
+ uint16 authSz = 0;
+
+ for (int j = 0; j < authCount; j++) {
+ int sz = REQUEST_HEADER + MIN_DIS_SIZE;
+ DistinguishedName dn;
+ certificate_authorities_.push_back(dn = new (ys) byte[sz]);
+
+ opaque tmp[REQUEST_HEADER];
+ c16toa(MIN_DIS_SIZE, tmp);
+ memcpy(dn, tmp, sizeof(tmp));
+
+ // fill w/ junk for now
+ memcpy(dn, tmp, MIN_DIS_SIZE);
+ authSz += sz;
+ }
+
+ set_length(SIZEOF_ENUM + typeTotal_ + REQUEST_HEADER + authSz);
+}
+
+
+input_buffer& CertificateRequest::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& CertificateRequest::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for CertificateRequest
+input_buffer& operator>>(input_buffer& input, CertificateRequest& request)
+{
+ // types
+ request.typeTotal_ = input[AUTO];
+ for (int i = 0; i < request.typeTotal_; i++)
+ request.certificate_types_[i] = ClientCertificateType(input[AUTO]);
+
+ byte tmp[REQUEST_HEADER];
+ input.read(tmp, sizeof(tmp));
+ uint16 sz;
+ ato16(tmp, sz);
+
+ // authorities
+ while (sz) {
+ uint16 dnSz;
+ input.read(tmp, sizeof(tmp));
+ ato16(tmp, dnSz);
+
+ DistinguishedName dn;
+ request.certificate_authorities_.push_back(dn = new (ys)
+ byte[REQUEST_HEADER + dnSz]);
+ memcpy(dn, tmp, REQUEST_HEADER);
+ input.read(&dn[REQUEST_HEADER], dnSz);
+
+ sz -= dnSz + REQUEST_HEADER;
+ }
+
+ return input;
+}
+
+
+// output operator for CertificateRequest
+output_buffer& operator<<(output_buffer& output,
+ const CertificateRequest& request)
+{
+ // types
+ output[AUTO] = request.typeTotal_;
+ for (int i = 0; i < request.typeTotal_; i++)
+ output[AUTO] = request.certificate_types_[i];
+
+ // authorities
+ opaque tmp[REQUEST_HEADER];
+ c16toa(request.get_length() - SIZEOF_ENUM -
+ request.typeTotal_ - REQUEST_HEADER, tmp);
+ output.write(tmp, sizeof(tmp));
+
+ mySTL::list<DistinguishedName>::const_iterator first =
+ request.certificate_authorities_.begin();
+ mySTL::list<DistinguishedName>::const_iterator last =
+ request.certificate_authorities_.end();
+ while (first != last) {
+ uint16 sz;
+ ato16(*first, sz);
+ output.write(*first, sz + REQUEST_HEADER);
+
+ ++first;
+ }
+
+ return output;
+}
+
+
+// CertificateRequest processing handler
+void CertificateRequest::Process(input_buffer&, SSL& ssl)
+{
+ ssl.useCrypto().use_certManager().setSendVerify();
+}
+
+
+HandShakeType CertificateRequest::get_type() const
+{
+ return certificate_request;
+}
+
+
+// CertificateVerify
+CertificateVerify::CertificateVerify() : signature_(0)
+{}
+
+
+CertificateVerify::~CertificateVerify()
+{
+ delete[] signature_;
+}
+
+
+void CertificateVerify::Build(SSL& ssl)
+{
+ build_certHashes(ssl, hashes_);
+
+ uint16 sz = 0;
+ byte len[VERIFY_HEADER];
+ mySTL::auto_ptr<byte> sig;
+
+ // sign
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+ if (cert.get_keyType() == rsa_sa_algo) {
+ RSA rsa(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+
+ sz = rsa.get_cipherLength() + VERIFY_HEADER;
+ sig.reset(new (ys) byte[sz]);
+
+ c16toa(sz - VERIFY_HEADER, len);
+ memcpy(sig.get(), len, VERIFY_HEADER);
+ rsa.sign(sig.get() + VERIFY_HEADER, hashes_.md5_, sizeof(Hashes),
+ ssl.getCrypto().get_random());
+ }
+ else { // DSA
+ DSS dss(cert.get_privateKey(), cert.get_privateKeyLength(), false);
+
+ sz = DSS_SIG_SZ + DSS_ENCODED_EXTRA + VERIFY_HEADER;
+ sig.reset(new (ys) byte[sz]);
+
+ c16toa(sz - VERIFY_HEADER, len);
+ memcpy(sig.get(), len, VERIFY_HEADER);
+ dss.sign(sig.get() + VERIFY_HEADER, hashes_.sha_, SHA_LEN,
+ ssl.getCrypto().get_random());
+
+ byte encoded[DSS_SIG_SZ + DSS_ENCODED_EXTRA];
+ TaoCrypt::EncodeDSA_Signature(sig.get() + VERIFY_HEADER, encoded);
+ memcpy(sig.get() + VERIFY_HEADER, encoded, sizeof(encoded));
+ }
+ set_length(sz);
+ signature_ = sig.release();
+}
+
+
+input_buffer& CertificateVerify::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& CertificateVerify::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+// input operator for CertificateVerify
+input_buffer& operator>>(input_buffer& input, CertificateVerify& request)
+{
+ byte tmp[VERIFY_HEADER];
+ input.read(tmp, sizeof(tmp));
+
+ uint16 sz = 0;
+ ato16(tmp, sz);
+ request.set_length(sz);
+
+ request.signature_ = new (ys) byte[sz];
+ input.read(request.signature_, sz);
+
+ return input;
+}
+
+
+// output operator for CertificateVerify
+output_buffer& operator<<(output_buffer& output,
+ const CertificateVerify& verify)
+{
+ output.write(verify.signature_, verify.get_length());
+
+ return output;
+}
+
+
+// CertificateVerify processing handler
+void CertificateVerify::Process(input_buffer&, SSL& ssl)
+{
+ const Hashes& hashVerify = ssl.getHashes().get_certVerify();
+ const CertManager& cert = ssl.getCrypto().get_certManager();
+
+ if (cert.get_peerKeyType() == rsa_sa_algo) {
+ RSA rsa(cert.get_peerKey(), cert.get_peerKeyLength());
+
+ if (!rsa.verify(hashVerify.md5_, sizeof(hashVerify), signature_,
+ get_length()))
+ ssl.SetError(verify_error);
+ }
+ else { // DSA
+ byte decodedSig[DSS_SIG_SZ];
+ TaoCrypt::DecodeDSA_Signature(decodedSig, signature_, get_length());
+
+ DSS dss(cert.get_peerKey(), cert.get_peerKeyLength());
+ if (!dss.verify(hashVerify.sha_, SHA_LEN, decodedSig, get_length()))
+ ssl.SetError(verify_error);
+ }
+}
+
+
+HandShakeType CertificateVerify::get_type() const
+{
+ return certificate_verify;
+}
+
+
+// output operator for ClientKeyExchange
+output_buffer& operator<<(output_buffer& output, const ClientKeyExchange& ck)
+{
+ output.write(ck.getKey(), ck.getKeyLength());
+ return output;
+}
+
+
+// Client Key Exchange processing handler
+void ClientKeyExchange::Process(input_buffer& input, SSL& ssl)
+{
+ createKey(ssl);
+ if (ssl.GetError()) return;
+ client_key_->read(ssl, input);
+
+ if (ssl.getCrypto().get_certManager().verifyPeer())
+ build_certHashes(ssl, ssl.useHashes().use_certVerify());
+
+ ssl.useStates().useServer() = clientKeyExchangeComplete;
+}
+
+
+ClientKeyExchange::ClientKeyExchange(SSL& ssl)
+{
+ createKey(ssl);
+}
+
+
+ClientKeyExchange::ClientKeyExchange()
+ : client_key_(0)
+{}
+
+
+ClientKeyExchange::~ClientKeyExchange()
+{
+ delete client_key_;
+}
+
+
+void ClientKeyExchange::build(SSL& ssl)
+{
+ client_key_->build(ssl);
+ set_length(client_key_->get_length());
+}
+
+const opaque* ClientKeyExchange::getKey() const
+{
+ return client_key_->get_clientKey();
+}
+
+
+int ClientKeyExchange::getKeyLength() const
+{
+ return client_key_->get_length();
+}
+
+
+input_buffer& ClientKeyExchange::set(input_buffer& in)
+{
+ return in;
+}
+
+
+output_buffer& ClientKeyExchange::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType ClientKeyExchange::get_type() const
+{
+ return client_key_exchange;
+}
+
+
+// input operator for Finished
+input_buffer& operator>>(input_buffer& input, Finished&)
+{
+ /* do in process */
+
+ return input;
+}
+
+// output operator for Finished
+output_buffer& operator<<(output_buffer& output, const Finished& fin)
+{
+ if (fin.get_length() == FINISHED_SZ) {
+ output.write(fin.hashes_.md5_, MD5_LEN);
+ output.write(fin.hashes_.sha_, SHA_LEN);
+ }
+ else // TLS_FINISHED_SZ
+ output.write(fin.hashes_.md5_, TLS_FINISHED_SZ);
+
+ return output;
+}
+
+
+// Finished processing handler
+void Finished::Process(input_buffer& input, SSL& ssl)
+{
+ // verify hashes
+ const Finished& verify = ssl.getHashes().get_verify();
+ uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ;
+
+ input.read(hashes_.md5_, finishedSz);
+
+ if (memcmp(&hashes_, &verify.hashes_, finishedSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+
+ // read verify mac
+ opaque verifyMAC[SHA_LEN];
+ uint macSz = finishedSz + HANDSHAKE_HEADER;
+
+ if (ssl.isTLS())
+ TLS_hmac(ssl, verifyMAC, input.get_buffer() + input.get_current()
+ - macSz, macSz, handshake, true);
+ else
+ hmac(ssl, verifyMAC, input.get_buffer() + input.get_current() - macSz,
+ macSz, handshake, true);
+
+ // read mac and fill
+ opaque mac[SHA_LEN]; // max size
+ int digestSz = ssl.getCrypto().get_digest().get_digestSize();
+ input.read(mac, digestSz);
+
+ opaque fill;
+ int padSz = ssl.getSecurity().get_parms().encrypt_size_ -
+ HANDSHAKE_HEADER - finishedSz - digestSz;
+ for (int i = 0; i < padSz; i++)
+ fill = input[AUTO];
+
+ // verify mac
+ if (memcmp(mac, verifyMAC, digestSz)) {
+ ssl.SetError(verify_error);
+ return;
+ }
+
+ // update states
+ ssl.useStates().useHandShake() = handShakeReady;
+ if (ssl.getSecurity().get_parms().entity_ == client_end)
+ ssl.useStates().useClient() = serverFinishedComplete;
+ else
+ ssl.useStates().useServer() = clientFinishedComplete;
+}
+
+
+Finished::Finished()
+{
+ set_length(FINISHED_SZ);
+}
+
+
+uint8* Finished::set_md5()
+{
+ return hashes_.md5_;
+}
+
+
+uint8* Finished::set_sha()
+{
+ return hashes_.sha_;
+}
+
+
+input_buffer& Finished::set(input_buffer& in)
+{
+ return in >> *this;
+}
+
+
+output_buffer& Finished::get(output_buffer& out) const
+{
+ return out << *this;
+}
+
+
+HandShakeType Finished::get_type() const
+{
+ return finished;
+}
+
+
+void clean(volatile opaque* p, uint sz, RandomPool& ran)
+{
+ uint i(0);
+
+ for (i = 0; i < sz; ++i)
+ p[i] = 0;
+
+ ran.Fill(const_cast<opaque*>(p), sz);
+
+ for (i = 0; i < sz; ++i)
+ p[i] = 0;
+}
+
+
+
+Connection::Connection(ProtocolVersion v, RandomPool& ran)
+ : pre_master_secret_(0), sequence_number_(0), peer_sequence_number_(0),
+ pre_secret_len_(0), send_server_key_(false), master_clean_(false),
+ TLS_(v.major_ >= 3 && v.minor_ >= 1), version_(v), random_(ran)
+{}
+
+
+Connection::~Connection()
+{
+ CleanMaster(); CleanPreMaster(); delete[] pre_master_secret_;
+}
+
+
+void Connection::AllocPreSecret(uint sz)
+{
+ pre_master_secret_ = new (ys) opaque[pre_secret_len_ = sz];
+}
+
+
+void Connection::TurnOffTLS()
+{
+ TLS_ = false;
+ version_.minor_ = 0;
+}
+
+
+// wipeout master secret
+void Connection::CleanMaster()
+{
+ if (!master_clean_) {
+ volatile opaque* p = master_secret_;
+ clean(p, SECRET_LEN, random_);
+ master_clean_ = true;
+ }
+}
+
+
+// wipeout pre master secret
+void Connection::CleanPreMaster()
+{
+ if (pre_master_secret_) {
+ volatile opaque* p = pre_master_secret_;
+ clean(p, pre_secret_len_, random_);
+
+ delete[] pre_master_secret_;
+ pre_master_secret_ = 0;
+ }
+}
+
+
+// Create functions for message factory
+Message* CreateCipherSpec() { return new (ys) ChangeCipherSpec; }
+Message* CreateAlert() { return new (ys) Alert; }
+Message* CreateHandShake() { return new (ys) HandShakeHeader; }
+Message* CreateData() { return new (ys) Data; }
+
+// Create functions for handshake factory
+HandShakeBase* CreateHelloRequest() { return new (ys) HelloRequest; }
+HandShakeBase* CreateClientHello() { return new (ys) ClientHello; }
+HandShakeBase* CreateServerHello() { return new (ys) ServerHello; }
+HandShakeBase* CreateCertificate() { return new (ys) Certificate; }
+HandShakeBase* CreateServerKeyExchange() { return new (ys) ServerKeyExchange;}
+HandShakeBase* CreateCertificateRequest() { return new (ys)
+ CertificateRequest; }
+HandShakeBase* CreateServerHelloDone() { return new (ys) ServerHelloDone; }
+HandShakeBase* CreateCertificateVerify() { return new (ys) CertificateVerify;}
+HandShakeBase* CreateClientKeyExchange() { return new (ys) ClientKeyExchange;}
+HandShakeBase* CreateFinished() { return new (ys) Finished; }
+
+// Create functions for server key exchange factory
+ServerKeyBase* CreateRSAServerKEA() { return new (ys) RSA_Server; }
+ServerKeyBase* CreateDHServerKEA() { return new (ys) DH_Server; }
+ServerKeyBase* CreateFortezzaServerKEA() { return new (ys) Fortezza_Server; }
+
+// Create functions for client key exchange factory
+ClientKeyBase* CreateRSAClient() { return new (ys)
+ EncryptedPreMasterSecret; }
+ClientKeyBase* CreateDHClient() { return new (ys)
+ ClientDiffieHellmanPublic; }
+ClientKeyBase* CreateFortezzaClient() { return new (ys) FortezzaKeys; }
+
+
+// Constructor calls this to Register compile time callbacks
+void InitMessageFactory(MessageFactory& mf)
+{
+ mf.Reserve(4);
+ mf.Register(alert, CreateAlert);
+ mf.Register(change_cipher_spec, CreateCipherSpec);
+ mf.Register(handshake, CreateHandShake);
+ mf.Register(application_data, CreateData);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitHandShakeFactory(HandShakeFactory& hsf)
+{
+ hsf.Reserve(10);
+ hsf.Register(hello_request, CreateHelloRequest);
+ hsf.Register(client_hello, CreateClientHello);
+ hsf.Register(server_hello, CreateServerHello);
+ hsf.Register(certificate, CreateCertificate);
+ hsf.Register(server_key_exchange, CreateServerKeyExchange);
+ hsf.Register(certificate_request, CreateCertificateRequest);
+ hsf.Register(server_hello_done, CreateServerHelloDone);
+ hsf.Register(certificate_verify, CreateCertificateVerify);
+ hsf.Register(client_key_exchange, CreateClientKeyExchange);
+ hsf.Register(finished, CreateFinished);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitServerKeyFactory(ServerKeyFactory& skf)
+{
+ skf.Reserve(3);
+ skf.Register(rsa_kea, CreateRSAServerKEA);
+ skf.Register(diffie_hellman_kea, CreateDHServerKEA);
+ skf.Register(fortezza_kea, CreateFortezzaServerKEA);
+}
+
+
+// Constructor calls this to Register compile time callbacks
+void InitClientKeyFactory(ClientKeyFactory& ckf)
+{
+ ckf.Reserve(3);
+ ckf.Register(rsa_kea, CreateRSAClient);
+ ckf.Register(diffie_hellman_kea, CreateDHClient);
+ ckf.Register(fortezza_kea, CreateFortezzaClient);
+}
+
+
+} // namespace
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
new file mode 100644
index 00000000000..d481194d2d7
--- /dev/null
+++ b/extra/yassl/src/yassl_int.cpp
@@ -0,0 +1,1971 @@
+/* yassl_int.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* yaSSL internal source implements SSL supporting types not specified in the
+ * draft along with type conversion functions.
+ */
+
+#include "runtime.hpp"
+#include "yassl_int.hpp"
+#include "handshake.hpp"
+#include "timer.hpp"
+#include "openssl/ssl.h" // for DH
+
+
+void* operator new(size_t sz, yaSSL::new_t)
+{
+ void* ptr = ::operator new(sz);
+
+ if (!ptr) abort();
+
+ return ptr;
+}
+
+void* operator new[](size_t sz, yaSSL::new_t n)
+{
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ void* ptr = ::operator new(sz); // no ::operator new[]
+#else
+ void* ptr = ::operator new[](sz);
+#endif
+
+ if (!ptr) abort();
+
+ return ptr;
+}
+
+
+namespace yaSSL {
+
+
+using mySTL::min;
+
+
+new_t ys; // for library new
+
+
+// convert a 32 bit integer into a 24 bit one
+void c32to24(uint32 u32, uint24& u24)
+{
+ u24[0] = (u32 >> 16) & 0xff;
+ u24[1] = (u32 >> 8) & 0xff;
+ u24[2] = u32 & 0xff;
+}
+
+
+// convert a 24 bit integer into a 32 bit one
+void c24to32(const uint24 u24, uint32& u32)
+{
+ u32 = 0;
+ u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2];
+}
+
+
+// convert with return for ease of use
+uint32 c24to32(const uint24 u24)
+{
+ uint32 ret;
+ c24to32(u24, ret);
+
+ return ret;
+}
+
+
+// using a for opaque since underlying type is unsgined char and o is not a
+// good leading identifier
+
+// convert opaque to 16 bit integer
+void ato16(const opaque* c, uint16& u16)
+{
+ u16 = 0;
+ u16 = (c[0] << 8) | (c[1]);
+}
+
+
+// convert (copy) opaque to 24 bit integer
+void ato24(const opaque* c, uint24& u24)
+{
+ u24[0] = c[0];
+ u24[1] = c[1];
+ u24[2] = c[2];
+}
+
+
+// convert 16 bit integer to opaque
+void c16toa(uint16 u16, opaque* c)
+{
+ c[0] = (u16 >> 8) & 0xff;
+ c[1] = u16 & 0xff;
+}
+
+
+// convert 24 bit integer to opaque
+void c24toa(const uint24 u24, opaque* c)
+{
+ c[0] = u24[0];
+ c[1] = u24[1];
+ c[2] = u24[2];
+}
+
+
+// convert 32 bit integer to opaque
+void c32toa(uint32 u32, opaque* c)
+{
+ c[0] = (u32 >> 24) & 0xff;
+ c[1] = (u32 >> 16) & 0xff;
+ c[2] = (u32 >> 8) & 0xff;
+ c[3] = u32 & 0xff;
+}
+
+
+States::States() : recordLayer_(recordReady), handshakeLayer_(preHandshake),
+ clientState_(serverNull), serverState_(clientNull),
+ what_(no_error) {}
+
+const RecordLayerState& States::getRecord() const
+{
+ return recordLayer_;
+}
+
+
+const HandShakeState& States::getHandShake() const
+{
+ return handshakeLayer_;
+}
+
+
+const ClientState& States::getClient() const
+{
+ return clientState_;
+}
+
+
+const ServerState& States::getServer() const
+{
+ return serverState_;
+}
+
+
+const char* States::getString() const
+{
+ return errorString_;
+}
+
+
+YasslError States::What() const
+{
+ return what_;
+}
+
+
+RecordLayerState& States::useRecord()
+{
+ return recordLayer_;
+}
+
+
+HandShakeState& States::useHandShake()
+{
+ return handshakeLayer_;
+}
+
+
+ClientState& States::useClient()
+{
+ return clientState_;
+}
+
+
+ServerState& States::useServer()
+{
+ return serverState_;
+}
+
+
+char* States::useString()
+{
+ return errorString_;
+}
+
+
+void States::SetError(YasslError ye)
+{
+ what_ = ye;
+}
+
+
+sslFactory::sslFactory() :
+ messageFactory_(InitMessageFactory),
+ handShakeFactory_(InitHandShakeFactory),
+ serverKeyFactory_(InitServerKeyFactory),
+ clientKeyFactory_(InitClientKeyFactory)
+{}
+
+
+const MessageFactory& sslFactory::getMessage() const
+{
+ return messageFactory_;
+}
+
+
+const HandShakeFactory& sslFactory::getHandShake() const
+{
+ return handShakeFactory_;
+}
+
+
+const ServerKeyFactory& sslFactory::getServerKey() const
+{
+ return serverKeyFactory_;
+}
+
+
+const ClientKeyFactory& sslFactory::getClientKey() const
+{
+ return clientKeyFactory_;
+}
+
+
+// extract context parameters and store
+SSL::SSL(SSL_CTX* ctx)
+ : secure_(ctx->getMethod()->getVersion(), crypto_.use_random(),
+ ctx->getMethod()->getSide(), ctx->GetCiphers(), ctx)
+{
+ if (int err = crypto_.get_random().GetError()) {
+ SetError(YasslError(err));
+ return;
+ }
+
+ CertManager& cm = crypto_.use_certManager();
+ cm.CopySelfCert(ctx->getCert());
+
+ bool serverSide = secure_.use_parms().entity_ == server_end;
+
+ if (ctx->getKey()) {
+ if (int err = cm.SetPrivateKey(*ctx->getKey())) {
+ SetError(YasslError(err));
+ return;
+ }
+ }
+ else if (serverSide) {
+ SetError(no_key_file);
+ return;
+ }
+
+ if (ctx->getMethod()->verifyPeer())
+ cm.setVerifyPeer();
+ if (ctx->getMethod()->failNoCert())
+ cm.setFailNoCert();
+
+ if (serverSide)
+ crypto_.SetDH(ctx->GetDH_Parms());
+
+ const SSL_CTX::CertList& ca = ctx->GetCA_List();
+ SSL_CTX::CertList::const_iterator first(ca.begin());
+ SSL_CTX::CertList::const_iterator last(ca.end());
+
+ while (first != last) {
+ if (int err = cm.CopyCaCert(*first)) {
+ SetError(YasslError(err));
+ return;
+ }
+ ++first;
+ }
+}
+
+
+// store pending security parameters from Server Hello
+void SSL::set_pending(Cipher suite)
+{
+ Parameters& parms = secure_.use_parms();
+
+ switch (suite) {
+
+ case TLS_RSA_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_, cipher_names[TLS_RSA_WITH_AES_256_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_, cipher_names[TLS_RSA_WITH_AES_128_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_3DES_EDE_CBC_SHA]
+ , MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_RC4_128_SHA:
+ parms.bulk_cipher_algorithm_ = rc4;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = RC4_KEY_SZ;
+ parms.iv_size_ = 0;
+ parms.cipher_type_ = stream;
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) RC4);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_RC4_128_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_RSA_WITH_RC4_128_MD5:
+ parms.bulk_cipher_algorithm_ = rc4;
+ parms.mac_algorithm_ = md5;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = MD5_LEN;
+ parms.key_size_ = RC4_KEY_SZ;
+ parms.iv_size_ = 0;
+ parms.cipher_type_ = stream;
+ crypto_.setDigest(new (ys) MD5);
+ crypto_.setCipher(new (ys) RC4);
+ strncpy(parms.cipher_name_, cipher_names[SSL_RSA_WITH_RC4_128_MD5],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_RSA_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_DHE_RSA_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_256_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_128_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_DSS_WITH_DES_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES);
+ strncpy(parms.cipher_name_, cipher_names[SSL_DHE_DSS_WITH_DES_CBC_SHA],
+ MAX_SUITE_NAME);
+ break;
+
+ case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_256_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = sha;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = SHA_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) SHA);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_128_CBC_SHA], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_AES_256_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_AES_128_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_RSA_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = rsa_kea;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_RSA_WITH_3DES_EDE_CBC_RMD160], MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_256_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_RSA_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = rsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_RSA_WITH_AES_128_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = triple_des;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = DES_EDE_KEY_SZ;
+ parms.iv_size_ = DES_IV_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) DES_EDE);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_256_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_256_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES(AES_256_KEY_SZ));
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_256_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ case TLS_DHE_DSS_WITH_AES_128_CBC_RMD160:
+ parms.bulk_cipher_algorithm_ = aes;
+ parms.mac_algorithm_ = rmd;
+ parms.kea_ = diffie_hellman_kea;
+ parms.sig_algo_ = dsa_sa_algo;
+ parms.hash_size_ = RMD_LEN;
+ parms.key_size_ = AES_128_KEY_SZ;
+ parms.iv_size_ = AES_BLOCK_SZ;
+ parms.cipher_type_ = block;
+ secure_.use_connection().send_server_key_ = true; // eph
+ crypto_.setDigest(new (ys) RMD);
+ crypto_.setCipher(new (ys) AES);
+ strncpy(parms.cipher_name_,
+ cipher_names[TLS_DHE_DSS_WITH_AES_128_CBC_RMD160],
+ MAX_SUITE_NAME);
+ break;
+
+ default:
+ SetError(unknown_cipher);
+ }
+}
+
+
+// store peer's random
+void SSL::set_random(const opaque* random, ConnectionEnd sender)
+{
+ if (sender == client_end)
+ memcpy(secure_.use_connection().client_random_, random, RAN_LEN);
+ else
+ memcpy(secure_.use_connection().server_random_, random, RAN_LEN);
+}
+
+
+// store client pre master secret
+void SSL::set_preMaster(const opaque* pre, uint sz)
+{
+ secure_.use_connection().AllocPreSecret(sz);
+ memcpy(secure_.use_connection().pre_master_secret_, pre, sz);
+}
+
+
+// store master secret
+void SSL::set_masterSecret(const opaque* sec)
+{
+ memcpy(secure_.use_connection().master_secret_, sec, SECRET_LEN);
+}
+
+// store server issued id
+void SSL::set_sessionID(const opaque* sessionID)
+{
+ memcpy(secure_.use_connection().sessionID_, sessionID, ID_LEN);
+}
+
+
+// store error
+void SSL::SetError(YasslError ye)
+{
+ states_.SetError(ye);
+ //strncpy(states_.useString(), e.what(), mySTL::named_exception::NAME_SIZE);
+ // TODO: add string here
+}
+
+
+// locals
+namespace {
+
+// DeriveKeys and MasterSecret helper sets prefix letters
+static bool setPrefix(opaque* sha_input, int i)
+{
+ switch (i) {
+ case 0:
+ memcpy(sha_input, "A", 1);
+ break;
+ case 1:
+ memcpy(sha_input, "BB", 2);
+ break;
+ case 2:
+ memcpy(sha_input, "CCC", 3);
+ break;
+ case 3:
+ memcpy(sha_input, "DDDD", 4);
+ break;
+ case 4:
+ memcpy(sha_input, "EEEEE", 5);
+ break;
+ case 5:
+ memcpy(sha_input, "FFFFFF", 6);
+ break;
+ case 6:
+ memcpy(sha_input, "GGGGGGG", 7);
+ break;
+ default:
+ return false; // prefix_error
+ }
+ return true;
+}
+
+
+const char handshake_order[] = "Out of order HandShake Message!";
+
+
+} // namespcae for locals
+
+
+void SSL::order_error()
+{
+ SetError(out_of_order);
+}
+
+
+// Create and store the master secret see page 32, 6.1
+void SSL::makeMasterSecret()
+{
+ if (isTLS())
+ makeTLSMasterSecret();
+ else {
+ opaque sha_output[SHA_LEN];
+
+ const uint& preSz = secure_.get_connection().pre_secret_len_;
+ output_buffer md5_input(preSz + SHA_LEN);
+ output_buffer sha_input(PREFIX + preSz + 2 * RAN_LEN);
+
+ MD5 md5;
+ SHA sha;
+
+ md5_input.write(secure_.get_connection().pre_master_secret_, preSz);
+
+ for (int i = 0; i < MASTER_ROUNDS; ++i) {
+ opaque prefix[PREFIX];
+ if (!setPrefix(prefix, i)) {
+ SetError(prefix_error);
+ return;
+ }
+
+ sha_input.set_current(0);
+ sha_input.write(prefix, i + 1);
+
+ sha_input.write(secure_.get_connection().pre_master_secret_,preSz);
+ sha_input.write(secure_.get_connection().client_random_, RAN_LEN);
+ sha_input.write(secure_.get_connection().server_random_, RAN_LEN);
+ sha.get_digest(sha_output, sha_input.get_buffer(),
+ sha_input.get_size());
+
+ md5_input.set_current(preSz);
+ md5_input.write(sha_output, SHA_LEN);
+ md5.get_digest(&secure_.use_connection().master_secret_[i*MD5_LEN],
+ md5_input.get_buffer(), md5_input.get_size());
+ }
+ deriveKeys();
+ }
+ secure_.use_connection().CleanPreMaster();
+}
+
+
+// create TLSv1 master secret
+void SSL::makeTLSMasterSecret()
+{
+ opaque seed[SEED_LEN];
+
+ memcpy(seed, secure_.get_connection().client_random_, RAN_LEN);
+ memcpy(&seed[RAN_LEN], secure_.get_connection().server_random_, RAN_LEN);
+
+ PRF(secure_.use_connection().master_secret_, SECRET_LEN,
+ secure_.get_connection().pre_master_secret_,
+ secure_.get_connection().pre_secret_len_,
+ master_label, MASTER_LABEL_SZ,
+ seed, SEED_LEN);
+
+ deriveTLSKeys();
+}
+
+
+// derive mac, write, and iv keys for server and client, see page 34, 6.2.2
+void SSL::deriveKeys()
+{
+ int length = 2 * secure_.get_parms().hash_size_ +
+ 2 * secure_.get_parms().key_size_ +
+ 2 * secure_.get_parms().iv_size_;
+ int rounds = length / MD5_LEN + ((length % MD5_LEN) ? 1 : 0);
+ input_buffer key_data(rounds * MD5_LEN);
+
+ opaque sha_output[SHA_LEN];
+ opaque md5_input[SECRET_LEN + SHA_LEN];
+ opaque sha_input[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN];
+
+ MD5 md5;
+ SHA sha;
+
+ memcpy(md5_input, secure_.get_connection().master_secret_, SECRET_LEN);
+
+ for (int i = 0; i < rounds; ++i) {
+ int j = i + 1;
+ if (!setPrefix(sha_input, i)) {
+ SetError(prefix_error);
+ return;
+ }
+
+ memcpy(&sha_input[j], secure_.get_connection().master_secret_,
+ SECRET_LEN);
+ memcpy(&sha_input[j+SECRET_LEN],
+ secure_.get_connection().server_random_, RAN_LEN);
+ memcpy(&sha_input[j + SECRET_LEN + RAN_LEN],
+ secure_.get_connection().client_random_, RAN_LEN);
+ sha.get_digest(sha_output, sha_input,
+ sizeof(sha_input) - KEY_PREFIX + j);
+
+ memcpy(&md5_input[SECRET_LEN], sha_output, SHA_LEN);
+ md5.get_digest(key_data.get_buffer() + i * MD5_LEN,
+ md5_input, sizeof(md5_input));
+ }
+ storeKeys(key_data.get_buffer());
+}
+
+
+// derive mac, write, and iv keys for server and client
+void SSL::deriveTLSKeys()
+{
+ int length = 2 * secure_.get_parms().hash_size_ +
+ 2 * secure_.get_parms().key_size_ +
+ 2 * secure_.get_parms().iv_size_;
+ opaque seed[SEED_LEN];
+ input_buffer key_data(length);
+
+ memcpy(seed, secure_.get_connection().server_random_, RAN_LEN);
+ memcpy(&seed[RAN_LEN], secure_.get_connection().client_random_, RAN_LEN);
+
+ PRF(key_data.get_buffer(), length, secure_.get_connection().master_secret_,
+ SECRET_LEN, key_label, KEY_LABEL_SZ, seed, SEED_LEN);
+
+ storeKeys(key_data.get_buffer());
+}
+
+
+// store mac, write, and iv keys for client and server
+void SSL::storeKeys(const opaque* key_data)
+{
+ int sz = secure_.get_parms().hash_size_;
+ memcpy(secure_.use_connection().client_write_MAC_secret_, key_data, sz);
+ int i = sz;
+ memcpy(secure_.use_connection().server_write_MAC_secret_,&key_data[i], sz);
+ i += sz;
+
+ sz = secure_.get_parms().key_size_;
+ memcpy(secure_.use_connection().client_write_key_, &key_data[i], sz);
+ i += sz;
+ memcpy(secure_.use_connection().server_write_key_, &key_data[i], sz);
+ i += sz;
+
+ sz = secure_.get_parms().iv_size_;
+ memcpy(secure_.use_connection().client_write_IV_, &key_data[i], sz);
+ i += sz;
+ memcpy(secure_.use_connection().server_write_IV_, &key_data[i], sz);
+
+ setKeys();
+}
+
+
+// set encrypt/decrypt keys and ivs
+void SSL::setKeys()
+{
+ Connection& conn = secure_.use_connection();
+
+ if (secure_.get_parms().entity_ == client_end) {
+ crypto_.use_cipher().set_encryptKey(conn.client_write_key_,
+ conn.client_write_IV_);
+ crypto_.use_cipher().set_decryptKey(conn.server_write_key_,
+ conn.server_write_IV_);
+ }
+ else {
+ crypto_.use_cipher().set_encryptKey(conn.server_write_key_,
+ conn.server_write_IV_);
+ crypto_.use_cipher().set_decryptKey(conn.client_write_key_,
+ conn.client_write_IV_);
+ }
+}
+
+
+
+// local functors
+namespace {
+
+struct SumData {
+ uint total_;
+ SumData() : total_(0) {}
+ void operator()(input_buffer* data) { total_ += data->get_remaining(); }
+};
+
+
+struct SumBuffer {
+ uint total_;
+ SumBuffer() : total_(0) {}
+ void operator()(output_buffer* buffer) { total_ += buffer->get_size(); }
+};
+
+} // namespace for locals
+
+
+uint SSL::bufferedData()
+{
+ return mySTL::for_each(buffers_.getData().begin(),buffers_.getData().end(),
+ SumData()).total_;
+}
+
+
+// use input buffer to fill data
+void SSL::fillData(Data& data)
+{
+ if (GetError()) return;
+ uint dataSz = data.get_length(); // input, data size to fill
+ uint elements = buffers_.getData().size();
+
+ data.set_length(0); // output, actual data filled
+ dataSz = min(dataSz, bufferedData());
+
+ for (uint i = 0; i < elements; i++) {
+ input_buffer* front = buffers_.getData().front();
+ uint frontSz = front->get_remaining();
+ uint readSz = min(dataSz - data.get_length(), frontSz);
+
+ front->read(data.set_buffer() + data.get_length(), readSz);
+ data.set_length(data.get_length() + readSz);
+
+ if (readSz == frontSz) {
+ buffers_.useData().pop_front();
+ delete front;
+ }
+ if (data.get_length() == dataSz)
+ break;
+ }
+}
+
+
+// flush output buffer
+void SSL::flushBuffer()
+{
+ if (GetError()) return;
+
+ uint sz = mySTL::for_each(buffers_.getHandShake().begin(),
+ buffers_.getHandShake().end(),
+ SumBuffer()).total_;
+ output_buffer out(sz);
+ uint elements = buffers_.getHandShake().size();
+
+ for (uint i = 0; i < elements; i++) {
+ output_buffer* front = buffers_.getHandShake().front();
+ out.write(front->get_buffer(), front->get_size());
+
+ buffers_.useHandShake().pop_front();
+ delete front;
+ }
+ Send(out.get_buffer(), out.get_size());
+}
+
+
+void SSL::Send(const byte* buffer, uint sz)
+{
+ if (socket_.send(buffer, sz) != sz)
+ SetError(send_error);
+}
+
+
+// get sequence number, if verify get peer's
+uint SSL::get_SEQIncrement(bool verify)
+{
+ if (verify)
+ return secure_.use_connection().peer_sequence_number_++;
+ else
+ return secure_.use_connection().sequence_number_++;
+}
+
+
+const byte* SSL::get_macSecret(bool verify)
+{
+ if ( (secure_.get_parms().entity_ == client_end && !verify) ||
+ (secure_.get_parms().entity_ == server_end && verify) )
+ return secure_.get_connection().client_write_MAC_secret_;
+ else
+ return secure_.get_connection().server_write_MAC_secret_;
+}
+
+
+void SSL::verifyState(const RecordLayerHeader& rlHeader)
+{
+ if (GetError()) return;
+
+ if (states_.getRecord() == recordNotReady ||
+ (rlHeader.type_ == application_data && // data and handshake
+ states_.getHandShake() != handShakeReady) ) // isn't complete yet
+ SetError(record_layer);
+}
+
+
+void SSL::verifyState(const HandShakeHeader& hsHeader)
+{
+ if (GetError()) return;
+
+ if (states_.getHandShake() == handShakeNotReady) {
+ SetError(handshake_layer);
+ return;
+ }
+
+ if (secure_.get_parms().entity_ == client_end)
+ verifyClientState(hsHeader.get_handshakeType());
+ else
+ verifyServerState(hsHeader.get_handshakeType());
+}
+
+
+void SSL::verifyState(ClientState cs)
+{
+ if (GetError()) return;
+ if (states_.getClient() != cs) order_error();
+}
+
+
+void SSL::verifyState(ServerState ss)
+{
+ if (GetError()) return;
+ if (states_.getServer() != ss) order_error();
+}
+
+
+void SSL::verfiyHandShakeComplete()
+{
+ if (GetError()) return;
+ if (states_.getHandShake() != handShakeReady) order_error();
+}
+
+
+void SSL::verifyClientState(HandShakeType hsType)
+{
+ if (GetError()) return;
+
+ switch(hsType) {
+ case server_hello :
+ if (states_.getClient() != serverNull)
+ order_error();
+ break;
+ case certificate :
+ if (states_.getClient() != serverHelloComplete)
+ order_error();
+ break;
+ case server_key_exchange :
+ if (states_.getClient() != serverCertComplete)
+ order_error();
+ break;
+ case certificate_request :
+ if (states_.getClient() != serverCertComplete &&
+ states_.getClient() != serverKeyExchangeComplete)
+ order_error();
+ break;
+ case server_hello_done :
+ if (states_.getClient() != serverCertComplete &&
+ states_.getClient() != serverKeyExchangeComplete)
+ order_error();
+ break;
+ case finished :
+ if (states_.getClient() != serverHelloDoneComplete ||
+ secure_.get_parms().pending_) // no change
+ order_error(); // cipher yet
+ break;
+ default :
+ order_error();
+ };
+}
+
+
+void SSL::verifyServerState(HandShakeType hsType)
+{
+ if (GetError()) return;
+
+ switch(hsType) {
+ case client_hello :
+ if (states_.getServer() != clientNull)
+ order_error();
+ break;
+ case certificate :
+ if (states_.getServer() != clientHelloComplete)
+ order_error();
+ break;
+ case client_key_exchange :
+ if (states_.getServer() != clientHelloComplete)
+ order_error();
+ break;
+ case certificate_verify :
+ if (states_.getServer() != clientKeyExchangeComplete)
+ order_error();
+ break;
+ case finished :
+ if (states_.getServer() != clientKeyExchangeComplete ||
+ secure_.get_parms().pending_) // no change
+ order_error(); // cipher yet
+ break;
+ default :
+ order_error();
+ };
+}
+
+
+// try to find a suite match
+void SSL::matchSuite(const opaque* peer, uint length)
+{
+ if (length == 0 || (length % 2) != 0) {
+ SetError(bad_input);
+ return;
+ }
+
+ // start with best, if a match we are good, Ciphers are at odd index
+ // since all SSL and TLS ciphers have 0x00 first byte
+ for (uint i = 1; i < secure_.get_parms().suites_size_; i += 2)
+ for (uint j = 1; j < length; j+= 2)
+ if (secure_.use_parms().suites_[i] == peer[j]) {
+ secure_.use_parms().suite_[0] = 0x00;
+ secure_.use_parms().suite_[1] = peer[j];
+ return;
+ }
+
+ SetError(match_error);
+}
+
+
+void SSL::set_session(SSL_SESSION* s)
+{
+ if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume()))
+ secure_.set_resuming(true);
+}
+
+
+const Crypto& SSL::getCrypto() const
+{
+ return crypto_;
+}
+
+
+const Security& SSL::getSecurity() const
+{
+ return secure_;
+}
+
+
+const States& SSL::getStates() const
+{
+ return states_;
+}
+
+
+const sslHashes& SSL::getHashes() const
+{
+ return hashes_;
+}
+
+
+const sslFactory& SSL::getFactory() const
+{
+ return GetSSL_Factory();
+}
+
+
+const Socket& SSL::getSocket() const
+{
+ return socket_;
+}
+
+
+YasslError SSL::GetError() const
+{
+ return states_.What();
+}
+
+
+Crypto& SSL::useCrypto()
+{
+ return crypto_;
+}
+
+
+Security& SSL::useSecurity()
+{
+ return secure_;
+}
+
+
+States& SSL::useStates()
+{
+ return states_;
+}
+
+
+sslHashes& SSL::useHashes()
+{
+ return hashes_;
+}
+
+
+Socket& SSL::useSocket()
+{
+ return socket_;
+}
+
+
+Log& SSL::useLog()
+{
+ return log_;
+}
+
+
+bool SSL::isTLS() const
+{
+ return secure_.get_connection().TLS_;
+}
+
+
+void SSL::addData(input_buffer* data)
+{
+ buffers_.useData().push_back(data);
+}
+
+
+void SSL::addBuffer(output_buffer* b)
+{
+ buffers_.useHandShake().push_back(b);
+}
+
+
+// store connection parameters
+SSL_SESSION::SSL_SESSION(const SSL& ssl, RandomPool& ran)
+ : timeout_(DEFAULT_TIMEOUT), random_(ran)
+{
+ const Connection& conn = ssl.getSecurity().get_connection();
+
+ memcpy(sessionID_, conn.sessionID_, ID_LEN);
+ memcpy(master_secret_, conn.master_secret_, SECRET_LEN);
+ memcpy(suite_, ssl.getSecurity().get_parms().suite_, SUITE_LEN);
+
+ bornOn_ = lowResTimer();
+}
+
+
+// for resumption copy in ssl::parameters
+SSL_SESSION::SSL_SESSION(RandomPool& ran)
+ : bornOn_(0), timeout_(0), random_(ran)
+{
+ memset(sessionID_, 0, ID_LEN);
+ memset(master_secret_, 0, SECRET_LEN);
+ memset(suite_, 0, SUITE_LEN);
+}
+
+
+SSL_SESSION& SSL_SESSION::operator=(const SSL_SESSION& that)
+{
+ memcpy(sessionID_, that.sessionID_, ID_LEN);
+ memcpy(master_secret_, that.master_secret_, SECRET_LEN);
+ memcpy(suite_, that.suite_, SUITE_LEN);
+
+ bornOn_ = that.bornOn_;
+ timeout_ = that.timeout_;
+
+ return *this;
+}
+
+
+const opaque* SSL_SESSION::GetID() const
+{
+ return sessionID_;
+}
+
+
+const opaque* SSL_SESSION::GetSecret() const
+{
+ return master_secret_;
+}
+
+
+const Cipher* SSL_SESSION::GetSuite() const
+{
+ return suite_;
+}
+
+
+uint SSL_SESSION::GetBornOn() const
+{
+ return bornOn_;
+}
+
+
+uint SSL_SESSION::GetTimeOut() const
+{
+ return timeout_;
+}
+
+
+void SSL_SESSION::SetTimeOut(uint t)
+{
+ timeout_ = t;
+}
+
+
+extern void clean(volatile opaque*, uint, RandomPool&);
+
+
+// clean up secret data
+SSL_SESSION::~SSL_SESSION()
+{
+ volatile opaque* p = master_secret_;
+ clean(p, SECRET_LEN, random_);
+}
+
+
+Sessions& GetSessions()
+{
+ static Sessions instance; // simple singleton
+ return instance;
+}
+
+
+sslFactory& GetSSL_Factory()
+{
+ static sslFactory instance; // simple singleton
+ return instance;
+}
+
+
+typedef Mutex::Lock Lock;
+
+
+void Sessions::add(const SSL& ssl)
+{
+ Lock guard(mutex_);
+ list_.push_back(new (ys) SSL_SESSION(ssl, random_));
+}
+
+
+Sessions::~Sessions()
+{
+ mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero());
+}
+
+
+namespace { // locals
+
+typedef mySTL::list<SSL_SESSION*>::iterator iterator;
+
+struct sess_match {
+ const opaque* id_;
+ explicit sess_match(const opaque* p) : id_(p) {}
+
+ bool operator()(SSL_SESSION* sess)
+ {
+ if ( memcmp(sess->GetID(), id_, ID_LEN) == 0)
+ return true;
+ return false;
+ }
+};
+
+
+} // local namespace
+
+
+// lookup session by id, return a copy if space provided
+SSL_SESSION* Sessions::lookup(const opaque* id, SSL_SESSION* copy)
+{
+ Lock guard(mutex_);
+ iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id));
+
+ if (find != list_.end()) {
+ uint current = lowResTimer();
+ if ( ((*find)->GetBornOn() + (*find)->GetTimeOut()) < current) {
+ del_ptr_zero()(*find);
+ list_.erase(find);
+ return 0;
+ }
+ if (copy)
+ *copy = *(*find);
+ return *find;
+ }
+ return 0;
+}
+
+
+// remove a session by id
+void Sessions::remove(const opaque* id)
+{
+ Lock guard(mutex_);
+ iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id));
+
+ if (find != list_.end()) {
+ del_ptr_zero()(*find);
+ list_.erase(find);
+ }
+}
+
+
+SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv)
+ : version_(pv), side_(ce), verifyPeer_(false), failNoCert_(false)
+{}
+
+
+ProtocolVersion SSL_METHOD::getVersion() const
+{
+ return version_;
+}
+
+
+ConnectionEnd SSL_METHOD::getSide() const
+{
+ return side_;
+}
+
+
+void SSL_METHOD::setVerifyPeer()
+{
+ verifyPeer_ = true;
+}
+
+
+void SSL_METHOD::setFailNoCert()
+{
+ failNoCert_ = true;
+}
+
+
+bool SSL_METHOD::verifyPeer() const
+{
+ return verifyPeer_;
+}
+
+
+bool SSL_METHOD::failNoCert() const
+{
+ return failNoCert_;
+}
+
+
+SSL_CTX::SSL_CTX(SSL_METHOD* meth)
+ : method_(meth), certificate_(0), privateKey_(0)
+{}
+
+
+SSL_CTX::~SSL_CTX()
+{
+ delete method_;
+ delete certificate_;
+ delete privateKey_;
+
+ mySTL::for_each(caList_.begin(), caList_.end(), del_ptr_zero());
+}
+
+
+void SSL_CTX::AddCA(x509* ca)
+{
+ caList_.push_back(ca);
+}
+
+
+const SSL_CTX::CertList&
+SSL_CTX::GetCA_List() const
+{
+ return caList_;
+}
+
+
+const x509* SSL_CTX::getCert() const
+{
+ return certificate_;
+}
+
+
+const x509* SSL_CTX::getKey() const
+{
+ return privateKey_;
+}
+
+
+const SSL_METHOD* SSL_CTX::getMethod() const
+{
+ return method_;
+}
+
+
+const Ciphers& SSL_CTX::GetCiphers() const
+{
+ return ciphers_;
+}
+
+
+const DH_Parms& SSL_CTX::GetDH_Parms() const
+{
+ return dhParms_;
+}
+
+
+const Stats& SSL_CTX::GetStats() const
+{
+ return stats_;
+}
+
+
+void SSL_CTX::setVerifyPeer()
+{
+ method_->setVerifyPeer();
+}
+
+
+void SSL_CTX::setFailNoCert()
+{
+ method_->setFailNoCert();
+}
+
+
+bool SSL_CTX::SetDH(const DH& dh)
+{
+ dhParms_.p_ = dh.p->int_;
+ dhParms_.g_ = dh.g->int_;
+
+ return dhParms_.set_ = true;
+}
+
+
+bool SSL_CTX::SetCipherList(const char* list)
+{
+ if (!list)
+ return false;
+
+ bool ret = false;
+ char name[MAX_SUITE_NAME];
+
+ char needle[] = ":";
+ char* haystack = const_cast<char*>(list);
+ char* prev;
+
+ const int suiteSz = sizeof(cipher_names) / sizeof(cipher_names[0]);
+ int idx = 0;
+
+ for(;;) {
+ int len;
+ prev = haystack;
+ haystack = strstr(haystack, needle);
+
+ if (!haystack) // last cipher
+ len = min(sizeof(name), strlen(prev));
+ else
+ len = min(sizeof(name), (size_t)(haystack - prev));
+
+ strncpy(name, prev, len);
+ name[(len == sizeof(name)) ? len - 1 : len] = 0;
+
+ for (int i = 0; i < suiteSz; i++)
+ if (strncmp(name, cipher_names[i], sizeof(name)) == 0) {
+
+ ciphers_.suites_[idx++] = 0x00; // first byte always zero
+ ciphers_.suites_[idx++] = i;
+
+ if (!ret) ret = true; // found at least one
+ break;
+ }
+ if (!haystack) break;
+ haystack++;
+ }
+
+ if (ret) {
+ ciphers_.setSuites_ = true;
+ ciphers_.suiteSz_ = idx;
+ }
+
+ return ret;
+}
+
+
+void SSL_CTX::IncrementStats(StatsField fd)
+{
+
+ Lock guard(mutex_);
+
+ switch (fd) {
+
+ case Accept:
+ ++stats_.accept_;
+ break;
+
+ case Connect:
+ ++stats_.connect_;
+ break;
+
+ case AcceptGood:
+ ++stats_.acceptGood_;
+ break;
+
+ case ConnectGood:
+ ++stats_.connectGood_;
+ break;
+
+ case AcceptRenegotiate:
+ ++stats_.acceptRenegotiate_;
+ break;
+
+ case ConnectRenegotiate:
+ ++stats_.connectRenegotiate_;
+ break;
+
+ case Hits:
+ ++stats_.hits_;
+ break;
+
+ case CbHits:
+ ++stats_.cbHits_;
+ break;
+
+ case CacheFull:
+ ++stats_.cacheFull_;
+ break;
+
+ case Misses:
+ ++stats_.misses_;
+ break;
+
+ case Timeouts:
+ ++stats_.timeouts_;
+ break;
+
+ case Number:
+ ++stats_.number_;
+ break;
+
+ case GetCacheSize:
+ ++stats_.getCacheSize_;
+ break;
+
+ case VerifyMode:
+ ++stats_.verifyMode_;
+ break;
+
+ case VerifyDepth:
+ ++stats_.verifyDepth_;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+Crypto::Crypto()
+ : digest_(0), cipher_(0), dh_(0)
+{}
+
+
+Crypto::~Crypto()
+{
+ delete dh_;
+ delete cipher_;
+ delete digest_;
+}
+
+
+const Digest& Crypto::get_digest() const
+{
+ return *digest_;
+}
+
+
+const BulkCipher& Crypto::get_cipher() const
+{
+ return *cipher_;
+}
+
+
+const DiffieHellman& Crypto::get_dh() const
+{
+ return *dh_;
+}
+
+
+const RandomPool& Crypto::get_random() const
+{
+ return random_;
+}
+
+
+const CertManager& Crypto::get_certManager() const
+{
+ return cert_;
+}
+
+
+
+Digest& Crypto::use_digest()
+{
+ return *digest_;
+}
+
+
+BulkCipher& Crypto::use_cipher()
+{
+ return *cipher_;
+}
+
+
+DiffieHellman& Crypto::use_dh()
+{
+ return *dh_;
+}
+
+
+RandomPool& Crypto::use_random()
+{
+ return random_;
+}
+
+
+CertManager& Crypto::use_certManager()
+{
+ return cert_;
+}
+
+
+
+void Crypto::SetDH(DiffieHellman* dh)
+{
+ dh_ = dh;
+}
+
+
+void Crypto::SetDH(const DH_Parms& dh)
+{
+ if (dh.set_)
+ dh_ = new (ys) DiffieHellman(dh.p_, dh.g_, random_);
+}
+
+
+bool Crypto::DhSet()
+{
+ return dh_ != 0;
+}
+
+
+void Crypto::setDigest(Digest* digest)
+{
+ digest_ = digest;
+}
+
+
+void Crypto::setCipher(BulkCipher* c)
+{
+ cipher_ = c;
+}
+
+
+const MD5& sslHashes::get_MD5() const
+{
+ return md5HandShake_;
+}
+
+
+const SHA& sslHashes::get_SHA() const
+{
+ return shaHandShake_;
+}
+
+
+const Finished& sslHashes::get_verify() const
+{
+ return verify_;
+}
+
+
+const Hashes& sslHashes::get_certVerify() const
+{
+ return certVerify_;
+}
+
+
+MD5& sslHashes::use_MD5(){
+ return md5HandShake_;
+}
+
+
+SHA& sslHashes::use_SHA()
+{
+ return shaHandShake_;
+}
+
+
+Finished& sslHashes::use_verify()
+{
+ return verify_;
+}
+
+
+Hashes& sslHashes::use_certVerify()
+{
+ return certVerify_;
+}
+
+
+Buffers::~Buffers()
+{
+ mySTL::for_each(handShakeList_.begin(), handShakeList_.end(),
+ del_ptr_zero()) ;
+ mySTL::for_each(dataList_.begin(), dataList_.end(),
+ del_ptr_zero()) ;
+}
+
+
+const Buffers::inputList& Buffers::getData() const
+{
+ return dataList_;
+}
+
+
+const Buffers::outputList& Buffers::getHandShake() const
+{
+ return handShakeList_;
+}
+
+
+Buffers::inputList& Buffers::useData()
+{
+ return dataList_;
+}
+
+
+Buffers::outputList& Buffers::useHandShake()
+{
+ return handShakeList_;
+}
+
+
+Security::Security(ProtocolVersion pv, RandomPool& ran, ConnectionEnd ce,
+ const Ciphers& ciphers, SSL_CTX* ctx)
+ : conn_(pv, ran), parms_(ce, ciphers, pv), resumeSession_(ran), ctx_(ctx),
+ resuming_(false)
+{}
+
+
+const Connection& Security::get_connection() const
+{
+ return conn_;
+}
+
+
+const SSL_CTX* Security::GetContext() const
+{
+ return ctx_;
+}
+
+
+const Parameters& Security::get_parms() const
+{
+ return parms_;
+}
+
+
+const SSL_SESSION& Security::get_resume() const
+{
+ return resumeSession_;
+}
+
+
+bool Security::get_resuming() const
+{
+ return resuming_;
+}
+
+
+Connection& Security::use_connection()
+{
+ return conn_;
+}
+
+
+Parameters& Security::use_parms()
+{
+ return parms_;
+}
+
+
+SSL_SESSION& Security::use_resume()
+{
+ return resumeSession_;
+}
+
+
+void Security::set_resuming(bool b)
+{
+ resuming_ = b;
+}
+
+
+X509_NAME::X509_NAME(const char* n, size_t sz)
+ : name_(0)
+{
+ if (sz) {
+ name_ = new (ys) char[sz];
+ memcpy(name_, n, sz);
+ }
+}
+
+
+X509_NAME::~X509_NAME()
+{
+ delete[] name_;
+}
+
+
+char* X509_NAME::GetName()
+{
+ return name_;
+}
+
+
+X509::X509(const char* i, size_t iSz, const char* s, size_t sSz)
+ : issuer_(i, iSz), subject_(s, sSz)
+{}
+
+
+X509_NAME* X509::GetIssuer()
+{
+ return &issuer_;
+}
+
+
+X509_NAME* X509::GetSubject()
+{
+ return &subject_;
+}
+
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/Makefile.am b/extra/yassl/taocrypt/Makefile.am
new file mode 100644
index 00000000000..af3ded7abfd
--- /dev/null
+++ b/extra/yassl/taocrypt/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = src
+EXTRA_DIST = taocrypt.dsw taocrypt.dsp
diff --git a/extra/yassl/taocrypt/include/aes.hpp b/extra/yassl/taocrypt/include/aes.hpp
new file mode 100644
index 00000000000..b2c93eff9fe
--- /dev/null
+++ b/extra/yassl/taocrypt/include/aes.hpp
@@ -0,0 +1,89 @@
+/* aes.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* aes.hpp defines AES
+*/
+
+
+#ifndef TAO_CRYPT_AES_HPP
+#define TAO_CRYPT_AES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+#include "modes.hpp"
+#include "block.hpp"
+
+namespace TaoCrypt {
+
+enum { AES_BLOCK_SIZE = 16 };
+
+
+// AES encryption and decryption, see FIPS-197
+class AES : public Mode_BASE<AES_BLOCK_SIZE> {
+public:
+ enum { BLOCK_SIZE = AES_BLOCK_SIZE };
+
+ AES(CipherDir DIR, Mode MODE) : dir_(DIR), mode_(MODE) {}
+
+ void Process(byte*, const byte*, word32);
+ void SetKey(const byte* iv, word32 sz, CipherDir fake = ENCRYPTION);
+
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ CipherDir dir_;
+ Mode mode_;
+
+ static const word32 Te0[256];
+ static const word32 Te1[256];
+ static const word32 Te2[256];
+ static const word32 Te3[256];
+ static const word32 Te4[256];
+
+ static const word32 Td0[256];
+ static const word32 Td1[256];
+ static const word32 Td2[256];
+ static const word32 Td3[256];
+ static const word32 Td4[256];
+
+ static const word32 rcon_[];
+
+ word32 rounds_;
+ Word32Block key_;
+
+ void encrypt(const byte*, const byte*, byte*) const;
+ void decrypt(const byte*, const byte*, byte*) const;
+
+ AES(const AES&); // hide copy
+ AES& operator=(const AES&); // and assign
+};
+
+
+typedef BlockCipher<ENCRYPTION, AES, ECB> AES_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, AES, ECB> AES_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, AES, CBC> AES_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, AES, CBC> AES_CBC_Decryption;
+
+
+
+} // naemspace
+
+#endif // TAO_CRYPT_AES_HPP
diff --git a/extra/yassl/taocrypt/include/algebra.hpp b/extra/yassl/taocrypt/include/algebra.hpp
new file mode 100644
index 00000000000..74f244507f6
--- /dev/null
+++ b/extra/yassl/taocrypt/include/algebra.hpp
@@ -0,0 +1,316 @@
+/* algebra.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's algebra.h from CryptoPP */
+
+#ifndef TAO_CRYPT_ALGEBRA_HPP
+#define TAO_CRYPT_ALGEBRA_HPP
+
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+class Integer;
+
+// "const Element&" returned by member functions are references
+// to internal data members. Since each object may have only
+// one such data member for holding results, the following code
+// will produce incorrect results:
+// abcd = group.Add(group.Add(a,b), group.Add(c,d));
+// But this should be fine:
+// abcd = group.Add(a, group.Add(b, group.Add(c,d));
+
+//! Abstract Group
+template <class T> class TAOCRYPT_NO_VTABLE AbstractGroup
+{
+public:
+ typedef T Element;
+
+ virtual ~AbstractGroup() {}
+
+ virtual bool Equal(const Element &a, const Element &b) const =0;
+ virtual const Element& Identity() const =0;
+ virtual const Element& Add(const Element &a, const Element &b) const =0;
+ virtual const Element& Inverse(const Element &a) const =0;
+ virtual bool InversionIsFast() const {return false;}
+
+ virtual const Element& Double(const Element &a) const;
+ virtual const Element& Subtract(const Element &a, const Element &b) const;
+ virtual Element& Accumulate(Element &a, const Element &b) const;
+ virtual Element& Reduce(Element &a, const Element &b) const;
+
+ virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
+ virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const;
+
+ virtual void SimultaneousMultiply(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const;
+};
+
+//! Abstract Ring
+template <class T> class TAOCRYPT_NO_VTABLE AbstractRing
+ : public AbstractGroup<T>
+{
+public:
+ typedef T Element;
+
+ AbstractRing() {m_mg.m_pRing = this;}
+ AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
+ AbstractRing& operator=(const AbstractRing &source) {return *this;}
+
+ virtual bool IsUnit(const Element &a) const =0;
+ virtual const Element& MultiplicativeIdentity() const =0;
+ virtual const Element& Multiply(const Element&, const Element&) const =0;
+ virtual const Element& MultiplicativeInverse(const Element &a) const =0;
+
+ virtual const Element& Square(const Element &a) const;
+ virtual const Element& Divide(const Element &a, const Element &b) const;
+
+ virtual Element Exponentiate(const Element &a, const Integer &e) const;
+ virtual Element CascadeExponentiate(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const;
+
+ virtual void SimultaneousExponentiate(Element *results, const Element&,
+ const Integer *exponents, unsigned int exponentsCount) const;
+
+ virtual const AbstractGroup<T>& MultiplicativeGroup() const
+ {return m_mg;}
+
+private:
+ class MultiplicativeGroupT : public AbstractGroup<T>
+ {
+ public:
+ const AbstractRing<T>& GetRing() const
+ {return *m_pRing;}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return GetRing().Equal(a, b);}
+
+ const Element& Identity() const
+ {return GetRing().MultiplicativeIdentity();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return GetRing().Multiply(a, b);}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return a = GetRing().Multiply(a, b);}
+
+ const Element& Inverse(const Element &a) const
+ {return GetRing().MultiplicativeInverse(a);}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return GetRing().Divide(a, b);}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a = GetRing().Divide(a, b);}
+
+ const Element& Double(const Element &a) const
+ {return GetRing().Square(a);}
+
+ Element ScalarMultiply(const Element &a, const Integer &e) const
+ {return GetRing().Exponentiate(a, e);}
+
+ Element CascadeScalarMultiply(const Element &x, const Integer &e1,
+ const Element &y, const Integer &e2) const
+ {return GetRing().CascadeExponentiate(x, e1, y, e2);}
+
+ void SimultaneousMultiply(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const
+ {GetRing().SimultaneousExponentiate(results, base, exponents,
+ exponentsCount);}
+
+ const AbstractRing<T> *m_pRing;
+ };
+
+ MultiplicativeGroupT m_mg;
+};
+
+// ********************************************************
+
+//! Base and Exponent
+template <class T, class E = Integer>
+struct BaseAndExponent
+{
+public:
+ BaseAndExponent() {}
+ BaseAndExponent(const T &base, const E &exponent) : base(base),
+ exponent(exponent) {}
+ bool operator<(const BaseAndExponent<T, E> &rhs) const
+ {return exponent < rhs.exponent;}
+ T base;
+ E exponent;
+};
+
+// VC60 workaround: incomplete member template support
+template <class Element, class Iterator>
+ Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group,
+ Iterator begin, Iterator end);
+template <class Element, class Iterator>
+ Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring,
+ Iterator begin, Iterator end);
+
+// ********************************************************
+
+//! Abstract Euclidean Domain
+template <class T> class TAOCRYPT_NO_VTABLE AbstractEuclideanDomain
+ : public AbstractRing<T>
+{
+public:
+ typedef T Element;
+
+ virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a,
+ const Element &d) const =0;
+
+ virtual const Element& Mod(const Element &a, const Element &b) const =0;
+ virtual const Element& Gcd(const Element &a, const Element &b) const;
+
+protected:
+ mutable Element result;
+};
+
+// ********************************************************
+
+//! EuclideanDomainOf
+template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
+{
+public:
+ typedef T Element;
+
+ EuclideanDomainOf() {}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return a==b;}
+
+ const Element& Identity() const
+ {return Element::Zero();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return result = a+b;}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return a+=b;}
+
+ const Element& Inverse(const Element &a) const
+ {return result = -a;}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return result = a-b;}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return a-=b;}
+
+ const Element& Double(const Element &a) const
+ {return result = a.Doubled();}
+
+ const Element& MultiplicativeIdentity() const
+ {return Element::One();}
+
+ const Element& Multiply(const Element &a, const Element &b) const
+ {return result = a*b;}
+
+ const Element& Square(const Element &a) const
+ {return result = a.Squared();}
+
+ bool IsUnit(const Element &a) const
+ {return a.IsUnit();}
+
+ const Element& MultiplicativeInverse(const Element &a) const
+ {return result = a.MultiplicativeInverse();}
+
+ const Element& Divide(const Element &a, const Element &b) const
+ {return result = a/b;}
+
+ const Element& Mod(const Element &a, const Element &b) const
+ {return result = a%b;}
+
+ void DivisionAlgorithm(Element &r, Element &q, const Element &a,
+ const Element &d) const
+ {Element::Divide(r, q, a, d);}
+
+private:
+ mutable Element result;
+};
+
+//! Quotient Ring
+template<class T> class QuotientRing : public AbstractRing<typename T::Element>
+{
+public:
+ typedef T EuclideanDomain;
+ typedef typename T::Element Element;
+
+ QuotientRing(const EuclideanDomain &domain, const Element &modulus)
+ : m_domain(domain), m_modulus(modulus) {}
+
+ const EuclideanDomain & GetDomain() const
+ {return m_domain;}
+
+ const Element& GetModulus() const
+ {return m_modulus;}
+
+ bool Equal(const Element &a, const Element &b) const
+ {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b),
+ m_modulus), m_domain.Identity());}
+
+ const Element& Identity() const
+ {return m_domain.Identity();}
+
+ const Element& Add(const Element &a, const Element &b) const
+ {return m_domain.Add(a, b);}
+
+ Element& Accumulate(Element &a, const Element &b) const
+ {return m_domain.Accumulate(a, b);}
+
+ const Element& Inverse(const Element &a) const
+ {return m_domain.Inverse(a);}
+
+ const Element& Subtract(const Element &a, const Element &b) const
+ {return m_domain.Subtract(a, b);}
+
+ Element& Reduce(Element &a, const Element &b) const
+ {return m_domain.Reduce(a, b);}
+
+ const Element& Double(const Element &a) const
+ {return m_domain.Double(a);}
+
+ bool IsUnit(const Element &a) const
+ {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
+
+ const Element& MultiplicativeIdentity() const
+ {return m_domain.MultiplicativeIdentity();}
+
+ const Element& Multiply(const Element &a, const Element &b) const
+ {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
+
+ const Element& Square(const Element &a) const
+ {return m_domain.Mod(m_domain.Square(a), m_modulus);}
+
+ const Element& MultiplicativeInverse(const Element &a) const;
+
+protected:
+ EuclideanDomain m_domain;
+ Element m_modulus;
+};
+
+
+} // namespace
+
+
+#endif // TAO_CRYPT_ALGEBRA_HPP
diff --git a/extra/yassl/taocrypt/include/arc4.hpp b/extra/yassl/taocrypt/include/arc4.hpp
new file mode 100644
index 00000000000..c919c8ea2ae
--- /dev/null
+++ b/extra/yassl/taocrypt/include/arc4.hpp
@@ -0,0 +1,59 @@
+/* arc4.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* arc4.hpp defines ARC4
+*/
+
+
+#ifndef TAO_CRYPT_ARC4_HPP
+#define TAO_CRYPT_ARC4_HPP
+
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+// ARC4 encryption and decryption
+class ARC4 {
+public:
+ enum { STATE_SIZE = 256 };
+
+ typedef ARC4 Encryption;
+ typedef ARC4 Decryption;
+
+ ARC4() {}
+
+ void Process(byte*, const byte*, word32);
+ void SetKey(const byte*, word32);
+private:
+ byte x_;
+ byte y_;
+ byte state_[STATE_SIZE];
+
+ ARC4(const ARC4&); // hide copy
+ const ARC4 operator=(const ARC4&); // and assign
+};
+
+} // namespace
+
+
+#endif // TAO_CRYPT_ARC4_HPP
+
diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp
new file mode 100644
index 00000000000..71633339a40
--- /dev/null
+++ b/extra/yassl/taocrypt/include/asn.hpp
@@ -0,0 +1,327 @@
+/* asn.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* asn.hpp provides ASN1 BER, PublicKey, and x509v3 decoding
+*/
+
+
+#ifndef TAO_CRYPT_ASN_HPP
+#define TAO_CRYPT_ASN_HPP
+
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "list.hpp"
+#include "error.hpp"
+
+
+
+namespace TaoCrypt {
+
+// these tags and flags are not complete
+enum ASNTag
+{
+ BOOLEAN = 0x01,
+ INTEGER = 0x02,
+ BIT_STRING = 0x03,
+ OCTET_STRING = 0x04,
+ TAG_NULL = 0x05,
+ OBJECT_IDENTIFIER = 0x06,
+ OBJECT_DESCRIPTOR = 0x07,
+ EXTERNAL = 0x08,
+ REAL = 0x09,
+ ENUMERATED = 0x0a,
+ UTF8_STRING = 0x0c,
+ SEQUENCE = 0x10,
+ SET = 0x11,
+ NUMERIC_STRING = 0x12,
+ PRINTABLE_STRING = 0x13,
+ T61_STRING = 0x14,
+ VIDEOTEXT_STRING = 0x15,
+ IA5_STRING = 0x16,
+ UTC_TIME = 0x17,
+ GENERALIZED_TIME = 0x18,
+ GRAPHIC_STRING = 0x19,
+ VISIBLE_STRING = 0x1a,
+ GENERAL_STRING = 0x1b,
+ LONG_LENGTH = 0x80
+};
+
+enum ASNIdFlag
+{
+ UNIVERSAL = 0x00,
+ DATA = 0x01,
+ HEADER = 0x02,
+ CONSTRUCTED = 0x20,
+ APPLICATION = 0x40,
+ CONTEXT_SPECIFIC = 0x80,
+ PRIVATE = 0xc0
+};
+
+
+enum DNTags
+{
+ COMMON_NAME = 0x03,
+};
+
+
+enum Constants
+{
+ MIN_DATE_SZ = 13,
+ MAX_DATE_SZ = 15,
+ MAX_ALGO_SZ = 16,
+ MAX_LENGTH_SZ = 5,
+ MAX_SEQ_SZ = 5, // enum(seq|con) + length(4)
+ MAX_ALGO_SIZE = 9,
+ MAX_DIGEST_SZ = 25, // SHA + enum(Bit or Octet) + length(4)
+ DSA_SIG_SZ = 40,
+};
+
+
+class Source;
+class RSA_PublicKey;
+class RSA_PrivateKey;
+class DSA_PublicKey;
+class DSA_PrivateKey;
+class Integer;
+class DH;
+
+
+// General BER decoding
+class BER_Decoder {
+protected:
+ Source& source_;
+public:
+ explicit BER_Decoder(Source& s) : source_(s) {}
+ virtual ~BER_Decoder() {}
+
+ Integer& GetInteger(Integer&);
+ word32 GetSequence();
+ word32 GetSet();
+ word32 GetVersion();
+ word32 GetExplicitVersion();
+
+ Error GetError();
+private:
+ virtual void ReadHeader() = 0;
+
+ BER_Decoder(const BER_Decoder&); // hide copy
+ BER_Decoder& operator=(const BER_Decoder&); // and assign
+};
+
+
+// RSA Private Key BER Decoder
+class RSA_Private_Decoder : public BER_Decoder {
+public:
+ explicit RSA_Private_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(RSA_PrivateKey&);
+private:
+ void ReadHeader();
+};
+
+
+// RSA Public Key BER Decoder
+class RSA_Public_Decoder : public BER_Decoder {
+public:
+ explicit RSA_Public_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(RSA_PublicKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DSA Private Key BER Decoder
+class DSA_Private_Decoder : public BER_Decoder {
+public:
+ explicit DSA_Private_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DSA_PrivateKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DSA Public Key BER Decoder
+class DSA_Public_Decoder : public BER_Decoder {
+public:
+ explicit DSA_Public_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DSA_PublicKey&);
+private:
+ void ReadHeader();
+};
+
+
+// DH Key BER Decoder
+class DH_Decoder : public BER_Decoder {
+public:
+ explicit DH_Decoder(Source& s) : BER_Decoder(s) {}
+ void Decode(DH&);
+private:
+ void ReadHeader();
+};
+
+
+// General PublicKey
+class PublicKey {
+ byte* key_;
+ word32 sz_;
+public:
+ explicit PublicKey(const byte* k = 0, word32 s = 0);
+ ~PublicKey() { delete[] key_; }
+
+ const byte* GetKey() const { return key_; }
+ word32 size() const { return sz_; }
+
+ void SetKey(const byte*);
+ void SetSize(word32 s);
+
+ void AddToEnd(const byte*, word32);
+private:
+ PublicKey(const PublicKey&); // hide copy
+ PublicKey& operator=(const PublicKey&); // and assign
+};
+
+
+enum { SHA_SIZE = 20 };
+
+
+// A Signing Authority
+class Signer {
+ PublicKey key_;
+ char* name_;
+ byte hash_[SHA_SIZE];
+public:
+ Signer(const byte* k, word32 kSz, const char* n, const byte* h);
+ ~Signer();
+
+ const PublicKey& GetPublicKey() const { return key_; }
+ const char* GetCommonName() const { return name_; }
+ const byte* GetHash() const { return hash_; }
+
+private:
+ Signer(const Signer&); // hide copy
+ Signer& operator=(const Signer&); // and assign
+};
+
+
+typedef mySTL::list<Signer*> SignerList;
+
+
+enum SigType { SHAwDSA = 517, MD2wRSA = 646, MD5wRSA = 648, SHAwRSA =649};
+enum HashType { MD2h = 646, MD5h = 649, SHAh = 88 };
+enum KeyType { DSAk = 515, RSAk = 645 }; // sums of algo OID
+
+
+// an x509v Certificate BER Decoder
+class CertDecoder : public BER_Decoder {
+public:
+ explicit CertDecoder(Source&, bool decode = true, SignerList* = 0);
+ ~CertDecoder();
+
+ const PublicKey& GetPublicKey() const { return key_; }
+ KeyType GetKeyType() const { return KeyType(keyOID_); }
+ const char* GetIssuer() const { return issuer_; }
+ const char* GetCommonName() const { return subject_; }
+ const byte* GetHash() const { return subjectHash_; }
+
+ void DecodeToKey();
+
+ enum DateType { BEFORE, AFTER };
+ enum NameType { ISSUER, SUBJECT };
+private:
+ PublicKey key_;
+ word32 certBegin_; // offset to start of cert
+ word32 sigIndex_; // offset to start of signature
+ word32 sigLength_; // length of signature
+ word32 signatureOID_; // sum of algorithm object id
+ word32 keyOID_; // sum of key algo object id
+ byte subjectHash_[SHA_SIZE]; // hash of all Names
+ byte issuerHash_[SHA_SIZE]; // hash of all Names
+ byte* signature_;
+ char* issuer_; // CommonName
+ char* subject_; // CommonName
+
+ void ReadHeader();
+ void Decode(SignerList*);
+ void StoreKey();
+ void AddDSA();
+ bool ValidateSelfSignature();
+ bool ValidateSignature(SignerList*);
+ bool ConfirmSignature(Source&);
+ void GetKey();
+ void GetName(NameType);
+ void GetValidity();
+ void GetDate(DateType);
+ void GetCompareHash(const byte*, word32, byte*, word32);
+ word32 GetAlgoId();
+ word32 GetSignature();
+ word32 GetDigest();
+};
+
+
+word32 GetLength(Source&);
+
+word32 SetLength(word32, byte*);
+word32 SetSequence(word32, byte*);
+
+word32 EncodeDSA_Signature(const byte* signature, byte* output);
+word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output);
+word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz);
+
+
+// General DER encoding
+class DER_Encoder {
+public:
+ DER_Encoder() {}
+ virtual ~DER_Encoder() {}
+
+ word32 SetAlgoID(HashType, byte*);
+
+ Error GetError() const { return error_; }
+private:
+ //virtual void WriteHeader() = 0;
+ Error error_;
+
+ DER_Encoder(const DER_Encoder&); // hide copy
+ DER_Encoder& operator=(const DER_Encoder&); // and assign
+};
+
+
+
+class Signature_Encoder : public DER_Encoder {
+ const byte* digest_;
+ word32 digestSz_;
+ SigType digestOID_;
+public:
+ explicit Signature_Encoder(const byte*, word32, HashType, Source&);
+
+private:
+ void WriteHeader();
+ word32 SetDigest(const byte*, word32, byte*);
+
+ Signature_Encoder(const Signature_Encoder&); // hide copy
+ Signature_Encoder& operator=(const Signature_Encoder&); // and assign
+};
+
+
+} // namespace
+
+
+#endif // TAO_CRYPT_ASN_HPP
diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp
new file mode 100644
index 00000000000..6e96ec9cc35
--- /dev/null
+++ b/extra/yassl/taocrypt/include/block.hpp
@@ -0,0 +1,211 @@
+/* block.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* block.hpp provides word and byte blocks with configurable allocators
+*/
+
+
+#ifndef TAO_CRYPT_BLOCK_HPP
+#define TAO_CRYPT_BLOCK_HPP
+
+#include "algorithm.hpp" // mySTL::swap
+#include "stdexcept.hpp" // mySTL::runtime_error
+#include "misc.hpp"
+#include <string.h> // memcpy
+#include <cstddef> // ptrdiff_t
+
+
+#if defined(_MSC_VER) && defined(_CRTAPI1)
+#define TAOCRYPT_MSVCRT6
+#endif
+
+
+namespace TaoCrypt {
+
+
+// a Base class for Allocators
+template<class T>
+class AllocatorBase
+{
+public:
+ typedef T value_type;
+ typedef size_t size_type;
+#ifdef TAOCRYPT_MSVCRT6
+ typedef ptrdiff_t difference_type;
+#else
+ typedef std::ptrdiff_t difference_type;
+#endif
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+
+ pointer address(reference r) const {return (&r);}
+ const_pointer address(const_reference r) const {return (&r); }
+ void construct(pointer p, const T& val) {new (p) T(val);}
+ void destroy(pointer p) {p->~T();}
+ size_type max_size() const {return ~size_type(0)/sizeof(T);}
+protected:
+ static void CheckSize(size_t n)
+ {
+ assert(n <= ~size_t(0) / sizeof(T));
+ }
+};
+
+
+// General purpose realloc
+template<typename T, class A>
+typename A::pointer StdReallocate(A& a, T* p, typename A::size_type oldSize,
+ typename A::size_type newSize, bool preserve)
+{
+ if (oldSize == newSize)
+ return p;
+
+ if (preserve) {
+ A b = A();
+ typename A::pointer newPointer = b.allocate(newSize, 0);
+ memcpy(newPointer, p, sizeof(T) * min(oldSize, newSize));
+ a.deallocate(p, oldSize);
+ mySTL::swap(a, b);
+ return newPointer;
+ }
+ else {
+ a.deallocate(p, oldSize);
+ return a.allocate(newSize, 0);
+ }
+}
+
+
+// Allocator that zeros out memory on deletion
+template <class T>
+class AllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+ typedef typename AllocatorBase<T>::pointer pointer;
+ typedef typename AllocatorBase<T>::size_type size_type;
+
+ pointer allocate(size_type n, const void* = 0)
+ {
+ CheckSize(n);
+ if (n == 0)
+ return 0;
+ return new (tc) T[n];
+ }
+
+ void deallocate(void* p, size_type n)
+ {
+ memset(p, 0, n * sizeof(T));
+ delete [] (T*)p;
+ }
+
+ pointer reallocate(T* p, size_type oldSize, size_type newSize,
+ bool preserve)
+ {
+ return StdReallocate(*this, p, oldSize, newSize, preserve);
+ }
+
+ // VS.NET STL enforces the policy of "All STL-compliant allocators have to
+ // provide a template class member called rebind".
+ template <class U> struct rebind { typedef AllocatorWithCleanup<U> other;};
+};
+
+
+// Block class template
+template<typename T, class A = AllocatorWithCleanup<T> >
+class Block {
+public:
+ explicit Block(word32 s = 0) : sz_(s), buffer_(allocator_.allocate(sz_))
+ { CleanNew(sz_); }
+
+ Block(const T* buff, word32 s) : sz_(s), buffer_(allocator_.allocate(sz_))
+ { memcpy(buffer_, buff, sz_ * sizeof(T)); }
+
+ Block(const Block& that) : sz_(that.sz_), buffer_(allocator_.allocate(sz_))
+ { memcpy(buffer_, that.buffer_, sz_ * sizeof(T)); }
+
+ Block& operator=(const Block& that) {
+ Block tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ T& operator[] (word32 i) { assert(i < sz_); return buffer_[i]; }
+ const T& operator[] (word32 i) const
+ { assert(i < sz_); return buffer_[i]; }
+
+ T* operator+ (word32 i) { return buffer_ + i; }
+ const T* operator+ (word32 i) const { return buffer_ + i; }
+
+ word32 size() const { return sz_; }
+
+ T* get_buffer() const { return buffer_; }
+ T* begin() const { return get_buffer(); }
+
+ void CleanGrow(word32 newSize)
+ {
+ if (newSize > sz_) {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true);
+ memset(buffer_ + sz_, 0, (newSize - sz_) * sizeof(T));
+ sz_ = newSize;
+ }
+ }
+
+ void CleanNew(word32 newSize)
+ {
+ New(newSize);
+ memset(buffer_, 0, sz_ * sizeof(T));
+ }
+
+ void New(word32 newSize)
+ {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, false);
+ sz_ = newSize;
+ }
+
+ void resize(word32 newSize)
+ {
+ buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true);
+ sz_ = newSize;
+ }
+
+ void Swap(Block& other) {
+ mySTL::swap(sz_, other.sz_);
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(allocator_, other.allocator_);
+ }
+
+ ~Block() { allocator_.deallocate(buffer_, sz_); }
+private:
+ word32 sz_; // size in Ts
+ T* buffer_;
+ A allocator_;
+};
+
+
+typedef Block<byte> ByteBlock;
+typedef Block<word> WordBlock;
+typedef Block<word32> Word32Block;
+
+
+} // namespace
+
+#endif // TAO_CRYPT_BLOCK_HPP
diff --git a/extra/yassl/taocrypt/include/coding.hpp b/extra/yassl/taocrypt/include/coding.hpp
new file mode 100644
index 00000000000..9aab2a30c7e
--- /dev/null
+++ b/extra/yassl/taocrypt/include/coding.hpp
@@ -0,0 +1,94 @@
+/* coding.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* coding.hpp defines hex and base64 encoding/decoing
+*/
+
+#ifndef TAO_CRYPT_CODING_HPP
+#define TAO_CRYPT_CODING_HPP
+
+#include "misc.hpp"
+#include "block.hpp"
+
+namespace TaoCrypt {
+
+class Source;
+
+
+// Hex Encoding, see RFC 3548
+class HexEncoder {
+ ByteBlock encoded_;
+ Source& plain_;
+public:
+ explicit HexEncoder(Source& s) : plain_(s) { Encode(); }
+private:
+ void Encode();
+
+ HexEncoder(const HexEncoder&); // hide copy
+ HexEncoder& operator=(const HexEncoder&); // and assign
+};
+
+
+// Hex Decoding, see RFC 3548
+class HexDecoder {
+ ByteBlock decoded_;
+ Source& coded_;
+public:
+ explicit HexDecoder(Source& s) : coded_(s) { Decode(); }
+private:
+ void Decode();
+
+ HexDecoder(const HexDecoder&); // hide copy
+ HexDecoder& operator=(const HexDecoder&); // and assign
+};
+
+
+// Base 64 encoding, see RFC 3548
+class Base64Encoder {
+ ByteBlock encoded_;
+ Source& plain_;
+public:
+ explicit Base64Encoder(Source& s) : plain_(s) { Encode(); }
+private:
+ void Encode();
+
+ Base64Encoder(const Base64Encoder&); // hide copy
+ Base64Encoder& operator=(const Base64Encoder&); // and assign
+};
+
+
+// Base 64 decoding, see RFC 3548
+class Base64Decoder {
+ ByteBlock decoded_;
+ Source& coded_;
+public:
+ explicit Base64Decoder(Source& s) : coded_(s) { Decode(); }
+private:
+ void Decode();
+
+ Base64Decoder(const Base64Decoder&); // hide copy
+ Base64Decoder& operator=(const Base64Decoder&); // and assign
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_CODING_HPP
diff --git a/extra/yassl/taocrypt/include/des.hpp b/extra/yassl/taocrypt/include/des.hpp
new file mode 100644
index 00000000000..e8100b4e198
--- /dev/null
+++ b/extra/yassl/taocrypt/include/des.hpp
@@ -0,0 +1,121 @@
+/* des.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* des.hpp defines DES, DES_EDE2, and DES_EDE3
+ see FIPS 46-2 and FIPS 81
+*/
+
+
+#ifndef TAO_CRYPT_DES_HPP
+#define TAO_CRYPT_DES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+#include "modes.hpp"
+
+namespace TaoCrypt {
+
+enum { DES_BLOCK_SIZE = 8 };
+
+// Base for all DES types
+class DES_BASE : public Mode_BASE<DES_BLOCK_SIZE> {
+public:
+ enum { BLOCK_SIZE = DES_BLOCK_SIZE, KEY_SIZE = 32, BOXES = 8,
+ BOX_SIZE = 64 };
+
+ DES_BASE(CipherDir DIR, Mode MODE) : dir_(DIR), mode_(MODE) {}
+
+ void Process(byte*, const byte*, word32);
+protected:
+ CipherDir dir_;
+ Mode mode_;
+private:
+ DES_BASE(const DES_BASE&); // hide copy
+ DES_BASE& operator=(const DES_BASE&); // and assign
+};
+
+
+// DES
+class DES : public DES_BASE {
+public:
+ DES(CipherDir DIR, Mode MODE) : DES_BASE(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void RawProcessBlock(word32&, word32&) const;
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ word32 k_[KEY_SIZE];
+};
+
+
+// DES_EDE2
+class DES_EDE2 : public DES_BASE {
+public:
+ DES_EDE2(CipherDir DIR, Mode MODE)
+ : DES_BASE(DIR, MODE), des1_(DIR, MODE), des2_(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ DES des1_;
+ DES des2_;
+};
+
+
+// DES_EDE3
+class DES_EDE3 : public DES_BASE {
+public:
+ DES_EDE3(CipherDir DIR, Mode MODE)
+ : DES_BASE(DIR, MODE), des1_(DIR, MODE), des2_(DIR, MODE),
+ des3_(DIR, MODE) {}
+
+ void SetKey(const byte*, word32, CipherDir dir);
+ void ProcessAndXorBlock(const byte*, const byte*, byte*) const;
+private:
+ DES des1_;
+ DES des2_;
+ DES des3_;
+};
+
+
+typedef BlockCipher<ENCRYPTION, DES, ECB> DES_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES, ECB> DES_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES, CBC> DES_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES, CBC> DES_CBC_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE2, ECB> DES_EDE2_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE2, ECB> DES_EDE2_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE2, CBC> DES_EDE2_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE2, CBC> DES_EDE2_CBC_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE3, ECB> DES_EDE3_ECB_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE3, ECB> DES_EDE3_ECB_Decryption;
+
+typedef BlockCipher<ENCRYPTION, DES_EDE3, CBC> DES_EDE3_CBC_Encryption;
+typedef BlockCipher<DECRYPTION, DES_EDE3, CBC> DES_EDE3_CBC_Decryption;
+
+
+} // namespace
+
+
+#endif // TAO_CRYPT_DES_HPP
diff --git a/extra/yassl/taocrypt/include/dh.hpp b/extra/yassl/taocrypt/include/dh.hpp
new file mode 100644
index 00000000000..54a1705546b
--- /dev/null
+++ b/extra/yassl/taocrypt/include/dh.hpp
@@ -0,0 +1,89 @@
+/* dh.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* dh.hpp provides Diffie-Hellman support
+*/
+
+
+#ifndef TAO_CRYPT_DH_HPP
+#define TAO_CRYPT_DH_HPP
+
+#include "misc.hpp"
+#include "integer.hpp"
+
+namespace TaoCrypt {
+
+
+class Source;
+
+
+// Diffie-Hellman
+class DH {
+public:
+ DH() {}
+ DH(Integer& p, Integer& g) : p_(p), g_(g) {}
+ explicit DH(Source&);
+
+ DH(const DH& that) : p_(that.p_), g_(that.g_) {}
+ DH& operator=(const DH& that)
+ {
+ DH tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(DH& other)
+ {
+ p_.Swap(other.p_);
+ g_.Swap(other.g_);
+ }
+
+ void Initialize(Source&);
+ void Initialize(Integer& p, Integer& g)
+ {
+ SetP(p);
+ SetG(g);
+ }
+
+ void GenerateKeyPair(RandomNumberGenerator&, byte*, byte*);
+ void Agree(byte*, const byte*, const byte*);
+
+ void SetP(const Integer& p) { p_ = p; }
+ void SetG(const Integer& g) { g_ = g; }
+
+ Integer& GetP() { return p_; }
+ Integer& GetG() { return g_; }
+
+ // for p and agree
+ word32 GetByteLength() const { return p_.ByteCount(); }
+private:
+ // group parms
+ Integer p_;
+ Integer g_;
+
+ void GeneratePrivate(RandomNumberGenerator&, byte*);
+ void GeneratePublic(const byte*, byte*);
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_DH_HPP
diff --git a/extra/yassl/taocrypt/include/dsa.hpp b/extra/yassl/taocrypt/include/dsa.hpp
new file mode 100644
index 00000000000..f1fdd2dfa25
--- /dev/null
+++ b/extra/yassl/taocrypt/include/dsa.hpp
@@ -0,0 +1,129 @@
+/* dsa.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* dsa.hpp provides Digitial Signautre Algorithm see FIPS 186-2
+*/
+
+#ifndef TAO_CRYPT_DSA_HPP
+#define TAO_CRYPT_DSA_HPP
+
+#include "integer.hpp"
+
+
+namespace TaoCrypt {
+
+class Source;
+
+
+class DSA_PublicKey {
+protected:
+ Integer p_;
+ Integer q_;
+ Integer g_;
+ Integer y_;
+public:
+ DSA_PublicKey() {}
+ explicit DSA_PublicKey(Source&);
+
+ void Initialize(Source&);
+ void Initialize(const Integer& p, const Integer& q, const Integer& g,
+ const Integer& y);
+
+ const Integer& GetModulus() const;
+ const Integer& GetSubGroupOrder() const;
+ const Integer& GetSubGroupGenerator() const;
+ const Integer& GetPublicPart() const;
+
+ void SetModulus(const Integer&);
+ void SetSubGroupOrder(const Integer&);
+ void SetSubGroupGenerator(const Integer&);
+ void SetPublicPart(const Integer&);
+
+ word32 SignatureLength() const;
+
+ DSA_PublicKey(const DSA_PublicKey&);
+ DSA_PublicKey& operator=(const DSA_PublicKey&);
+
+ void Swap(DSA_PublicKey& other);
+};
+
+
+
+class DSA_PrivateKey : public DSA_PublicKey {
+ Integer x_;
+public:
+ DSA_PrivateKey() {}
+ explicit DSA_PrivateKey(Source&);
+
+ void Initialize(Source&);
+ void Initialize(const Integer& p, const Integer& q, const Integer& g,
+ const Integer& y, const Integer& x);
+
+ const Integer& GetPrivatePart() const;
+
+ void SetPrivatePart(const Integer&);
+private:
+ DSA_PrivateKey(const DSA_PrivateKey&); // hide copy
+ DSA_PrivateKey& operator=(const DSA_PrivateKey&); // and assign
+};
+
+
+
+class DSA_Signer {
+ const DSA_PrivateKey& key_;
+ Integer r_;
+ Integer s_;
+public:
+ explicit DSA_Signer(const DSA_PrivateKey&);
+
+ word32 Sign(const byte* sha_digest, byte* sig, RandomNumberGenerator&);
+
+ const Integer& GetR() const;
+ const Integer& GetS() const;
+private:
+ DSA_Signer(const DSA_Signer&); // hide copy
+ DSA_Signer& operator=(DSA_Signer&); // and assign
+};
+
+
+class DSA_Verifier {
+ const DSA_PublicKey& key_;
+ Integer r_;
+ Integer s_;
+public:
+ explicit DSA_Verifier(const DSA_PublicKey&);
+
+ bool Verify(const byte* sha_digest, const byte* sig);
+
+ const Integer& GetR() const;
+ const Integer& GetS() const;
+private:
+ DSA_Verifier(const DSA_Verifier&); // hide copy
+ DSA_Verifier& operator=(const DSA_Verifier&); // and assign
+};
+
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_DSA_HPP
diff --git a/extra/yassl/taocrypt/include/error.hpp b/extra/yassl/taocrypt/include/error.hpp
new file mode 100644
index 00000000000..cb7f82731c7
--- /dev/null
+++ b/extra/yassl/taocrypt/include/error.hpp
@@ -0,0 +1,86 @@
+/* error.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* error.hpp provides a taocrypt error numbers
+ *
+ */
+
+
+#ifndef TAO_CRYPT_ERROR_HPP
+#define TAO_CRYPT_ERROR_HPP
+
+
+namespace TaoCrypt {
+
+
+enum ErrorNumber {
+
+NO_ERROR = 0, // "not in error state"
+
+// RandomNumberGenerator
+WINCRYPT_E = 1001, // "bad wincrypt acquire"
+CRYPTGEN_E = 1002, // "CryptGenRandom error"
+OPEN_RAN_E = 1003, // "open /dev/urandom error"
+READ_RAN_E = 1004, // "read /dev/urandom error"
+
+// Integer
+INTEGER_E = 1010, // "bad DER Integer Header"
+
+
+// ASN.1
+SEQUENCE_E = 1020, // "bad Sequence Header"
+SET_E = 1021, // "bad Set Header"
+VERSION_E = 1022, // "version length not 1"
+SIG_OID_E = 1023, // "signature OID mismatch"
+BIT_STR_E = 1024, // "bad BitString Header"
+UNKNOWN_OID_E = 1025, // "unknown key OID type"
+OBJECT_ID_E = 1026, // "bad Ojbect ID Header"
+TAG_NULL_E = 1027, // "expected TAG NULL"
+EXPECT_0_E = 1028, // "expected 0"
+OCTET_STR_E = 1029, // "bad Octet String Header"
+TIME_E = 1030, // "bad TIME"
+
+DATE_SZ_E = 1031, // "bad Date Size"
+SIG_LEN_E = 1032, // "bad Signature Length"
+UNKOWN_SIG_E = 1033, // "unknown signature OID"
+UNKOWN_HASH_E = 1034, // "unknown hash OID"
+DSA_SZ_E = 1035, // "bad DSA r or s size"
+BEFORE_DATE_E = 1036, // "before date in the future"
+AFTER_DATE_E = 1037, // "after date in the past"
+SIG_CONFIRM_E = 1038, // "bad signature confirmation"
+
+};
+
+
+struct Error {
+ ErrorNumber what_; // description number, 0 for no error
+
+ explicit Error(ErrorNumber w = NO_ERROR) : what_(w) {}
+
+ ErrorNumber What() const { return what_; }
+ void SetError(ErrorNumber w) { what_ = w; }
+};
+
+
+
+} // namespace TaoCrypt
+
+#endif // TAO_CRYPT_ERROR_HPP
diff --git a/extra/yassl/taocrypt/include/file.hpp b/extra/yassl/taocrypt/include/file.hpp
new file mode 100644
index 00000000000..b27ab3aebf3
--- /dev/null
+++ b/extra/yassl/taocrypt/include/file.hpp
@@ -0,0 +1,124 @@
+/* file.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* file.hpp provies File Sources and Sinks
+*/
+
+
+#ifndef TAO_CRYPT_FILE_HPP
+#define TAO_CRYPT_FILE_HPP
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "error.hpp"
+#include <cstdio>
+
+namespace TaoCrypt {
+
+
+class Source {
+ ByteBlock buffer_;
+ word32 current_;
+ Error error_;
+public:
+ explicit Source(word32 sz = 0) : buffer_(sz), current_(0) {}
+ Source(const byte* b, word32 sz) : buffer_(b, sz), current_(0) {}
+
+ word32 size() const { return buffer_.size(); }
+ void grow(word32 sz) { buffer_.CleanGrow(sz); }
+
+ const byte* get_buffer() const { return buffer_.get_buffer(); }
+ const byte* get_current() const { return &buffer_[current_]; }
+ word32 get_index() const { return current_; }
+ void set_index(word32 i) { current_ = i; }
+
+ byte operator[] (word32 i) { current_ = i; return next(); }
+ byte next() { return buffer_[current_++]; }
+ byte prev() { return buffer_[--current_]; }
+
+ void add(const byte* data, word32 len)
+ {
+ memcpy(buffer_.get_buffer() + current_, data, len);
+ current_ += len;
+ }
+
+ void advance(word32 i) { current_ += i; }
+ void reset(ByteBlock&);
+
+ Error GetError() { return error_; }
+ void SetError(ErrorNumber w) { error_.SetError(w); }
+
+ friend class FileSource; // for get()
+private:
+ Source(const Source& that) : buffer_(that.buffer_), current_(that.current_) {}
+ Source& operator=(const Source& that)
+ {
+ Source tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(Source& other)
+ {
+ buffer_.Swap(other.buffer_);
+ mySTL::swap(current_, other.current_);
+ }
+
+};
+
+
+// File Source
+class FileSource {
+ FILE* file_;
+public:
+ FileSource(const char* fname, Source& source);
+ ~FileSource();
+
+ word32 size(bool use_current = false);
+private:
+ word32 get(Source&);
+ word32 size_left();
+
+ FileSource(const FileSource&); // hide
+ FileSource& operator=(const FileSource&); // hide
+};
+
+
+// File Sink
+class FileSink {
+ FILE* file_;
+public:
+ FileSink(const char* fname, Source& source);
+ ~FileSink();
+
+ word32 size(bool use_current = false);
+private:
+ void put(Source&);
+
+ FileSink(const FileSink&); // hide
+ FileSink& operator=(const FileSink&); // hide
+};
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_FILE_HPP
diff --git a/extra/yassl/taocrypt/include/hash.hpp b/extra/yassl/taocrypt/include/hash.hpp
new file mode 100644
index 00000000000..1703de23713
--- /dev/null
+++ b/extra/yassl/taocrypt/include/hash.hpp
@@ -0,0 +1,73 @@
+/* hash.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* hash.hpp provides a base for digest types
+*/
+
+
+#ifndef TAO_CRYPT_HASH_HPP
+#define TAO_CRYPT_HASH_HPP
+
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+// HASH
+class HASH {
+public:
+ virtual ~HASH() {}
+
+ virtual void Update(const byte*, word32) = 0;
+ virtual void Final(byte*) = 0;
+
+ virtual void Init() = 0;
+
+ virtual word32 getBlockSize() const = 0;
+ virtual word32 getDigestSize() const = 0;
+};
+
+
+// HASH with Transform
+class HASHwithTransform : public HASH {
+public:
+ HASHwithTransform(word32 digSz, word32 buffSz)
+ : digest_(new (tc) word32[digSz]), buffer_(new (tc) byte[buffSz]) {}
+ virtual ~HASHwithTransform() { delete[] buffer_; delete[] digest_; }
+
+ virtual ByteOrder getByteOrder() const = 0;
+ virtual word32 getPadSize() const = 0;
+
+ virtual void Update(const byte*, word32);
+ virtual void Final(byte*);
+protected:
+ word32 buffLen_;
+ word32 length_; // in Bits
+ word32* digest_;
+ byte* buffer_;
+
+ virtual void Transform() = 0;
+};
+
+
+} // namespace
+
+#endif // TAO_CRYPT_HASH_HPP
diff --git a/extra/yassl/taocrypt/include/hmac.hpp b/extra/yassl/taocrypt/include/hmac.hpp
new file mode 100644
index 00000000000..dcfef225d89
--- /dev/null
+++ b/extra/yassl/taocrypt/include/hmac.hpp
@@ -0,0 +1,128 @@
+/* hmac.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* hamc.hpp implements HMAC, see RFC 2104
+*/
+
+
+#ifndef TAO_CRYPT_HMAC_HPP
+#define TAO_CRYPT_HMAC_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// HMAC class template
+template <class T>
+class HMAC {
+public:
+ enum { IPAD = 0x36, OPAD = 0x5C };
+
+ HMAC() { Init(); }
+ void Update(const byte*, word32);
+ void Final(byte*);
+ void Init();
+
+ void SetKey(const byte*, word32);
+private:
+ byte ipad_[T::BLOCK_SIZE];
+ byte opad_[T::BLOCK_SIZE];
+ byte innerHash_[T::DIGEST_SIZE];
+ bool innerHashKeyed_;
+ T mac_;
+
+ void KeyInnerHash();
+
+ HMAC(const HMAC&);
+ HMAC& operator= (const HMAC&);
+};
+
+
+// Setup
+template <class T>
+void HMAC<T>::Init()
+{
+ mac_.Init();
+ innerHashKeyed_ = false;
+}
+
+
+// Key generation
+template <class T>
+void HMAC<T>::SetKey(const byte* key, word32 length)
+{
+ Init();
+
+ if (length <= T::BLOCK_SIZE)
+ memcpy(ipad_, key, length);
+ else {
+ mac_.Update(key, length);
+ mac_.Final(ipad_);
+ length = T::DIGEST_SIZE;
+ }
+ memset(ipad_ + length, 0, T::BLOCK_SIZE - length);
+
+ for (word32 i = 0; i < T::BLOCK_SIZE; i++) {
+ opad_[i] = ipad_[i] ^ OPAD;
+ ipad_[i] ^= IPAD;
+ }
+}
+
+
+// Inner Key Hash
+template <class T>
+void HMAC<T>::KeyInnerHash()
+{
+ mac_.Update(ipad_, T::BLOCK_SIZE);
+ innerHashKeyed_ = true;
+}
+
+
+// Update
+template <class T>
+void HMAC<T>::Update(const byte* msg, word32 length)
+{
+ if (!innerHashKeyed_)
+ KeyInnerHash();
+ mac_.Update(msg, length);
+}
+
+
+// Final
+template <class T>
+void HMAC<T>::Final(byte* hash)
+{
+ if (!innerHashKeyed_)
+ KeyInnerHash();
+ mac_.Final(innerHash_);
+
+ mac_.Update(opad_, T::BLOCK_SIZE);
+ mac_.Update(innerHash_, T::DIGEST_SIZE);
+ mac_.Final(hash);
+
+ innerHashKeyed_ = false;
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_HMAC_HPP
diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp
new file mode 100644
index 00000000000..1706b4c0eea
--- /dev/null
+++ b/extra/yassl/taocrypt/include/integer.hpp
@@ -0,0 +1,320 @@
+/* integer.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's integer.h from CryptoPP */
+
+
+#ifndef TAO_CRYPT_INTEGER_HPP
+#define TAO_CRYPT_INTEGER_HPP
+
+#include "misc.hpp"
+#include "block.hpp"
+#include "random.hpp"
+#include "file.hpp"
+#include <cstring>
+#include "algorithm.hpp" // mySTL::swap
+
+
+#ifdef TAOCRYPT_X86ASM_AVAILABLE
+
+#ifdef _M_IX86
+ #if (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 500)) || \
+ (defined(__ICL) && (__ICL >= 500))
+ #define SSE2_INTRINSICS_AVAILABLE
+ #define TAOCRYPT_MM_MALLOC_AVAILABLE
+ #elif defined(_MSC_VER)
+ // _mm_free seems to be the only way to tell if the Processor Pack is
+ //installed or not
+ #include <malloc.h>
+ #if defined(_mm_free)
+ #define SSE2_INTRINSICS_AVAILABLE
+ #define TAOCRYPT_MM_MALLOC_AVAILABLE
+ #endif
+ #endif
+#endif
+
+// SSE2 intrinsics work in GCC 3.3 or later
+#if defined(__SSE2__) && (__GNUC_MAJOR__ > 3 || __GNUC_MINOR__ > 2)
+ #define SSE2_INTRINSICS_AVAILABLE
+#endif
+
+#endif // X86ASM
+
+
+
+
+namespace TaoCrypt {
+
+#if defined(SSE2_INTRINSICS_AVAILABLE)
+
+ // Allocator handling proper alignment
+ template <class T>
+ class AlignedAllocator : public AllocatorBase<T>
+ {
+ public:
+ typedef typename AllocatorBase<T>::pointer pointer;
+ typedef typename AllocatorBase<T>::size_type size_type;
+
+ pointer allocate(size_type n, const void* = 0);
+ void deallocate(void* p, size_type n);
+ pointer reallocate(T* p, size_type oldSize, size_type newSize,
+ bool preserve)
+ {
+ return StdReallocate(*this, p, oldSize, newSize, preserve);
+ }
+
+ #if !(defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16) || \
+ defined(TAOCRYPT_MEMALIGN_AVAILABLE) || \
+ defined(TAOCRYPT_MM_MALLOC_AVAILABLE))
+ #define TAOCRYPT_NO_ALIGNED_ALLOC
+ AlignedAllocator() : m_pBlock(0) {}
+ protected:
+ void *m_pBlock;
+ #endif
+ };
+
+ template class TAOCRYPT_DLL AlignedAllocator<word>;
+ typedef Block<word, AlignedAllocator<word> > AlignedWordBlock;
+#else
+ typedef WordBlock AlignedWordBlock;
+#endif
+
+
+// general MIN
+template<typename T> inline
+const T& min(const T& a, const T& b)
+{
+ return a < b ? a : b;
+}
+
+
+// general MAX
+template<typename T> inline
+const T& max(const T& a, const T& b)
+{
+ return a > b ? a : b;
+}
+
+
+// Large Integer class
+class Integer {
+public:
+ enum Sign {POSITIVE = 0, NEGATIVE = 1 };
+ enum Signedness { UNSIGNED, SIGNED };
+ enum RandomNumberType { ANY, PRIME };
+
+ class DivideByZero {};
+
+ Integer();
+ Integer(const Integer& t);
+ Integer(signed long value);
+ Integer(Sign s, word highWord, word lowWord);
+
+ explicit Integer(const char* str);
+ explicit Integer(const wchar_t* str);
+
+ // BER Decode Source
+ explicit Integer(Source&);
+
+ Integer(const byte* encodedInteger, unsigned int byteCount,
+ Signedness s = UNSIGNED);
+
+ ~Integer() {}
+
+ static const Integer &Zero();
+ static const Integer &One();
+ static const Integer &Two();
+
+ Integer& Ref() { return *this; }
+
+ Integer(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max);
+
+ static Integer Power2(unsigned int e);
+
+ unsigned int MinEncodedSize(Signedness = UNSIGNED) const;
+ unsigned int Encode(byte* output, unsigned int outputLen,
+ Signedness = UNSIGNED) const;
+
+ void Decode(const byte* input, unsigned int inputLen,
+ Signedness = UNSIGNED);
+ void Decode(Source&);
+
+ bool IsConvertableToLong() const;
+ signed long ConvertToLong() const;
+
+ unsigned int BitCount() const;
+ unsigned int ByteCount() const;
+ unsigned int WordCount() const;
+
+ bool GetBit(unsigned int i) const;
+ byte GetByte(unsigned int i) const;
+ unsigned long GetBits(unsigned int i, unsigned int n) const;
+
+ bool IsZero() const { return !*this; }
+ bool NotZero() const { return !IsZero(); }
+ bool IsNegative() const { return sign_ == NEGATIVE; }
+ bool NotNegative() const { return !IsNegative(); }
+ bool IsPositive() const { return NotNegative() && NotZero(); }
+ bool NotPositive() const { return !IsPositive(); }
+ bool IsEven() const { return GetBit(0) == 0; }
+ bool IsOdd() const { return GetBit(0) == 1; }
+
+ Integer& operator=(const Integer& t);
+ Integer& operator+=(const Integer& t);
+ Integer& operator-=(const Integer& t);
+ Integer& operator*=(const Integer& t) { return *this = Times(t); }
+ Integer& operator/=(const Integer& t)
+ { return *this = DividedBy(t);}
+ Integer& operator%=(const Integer& t) { return *this = Modulo(t); }
+ Integer& operator/=(word t) { return *this = DividedBy(t); }
+ Integer& operator%=(word t) { return *this = Modulo(t); }
+ Integer& operator<<=(unsigned int);
+ Integer& operator>>=(unsigned int);
+
+
+ void Randomize(RandomNumberGenerator &rng, unsigned int bitcount);
+ void Randomize(RandomNumberGenerator &rng, const Integer &min,
+ const Integer &max);
+
+ void SetBit(unsigned int n, bool value = 1);
+ void SetByte(unsigned int n, byte value);
+
+ void Negate();
+ void SetPositive() { sign_ = POSITIVE; }
+ void SetNegative() { if (!!(*this)) sign_ = NEGATIVE; }
+ void Swap(Integer& a);
+
+ bool operator!() const;
+ Integer operator+() const {return *this;}
+ Integer operator-() const;
+ Integer& operator++();
+ Integer& operator--();
+ Integer operator++(int)
+ { Integer temp = *this; ++*this; return temp; }
+ Integer operator--(int)
+ { Integer temp = *this; --*this; return temp; }
+
+ int Compare(const Integer& a) const;
+
+ Integer Plus(const Integer &b) const;
+ Integer Minus(const Integer &b) const;
+ Integer Times(const Integer &b) const;
+ Integer DividedBy(const Integer &b) const;
+ Integer Modulo(const Integer &b) const;
+ Integer DividedBy(word b) const;
+ word Modulo(word b) const;
+
+ Integer operator>>(unsigned int n) const { return Integer(*this)>>=n; }
+ Integer operator<<(unsigned int n) const { return Integer(*this)<<=n; }
+
+ Integer AbsoluteValue() const;
+ Integer Doubled() const { return Plus(*this); }
+ Integer Squared() const { return Times(*this); }
+ Integer SquareRoot() const;
+
+ bool IsSquare() const;
+ bool IsUnit() const;
+
+ Integer MultiplicativeInverse() const;
+
+ friend Integer a_times_b_mod_c(const Integer& x, const Integer& y,
+ const Integer& m);
+ friend Integer a_exp_b_mod_c(const Integer& x, const Integer& e,
+ const Integer& m);
+
+ static void Divide(Integer& r, Integer& q, const Integer& a,
+ const Integer& d);
+ static void Divide(word& r, Integer& q, const Integer& a, word d);
+ static void DivideByPowerOf2(Integer& r, Integer& q, const Integer& a,
+ unsigned int n);
+ static Integer Gcd(const Integer& a, const Integer& n);
+
+ Integer InverseMod(const Integer& n) const;
+ word InverseMod(word n) const;
+
+private:
+ friend class ModularArithmetic;
+ friend class MontgomeryRepresentation;
+ friend class HalfMontgomeryRepresentation;
+
+ Integer(word value, unsigned int length);
+
+ int PositiveCompare(const Integer& t) const;
+ friend void PositiveAdd(Integer& sum, const Integer& a, const Integer& b);
+ friend void PositiveSubtract(Integer& diff, const Integer& a,
+ const Integer& b);
+ friend void PositiveMultiply(Integer& product, const Integer& a,
+ const Integer& b);
+ friend void PositiveDivide(Integer& remainder, Integer& quotient, const
+ Integer& dividend, const Integer& divisor);
+ AlignedWordBlock reg_;
+ Sign sign_;
+};
+
+inline bool operator==(const Integer& a, const Integer& b)
+ {return a.Compare(b)==0;}
+inline bool operator!=(const Integer& a, const Integer& b)
+ {return a.Compare(b)!=0;}
+inline bool operator> (const Integer& a, const Integer& b)
+ {return a.Compare(b)> 0;}
+inline bool operator>=(const Integer& a, const Integer& b)
+ {return a.Compare(b)>=0;}
+inline bool operator< (const Integer& a, const Integer& b)
+ {return a.Compare(b)< 0;}
+inline bool operator<=(const Integer& a, const Integer& b)
+ {return a.Compare(b)<=0;}
+
+inline Integer operator+(const Integer &a, const Integer &b)
+ {return a.Plus(b);}
+inline Integer operator-(const Integer &a, const Integer &b)
+ {return a.Minus(b);}
+inline Integer operator*(const Integer &a, const Integer &b)
+ {return a.Times(b);}
+inline Integer operator/(const Integer &a, const Integer &b)
+ {return a.DividedBy(b);}
+inline Integer operator%(const Integer &a, const Integer &b)
+ {return a.Modulo(b);}
+inline Integer operator/(const Integer &a, word b) {return a.DividedBy(b);}
+inline word operator%(const Integer &a, word b) {return a.Modulo(b);}
+
+inline void swap(Integer &a, Integer &b)
+{
+ a.Swap(b);
+}
+
+
+Integer CRT(const Integer& xp, const Integer& p, const Integer& xq,
+ const Integer& q, const Integer& u);
+inline Integer ModularExponentiation(const Integer& a, const Integer& e,
+ const Integer& m)
+{
+ return a_exp_b_mod_c(a, e, m);
+}
+
+Integer ModularRoot(const Integer& a, const Integer& dp, const Integer& dq,
+ const Integer& p, const Integer& q, const Integer& u);
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_INTEGER_HPP
diff --git a/extra/yassl/taocrypt/include/md2.hpp b/extra/yassl/taocrypt/include/md2.hpp
new file mode 100644
index 00000000000..1e1c17e9cbe
--- /dev/null
+++ b/extra/yassl/taocrypt/include/md2.hpp
@@ -0,0 +1,67 @@
+/* md5.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* md2.hpp provides MD2 digest support, see RFC 1319
+*/
+
+#ifndef TAO_CRYPT_MD2_HPP
+#define TAO_CRYPT_MD2_HPP
+
+
+#include "hash.hpp"
+#include "block.hpp"
+
+
+namespace TaoCrypt {
+
+
+// MD2 digest
+class MD2 : public HASH {
+public:
+ enum { BLOCK_SIZE = 16, DIGEST_SIZE = 16, PAD_SIZE = 16, X_SIZE = 48 };
+ MD2();
+
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+
+ void Update(const byte*, word32);
+ void Final(byte*);
+
+ void Init();
+ void Swap(MD2&);
+private:
+ ByteBlock X_, C_, buffer_;
+ word32 count_; // bytes % PAD_SIZE
+
+ MD2(const MD2&);
+ MD2& operator=(const MD2&);
+};
+
+inline void swap(MD2& a, MD2& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MD2_HPP
+
diff --git a/extra/yassl/taocrypt/include/md5.hpp b/extra/yassl/taocrypt/include/md5.hpp
new file mode 100644
index 00000000000..0198daa466e
--- /dev/null
+++ b/extra/yassl/taocrypt/include/md5.hpp
@@ -0,0 +1,63 @@
+/* md5.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* md5.hpp provides MD5 digest support, see RFC 1321
+*/
+
+#ifndef TAO_CRYPT_MD5_HPP
+#define TAO_CRYPT_MD5_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// MD5 digest
+class MD5 : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 16, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes
+ MD5() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ MD5(const MD5&);
+ MD5& operator= (const MD5&);
+
+ void Init();
+ void Swap(MD5&);
+private:
+ void Transform();
+};
+
+inline void swap(MD5& a, MD5& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MD5_HPP
+
diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp
new file mode 100644
index 00000000000..01a3e8ee731
--- /dev/null
+++ b/extra/yassl/taocrypt/include/misc.hpp
@@ -0,0 +1,776 @@
+/* misc.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's misc.h from CryptoPP */
+
+#ifndef TAO_CRYPT_MISC_HPP
+#define TAO_CRYPT_MISC_HPP
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+namespace TaoCrypt {
+
+// library allocation
+struct new_t {}; // TaoCrypt New type
+extern new_t tc; // pass in parameter
+
+} // namespace TaoCrypt
+
+void* operator new (size_t, TaoCrypt::new_t);
+void* operator new[](size_t, TaoCrypt::new_t);
+
+
+namespace TaoCrypt {
+
+
+// define this if running on a big-endian CPU
+#if !defined(LITTLE_ENDIAN_ORDER) && (defined(__BIG_ENDIAN__) || \
+ defined(__sparc) || defined(__sparc__) || defined(__hppa__) || \
+ defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__)))
+ #define BIG_ENDIAN_ORDER
+#endif
+
+#ifndef BIG_ENDIAN_ORDER
+ #define LITTLE_ENDIAN_ORDER
+#endif
+
+
+typedef unsigned char byte;
+typedef unsigned short word16;
+typedef unsigned int word32;
+
+#if defined(__GNUC__) || defined(__MWERKS__)
+ #define WORD64_AVAILABLE
+ typedef unsigned long long word64;
+ #define W64LIT(x) x##LL
+#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+ #define WORD64_AVAILABLE
+ typedef unsigned __int64 word64;
+ #define W64LIT(x) x##ui64
+#elif defined(__DECCXX)
+ #define WORD64_AVAILABLE
+ typedef unsigned long word64;
+#endif
+
+// define largest word type
+#ifdef WORD64_AVAILABLE
+ typedef word64 lword;
+#else
+ typedef word32 lword;
+#endif
+
+#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \
+ defined(__x86_64__) || defined(__mips64)
+// These platforms have 64-bit CPU registers. Unfortunately most C++ compilers
+// don't allow any way to access the 64-bit by 64-bit multiply instruction
+// without using assembly, so in order to use word64 as word, the assembly
+// instruction must be defined in Dword::Multiply().
+ typedef word32 hword;
+ typedef word64 word;
+#else
+ #define TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ #ifdef WORD64_AVAILABLE
+ #define TAOCRYPT_SLOW_WORD64
+ // define this if your CPU is not64-bit to use alternative code
+ // that avoids word64
+ typedef word16 hword;
+ typedef word32 word;
+ typedef word64 dword;
+ #else
+ typedef word8 hword;
+ typedef word16 word;
+ typedef word32 dword;
+ #endif
+#endif
+
+const word32 WORD_SIZE = sizeof(word);
+const word32 WORD_BITS = WORD_SIZE * 8;
+
+
+#if defined(_MSC_VER) || defined(__BCPLUSPLUS__)
+ #define INTEL_INTRINSICS
+ #define FAST_ROTATE
+#elif defined(__MWERKS__) && TARGET_CPU_PPC
+ #define PPC_INTRINSICS
+ #define FAST_ROTATE
+#elif defined(__GNUC__) && defined(__i386__)
+ // GCC does peephole optimizations which should result in using rotate
+ // instructions
+ #define FAST_ROTATE
+#endif
+
+
+// no gas on these systems ?, disable for now
+#if defined(__sun__) || defined (__QNX__)
+ #define TAOCRYPT_DISABLE_X86ASM
+#endif
+
+
+
+// CodeWarrior defines _MSC_VER
+#if !defined(TAOCRYPT_DISABLE_X86ASM) && ((defined(_MSC_VER) && \
+ !defined(__MWERKS__) && defined(_M_IX86)) || \
+ (defined(__GNUC__) && defined(__i386__)))
+ #define TAOCRYPT_X86ASM_AVAILABLE
+#endif
+
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# define TAOCRYPT_MALLOC_ALIGNMENT_IS_16
+#endif
+
+#if defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
+# define TAOCRYPT_MEMALIGN_AVAILABLE
+#endif
+
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ #define TAOCRYPT_WIN32_AVAILABLE
+#endif
+
+#if defined(__unix__) || defined(__MACH__)
+ #define TAOCRYPT_UNIX_AVAILABLE
+#endif
+
+
+// VC60 workaround: it doesn't allow typename in some places
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ #define CPP_TYPENAME
+#else
+ #define CPP_TYPENAME typename
+#endif
+
+
+#ifdef _MSC_VER
+ #define TAOCRYPT_NO_VTABLE __declspec(novtable)
+#else
+ #define TAOCRYPT_NO_VTABLE
+#endif
+
+
+// ***************** DLL related ********************
+
+#ifdef TAOCRYPT_WIN32_AVAILABLE
+
+#ifdef TAOCRYPT_EXPORTS
+ #define TAOCRYPT_IS_DLL
+ #define TAOCRYPT_DLL __declspec(dllexport)
+#elif defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_IS_DLL
+ #define TAOCRYPT_DLL __declspec(dllimport)
+#else
+ #define TAOCRYPT_DLL
+#endif // EXPORTS
+
+#define TAOCRYPT_API __stdcall
+#define TAOCRYPT_CDECL __cdecl
+
+#else // TAOCRYPT_WIN32_AVAILABLE
+
+#define TAOCRYPT_DLL
+#define TAOCRYPT_API
+#define TAOCRYPT_CDECL
+
+#endif // TAOCRYPT_WIN32_AVAILABLE
+
+
+// ****************** tempalte stuff *******************
+
+
+#if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \
+ !defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS template class TAOCRYPT_DLL
+#elif defined(__MWERKS__)
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS extern class TAOCRYPT_DLL
+#else
+ #define TAOCRYPT_DLL_TEMPLATE_CLASS extern template class TAOCRYPT_DLL
+#endif
+
+
+#if defined(TAOCRYPT_MANUALLY_INSTANTIATE_TEMPLATES) && \
+ !defined(TAOCRYPT_EXPORTS)
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS template class
+#elif defined(__MWERKS__)
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern class
+#else
+ #define TAOCRYPT_STATIC_TEMPLATE_CLASS extern template class
+#endif
+
+
+// ************** compile-time assertion ***************
+
+template <bool b>
+struct CompileAssert
+{
+ static char dummy[2*b-1];
+};
+
+#define TAOCRYPT_COMPILE_ASSERT(assertion) \
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
+
+#if defined(TAOCRYPT_EXPORTS) || defined(TAOCRYPT_IMPORTS)
+ #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance)
+#else
+ #define TAOCRYPT_COMPILE_ASSERT_INSTANCE(assertion, instance) \
+ (void)sizeof(CompileAssert<(assertion)>)
+#endif
+
+#define TAOCRYPT_ASSERT_JOIN(X, Y) TAOCRYPT_DO_ASSERT_JOIN(X, Y)
+
+#define TAOCRYPT_DO_ASSERT_JOIN(X, Y) X##Y
+
+
+/*************** helpers *****************************/
+
+inline unsigned int BitsToBytes(unsigned int bitCount)
+{
+ return ((bitCount+7)/(8));
+}
+
+inline unsigned int BytesToWords(unsigned int byteCount)
+{
+ return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
+}
+
+inline unsigned int BitsToWords(unsigned int bitCount)
+{
+ return ((bitCount+WORD_BITS-1)/(WORD_BITS));
+}
+
+inline void CopyWords(word* r, const word* a, word32 n)
+{
+ for (word32 i = 0; i < n; i++)
+ r[i] = a[i];
+}
+
+inline unsigned int CountWords(const word* X, unsigned int N)
+{
+ while (N && X[N-1]==0)
+ N--;
+ return N;
+}
+
+inline void SetWords(word* r, word a, unsigned int n)
+{
+ for (unsigned int i=0; i<n; i++)
+ r[i] = a;
+}
+
+enum ByteOrder { LittleEndianOrder = 0, BigEndianOrder = 1 };
+enum CipherDir {ENCRYPTION, DECRYPTION};
+
+inline CipherDir ReverseDir(CipherDir dir)
+{
+ return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION;
+}
+
+template <typename ENUM_TYPE, int VALUE>
+struct EnumToType
+{
+ static ENUM_TYPE ToEnum() { return (ENUM_TYPE)VALUE; }
+};
+
+typedef EnumToType<ByteOrder, LittleEndianOrder> LittleEndian;
+typedef EnumToType<ByteOrder, BigEndianOrder> BigEndian;
+
+
+#ifndef BIG_ENDIAN_ORDER
+ typedef LittleEndian HostByteOrder;
+#else
+ typedef BigEndian HostByteOrder;
+#endif
+
+inline ByteOrder GetHostByteOrder()
+{
+ return HostByteOrder::ToEnum();
+}
+
+inline bool HostByteOrderIs(ByteOrder order)
+{
+ return order == GetHostByteOrder();
+}
+
+
+void xorbuf(byte*, const byte*, unsigned int);
+
+
+template <class T>
+inline bool IsPowerOf2(T n)
+{
+ return n > 0 && (n & (n-1)) == 0;
+}
+
+template <class T1, class T2>
+inline T2 ModPowerOf2(T1 a, T2 b)
+{
+ assert(IsPowerOf2(b));
+ return T2(a) & (b-1);
+}
+
+template <class T>
+inline T RoundDownToMultipleOf(T n, T m)
+{
+ return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m));
+}
+
+template <class T>
+inline T RoundUpToMultipleOf(T n, T m)
+{
+ return RoundDownToMultipleOf(n+m-1, m);
+}
+
+template <class T>
+inline unsigned int GetAlignment(T* dummy = 0) // VC60 workaround
+{
+#if (_MSC_VER >= 1300)
+ return __alignof(T);
+#elif defined(__GNUC__)
+ return __alignof__(T);
+#else
+ return sizeof(T);
+#endif
+}
+
+inline bool IsAlignedOn(const void* p, unsigned int alignment)
+{
+ return IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0
+ : (size_t)p % alignment == 0;
+}
+
+template <class T>
+inline bool IsAligned(const void* p, T* dummy = 0) // VC60 workaround
+{
+ return IsAlignedOn(p, GetAlignment<T>());
+}
+
+
+template <class T> inline T rotlFixed(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return (x<<y) | (x>>(sizeof(T)*8-y));
+}
+
+template <class T> inline T rotrFixed(T x, unsigned int y)
+{
+ assert(y < sizeof(T)*8);
+ return (x>>y) | (x<<(sizeof(T)*8-y));
+}
+
+#ifdef INTEL_INTRINSICS
+
+#pragma intrinsic(_lrotl, _lrotr)
+
+template<> inline word32 rotlFixed(word32 x, word32 y)
+{
+ assert(y < 32);
+ return y ? _lrotl(x, y) : x;
+}
+
+template<> inline word32 rotrFixed(word32 x, word32 y)
+{
+ assert(y < 32);
+ return y ? _lrotr(x, y) : x;
+}
+
+#endif // INTEL_INTRINSICS
+
+#ifdef min
+#undef min
+#endif
+
+inline word32 min(word32 a, word32 b)
+{
+ return a < b ? a : b;
+}
+
+
+inline word32 ByteReverse(word32 value)
+{
+#ifdef PPC_INTRINSICS
+ // PPC: load reverse indexed instruction
+ return (word32)__lwbrx(&value,0);
+#elif defined(FAST_ROTATE)
+ // 5 instructions with rotate instruction, 9 without
+ return (rotrFixed(value, 8U) & 0xff00ff00) |
+ (rotlFixed(value, 8U) & 0x00ff00ff);
+#else
+ // 6 instructions with rotate instruction, 8 without
+ value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+ return rotlFixed(value, 16U);
+#endif
+}
+
+
+template <typename T>
+inline void ByteReverse(T* out, const T* in, word32 byteCount)
+{
+ assert(byteCount % sizeof(T) == 0);
+ word32 count = byteCount/sizeof(T);
+ for (word32 i=0; i<count; i++)
+ out[i] = ByteReverse(in[i]);
+}
+
+inline void ByteReverse(byte* out, const byte* in, word32 byteCount)
+{
+ word32* o = reinterpret_cast<word32*>(out);
+ const word32* i = reinterpret_cast<const word32*>(in);
+ ByteReverse(o, i, byteCount);
+}
+
+
+template <class T>
+inline T ByteReverseIf(T value, ByteOrder order)
+{
+ return HostByteOrderIs(order) ? value : ByteReverse(value);
+}
+
+
+template <typename T>
+inline void ByteReverseIf(T* out, const T* in, word32 bc, ByteOrder order)
+{
+ if (!HostByteOrderIs(order))
+ ByteReverse(out, in, bc);
+ else if (out != in)
+ memcpy(out, in, bc);
+}
+
+
+template <class T>
+inline void GetUserKey(ByteOrder order, T* out, word32 outlen, const byte* in,
+ word32 inlen)
+{
+ const unsigned int U = sizeof(T);
+ assert(inlen <= outlen*U);
+ memcpy(out, in, inlen);
+ memset((byte *)out+inlen, 0, outlen*U-inlen);
+ ByteReverseIf(out, out, RoundUpToMultipleOf(inlen, U), order);
+}
+
+
+#ifdef _MSC_VER
+ // disable conversion warning
+ #pragma warning(disable:4244)
+#endif
+
+
+inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block,
+ byte*)
+{
+ return block[0];
+}
+
+inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block,
+ word16*)
+{
+ return (order == BigEndianOrder)
+ ? block[1] | (block[0] << 8)
+ : block[0] | (block[1] << 8);
+}
+
+inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte* block,
+ word32*)
+{
+ return (order == BigEndianOrder)
+ ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16)
+ | (word32(block[0]) << 24)
+ : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16)
+ | (word32(block[3]) << 24);
+}
+
+template <class T>
+inline T UnalignedGetWord(ByteOrder order, const byte *block, T* dummy = 0)
+{
+ return UnalignedGetWordNonTemplate(order, block, dummy);
+}
+
+inline void UnalignedPutWord(ByteOrder order, byte *block, byte value,
+ const byte *xorBlock = 0)
+{
+ block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
+}
+
+#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
+
+inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value,
+ const byte *xorBlock = 0)
+{
+ if (order == BigEndianOrder)
+ {
+ block[0] = GETBYTE(value, 1);
+ block[1] = GETBYTE(value, 0);
+ }
+ else
+ {
+ block[0] = GETBYTE(value, 0);
+ block[1] = GETBYTE(value, 1);
+ }
+
+ if (xorBlock)
+ {
+ block[0] ^= xorBlock[0];
+ block[1] ^= xorBlock[1];
+ }
+}
+
+inline void UnalignedPutWord(ByteOrder order, byte* block, word32 value,
+ const byte* xorBlock = 0)
+{
+ if (order == BigEndianOrder)
+ {
+ block[0] = GETBYTE(value, 3);
+ block[1] = GETBYTE(value, 2);
+ block[2] = GETBYTE(value, 1);
+ block[3] = GETBYTE(value, 0);
+ }
+ else
+ {
+ block[0] = GETBYTE(value, 0);
+ block[1] = GETBYTE(value, 1);
+ block[2] = GETBYTE(value, 2);
+ block[3] = GETBYTE(value, 3);
+ }
+
+ if (xorBlock)
+ {
+ block[0] ^= xorBlock[0];
+ block[1] ^= xorBlock[1];
+ block[2] ^= xorBlock[2];
+ block[3] ^= xorBlock[3];
+ }
+}
+
+
+template <class T>
+inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
+{
+ if (assumeAligned)
+ {
+ assert(IsAligned<T>(block));
+ return ByteReverseIf(*reinterpret_cast<const T *>(block), order);
+ }
+ else
+ return UnalignedGetWord<T>(order, block);
+}
+
+template <class T>
+inline void GetWord(bool assumeAligned, ByteOrder order, T &result,
+ const byte *block)
+{
+ result = GetWord<T>(assumeAligned, order, block);
+}
+
+template <class T>
+inline void PutWord(bool assumeAligned, ByteOrder order, byte* block, T value,
+ const byte *xorBlock = 0)
+{
+ if (assumeAligned)
+ {
+ assert(IsAligned<T>(block));
+ if (xorBlock)
+ *reinterpret_cast<T *>(block) = ByteReverseIf(value, order)
+ ^ *reinterpret_cast<const T *>(xorBlock);
+ else
+ *reinterpret_cast<T *>(block) = ByteReverseIf(value, order);
+ }
+ else
+ UnalignedPutWord(order, block, value, xorBlock);
+}
+
+template <class T, class B, bool A=true>
+class GetBlock
+{
+public:
+ GetBlock(const void *block)
+ : m_block((const byte *)block) {}
+
+ template <class U>
+ inline GetBlock<T, B, A> & operator()(U &x)
+ {
+ TAOCRYPT_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
+ x = GetWord<T>(A, B::ToEnum(), m_block);
+ m_block += sizeof(T);
+ return *this;
+ }
+
+private:
+ const byte *m_block;
+};
+
+template <class T, class B, bool A = true>
+class PutBlock
+{
+public:
+ PutBlock(const void *xorBlock, void *block)
+ : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
+
+ template <class U>
+ inline PutBlock<T, B, A> & operator()(U x)
+ {
+ PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
+ m_block += sizeof(T);
+ if (m_xorBlock)
+ m_xorBlock += sizeof(T);
+ return *this;
+ }
+
+private:
+ const byte *m_xorBlock;
+ byte *m_block;
+};
+
+template <class T, class B, bool A=true>
+struct BlockGetAndPut
+{
+ // function needed because of C++ grammatical ambiguity between
+ // expression-statements and declarations
+ static inline GetBlock<T, B, A> Get(const void *block)
+ {return GetBlock<T, B, A>(block);}
+ typedef PutBlock<T, B, A> Put;
+};
+
+
+
+template <bool overflow> struct SafeShifter;
+
+template<> struct SafeShifter<true>
+{
+ template <class T>
+ static inline T RightShift(T value, unsigned int bits)
+ {
+ return 0;
+ }
+
+ template <class T>
+ static inline T LeftShift(T value, unsigned int bits)
+ {
+ return 0;
+ }
+};
+
+template<> struct SafeShifter<false>
+{
+ template <class T>
+ static inline T RightShift(T value, unsigned int bits)
+ {
+ return value >> bits;
+ }
+
+ template <class T>
+ static inline T LeftShift(T value, unsigned int bits)
+ {
+ return value << bits;
+ }
+};
+
+template <unsigned int bits, class T>
+inline T SafeRightShift(T value)
+{
+ return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
+}
+
+template <unsigned int bits, class T>
+inline T SafeLeftShift(T value)
+{
+ return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
+}
+
+
+inline
+word ShiftWordsLeftByBits(word* r, unsigned int n, unsigned int shiftBits)
+{
+ assert (shiftBits<WORD_BITS);
+ word u, carry=0;
+ if (shiftBits)
+ for (unsigned int i=0; i<n; i++)
+ {
+ u = r[i];
+ r[i] = (u << shiftBits) | carry;
+ carry = u >> (WORD_BITS-shiftBits);
+ }
+ return carry;
+}
+
+
+inline
+word ShiftWordsRightByBits(word* r, unsigned int n, unsigned int shiftBits)
+{
+ assert (shiftBits<WORD_BITS);
+ word u, carry=0;
+ if (shiftBits)
+ for (int i=n-1; i>=0; i--)
+ {
+ u = r[i];
+ r[i] = (u >> shiftBits) | carry;
+ carry = u << (WORD_BITS-shiftBits);
+ }
+ return carry;
+}
+
+
+inline
+void ShiftWordsLeftByWords(word* r, unsigned int n, unsigned int shiftWords)
+{
+ shiftWords = min(shiftWords, n);
+ if (shiftWords)
+ {
+ for (unsigned int i=n-1; i>=shiftWords; i--)
+ r[i] = r[i-shiftWords];
+ SetWords(r, 0, shiftWords);
+ }
+}
+
+
+inline
+void ShiftWordsRightByWords(word* r, unsigned int n, unsigned int shiftWords)
+{
+ shiftWords = min(shiftWords, n);
+ if (shiftWords)
+ {
+ for (unsigned int i=0; i+shiftWords<n; i++)
+ r[i] = r[i+shiftWords];
+ SetWords(r+n-shiftWords, 0, shiftWords);
+ }
+}
+
+
+template <class T1, class T2>
+inline T1 SaturatingSubtract(T1 a, T2 b)
+{
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0); // T1 is unsigned type
+ TAOCRYPT_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1); // T2 is unsigned type
+ return T1((a > b) ? (a - b) : 0);
+}
+
+
+// declares
+unsigned int BytePrecision(unsigned long value);
+unsigned int BitPrecision(unsigned long);
+unsigned long Crop(unsigned long value, unsigned int size);
+
+void CallNewHandler();
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MISC_HPP
diff --git a/extra/yassl/taocrypt/include/modarith.hpp b/extra/yassl/taocrypt/include/modarith.hpp
new file mode 100644
index 00000000000..88a2cc95c7c
--- /dev/null
+++ b/extra/yassl/taocrypt/include/modarith.hpp
@@ -0,0 +1,169 @@
+/* modarith.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* based on Wei Dai's modarith.h from CryptoPP */
+
+
+#ifndef TAO_CRYPT_MODARITH_HPP
+#define TAO_CRYPT_MODARITH_HPP
+
+#include "misc.hpp"
+#include "integer.hpp"
+#include "algebra.hpp"
+
+namespace TaoCrypt {
+
+
+//! ModularArithmetic
+class ModularArithmetic : public AbstractRing<Integer>
+{
+public:
+
+ typedef int RandomizationParameter;
+ typedef Integer Element;
+
+ ModularArithmetic(const Integer &modulus = Integer::One())
+ : modulus(modulus), result((word)0, modulus.reg_.size()) {}
+
+ ModularArithmetic(const ModularArithmetic &ma)
+ : AbstractRing<Integer>(),
+ modulus(ma.modulus), result((word)0, modulus.reg_.size()) {}
+
+ const Integer& GetModulus() const {return modulus;}
+ void SetModulus(const Integer &newModulus)
+ {
+ modulus = newModulus;
+ result.reg_.resize(modulus.reg_.size());
+ }
+
+ virtual bool IsMontgomeryRepresentation() const {return false;}
+
+ virtual Integer ConvertIn(const Integer &a) const
+ {return a%modulus;}
+
+ virtual Integer ConvertOut(const Integer &a) const
+ {return a;}
+
+ const Integer& Half(const Integer &a) const;
+
+ bool Equal(const Integer &a, const Integer &b) const
+ {return a==b;}
+
+ const Integer& Identity() const
+ {return Integer::Zero();}
+
+ const Integer& Add(const Integer &a, const Integer &b) const;
+
+ Integer& Accumulate(Integer &a, const Integer &b) const;
+
+ const Integer& Inverse(const Integer &a) const;
+
+ const Integer& Subtract(const Integer &a, const Integer &b) const;
+
+ Integer& Reduce(Integer &a, const Integer &b) const;
+
+ const Integer& Double(const Integer &a) const
+ {return Add(a, a);}
+
+ const Integer& MultiplicativeIdentity() const
+ {return Integer::One();}
+
+ const Integer& Multiply(const Integer &a, const Integer &b) const
+ {return result1 = a*b%modulus;}
+
+ const Integer& Square(const Integer &a) const
+ {return result1 = a.Squared()%modulus;}
+
+ bool IsUnit(const Integer &a) const
+ {return Integer::Gcd(a, modulus).IsUnit();}
+
+ const Integer& MultiplicativeInverse(const Integer &a) const
+ {return result1 = a.InverseMod(modulus);}
+
+ const Integer& Divide(const Integer &a, const Integer &b) const
+ {return Multiply(a, MultiplicativeInverse(b));}
+
+ Integer CascadeExponentiate(const Integer &x, const Integer &e1,
+ const Integer &y, const Integer &e2) const;
+
+ void SimultaneousExponentiate(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const;
+
+ unsigned int MaxElementBitLength() const
+ {return (modulus-1).BitCount();}
+
+ unsigned int MaxElementByteLength() const
+ {return (modulus-1).ByteCount();}
+
+
+ static const RandomizationParameter DefaultRandomizationParameter;
+
+protected:
+ Integer modulus;
+ mutable Integer result, result1;
+
+};
+
+
+
+//! do modular arithmetics in Montgomery representation for increased speed
+class MontgomeryRepresentation : public ModularArithmetic
+{
+public:
+ MontgomeryRepresentation(const Integer &modulus); // modulus must be odd
+
+ bool IsMontgomeryRepresentation() const {return true;}
+
+ Integer ConvertIn(const Integer &a) const
+ {return (a<<(WORD_BITS*modulus.reg_.size()))%modulus;}
+
+ Integer ConvertOut(const Integer &a) const;
+
+ const Integer& MultiplicativeIdentity() const
+ {return result1 = Integer::Power2(WORD_BITS*modulus.reg_.size())%modulus;}
+
+ const Integer& Multiply(const Integer &a, const Integer &b) const;
+
+ const Integer& Square(const Integer &a) const;
+
+ const Integer& MultiplicativeInverse(const Integer &a) const;
+
+ Integer CascadeExponentiate(const Integer &x, const Integer &e1,
+ const Integer &y, const Integer &e2) const
+ {return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);}
+
+ void SimultaneousExponentiate(Element *results, const Element &base,
+ const Integer *exponents, unsigned int exponentsCount) const
+ {AbstractRing<Integer>::SimultaneousExponentiate(results, base,
+ exponents, exponentsCount);}
+
+private:
+ Integer u;
+ mutable AlignedWordBlock workspace;
+};
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MODARITH_HPP
diff --git a/extra/yassl/taocrypt/include/modes.hpp b/extra/yassl/taocrypt/include/modes.hpp
new file mode 100644
index 00000000000..2a21ad46b76
--- /dev/null
+++ b/extra/yassl/taocrypt/include/modes.hpp
@@ -0,0 +1,133 @@
+/* modes.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* modes.hpp provides ECB and CBC modes for block cipher encryption/decryption
+*/
+
+
+#ifndef TAO_CRYPT_MODES_HPP
+#define TAO_CRYPT_MODES_HPP
+
+#include <string.h>
+#include "misc.hpp"
+
+namespace TaoCrypt {
+
+
+enum Mode { ECB, CBC };
+
+
+// BlockCipher abstraction
+template<CipherDir DIR, class T, Mode MODE>
+class BlockCipher {
+public:
+ BlockCipher() : cipher_(DIR, MODE) {}
+
+ void Process(byte* c, const byte* p, word32 sz)
+ { cipher_.Process(c, p, sz); }
+ void SetKey(const byte* k, word32 sz)
+ { cipher_.SetKey(k, sz, DIR); }
+ void SetKey(const byte* k, word32 sz, const byte* iv)
+ { cipher_.SetKey(k, sz, DIR); cipher_.SetIV(iv); }
+private:
+ T cipher_;
+
+ BlockCipher(const BlockCipher&); // hide copy
+ BlockCipher& operator=(const BlockCipher&); // and assign
+};
+
+
+// Mode Base for block ciphers, static size
+template<int BLOCK_SIZE>
+class Mode_BASE {
+public:
+ Mode_BASE() {}
+ virtual ~Mode_BASE() {}
+
+ virtual void ProcessAndXorBlock(const byte*, const byte*, byte*) const = 0;
+
+ void ECB_Process(byte*, const byte*, word32);
+ void CBC_Encrypt(byte*, const byte*, word32);
+ void CBC_Decrypt(byte*, const byte*, word32);
+
+ void SetIV(const byte* iv) { memcpy(reg_, iv, BLOCK_SIZE); }
+private:
+ byte reg_[BLOCK_SIZE];
+ byte tmp_[BLOCK_SIZE];
+
+ Mode_BASE(const Mode_BASE&); // hide copy
+ Mode_BASE& operator=(const Mode_BASE&); // and assign
+};
+
+
+// ECB Process blocks
+template<int BLOCK_SIZE>
+void Mode_BASE<BLOCK_SIZE>::ECB_Process(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+
+ while (blocks--) {
+ ProcessAndXorBlock(in, 0, out);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+
+// CBC Encrypt
+template<int BLOCK_SIZE>
+void Mode_BASE<BLOCK_SIZE>::CBC_Encrypt(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+
+ while (blocks--) {
+ xorbuf(reg_, in, BLOCK_SIZE);
+ ProcessAndXorBlock(reg_, 0, reg_);
+ memcpy(out, reg_, BLOCK_SIZE);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+
+// CBC Decrypt
+template<int BLOCK_SIZE>
+void Mode_BASE<BLOCK_SIZE>::CBC_Decrypt(byte* out, const byte* in, word32 sz)
+{
+ word32 blocks = sz / BLOCK_SIZE;
+ byte hold[BLOCK_SIZE];
+
+ while (blocks--) {
+ memcpy(tmp_, in, BLOCK_SIZE);
+ ProcessAndXorBlock(tmp_, 0, out);
+ xorbuf(out, reg_, BLOCK_SIZE);
+ memcpy(hold, reg_, BLOCK_SIZE); // swap reg_ and tmp_
+ memcpy(reg_, tmp_, BLOCK_SIZE);
+ memcpy(tmp_, hold, BLOCK_SIZE);
+ out += BLOCK_SIZE;
+ in += BLOCK_SIZE;
+ }
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_MODES_HPP
diff --git a/extra/yassl/taocrypt/include/random.hpp b/extra/yassl/taocrypt/include/random.hpp
new file mode 100644
index 00000000000..5fdda8da47a
--- /dev/null
+++ b/extra/yassl/taocrypt/include/random.hpp
@@ -0,0 +1,87 @@
+/* random.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* random.hpp provides a crypto secure Random Number Generator using an OS
+ specific seed
+*/
+
+
+#ifndef TAO_CRYPT_RANDOM_HPP
+#define TAO_CRYPT_RANDOM_HPP
+
+#include "arc4.hpp"
+#include "error.hpp"
+
+namespace TaoCrypt {
+
+
+// OS specific seeder
+class OS_Seed {
+public:
+ OS_Seed();
+ ~OS_Seed();
+
+ void GenerateSeed(byte*, word32 sz);
+ Error GetError() const { return error_; }
+private:
+#if defined(WIN32)
+ #if defined(_WIN64)
+ typedef unsigned __int64 ProviderHandle;
+ // type HCRYPTPROV, avoid #include <windows.h>
+ #else
+ typedef unsigned long ProviderHandle;
+ #endif
+ ProviderHandle handle_;
+#else
+ int fd_;
+#endif
+ Error error_;
+
+ OS_Seed(const OS_Seed&); // hide copy
+ OS_Seed& operator=(const OS_Seed&); // hide assign
+};
+
+
+// secure Random Nnumber Generator
+class RandomNumberGenerator {
+public:
+ RandomNumberGenerator();
+ ~RandomNumberGenerator() {}
+
+ void GenerateBlock(byte*, word32 sz);
+ byte GenerateByte();
+
+ ErrorNumber GetError() const { return seed_.GetError().What(); }
+private:
+ OS_Seed seed_;
+ ARC4 cipher_;
+
+ RandomNumberGenerator(const RandomNumberGenerator&); // hide copy
+ RandomNumberGenerator operator=(const RandomNumberGenerator&); // && assign
+};
+
+
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RANDOM_HPP
+
diff --git a/extra/yassl/taocrypt/include/ripemd.hpp b/extra/yassl/taocrypt/include/ripemd.hpp
new file mode 100644
index 00000000000..4f8e1fd0386
--- /dev/null
+++ b/extra/yassl/taocrypt/include/ripemd.hpp
@@ -0,0 +1,63 @@
+/* ripemd.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* ripemd.hpp provides RIPEMD digest support
+*/
+
+#ifndef TAO_CRYPT_RIPEMD_HPP
+#define TAO_CRYPT_RIPEMD_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// RIPEMD160 digest
+class RIPEMD160 : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 20, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes
+ RIPEMD160() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ RIPEMD160(const RIPEMD160&);
+ RIPEMD160& operator= (const RIPEMD160&);
+
+ void Init();
+ void Swap(RIPEMD160&);
+private:
+ void Transform();
+};
+
+inline void swap(RIPEMD160& a, RIPEMD160& b)
+{
+ a.Swap(b);
+}
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RIPEMD_HPP
+
diff --git a/extra/yassl/taocrypt/include/rsa.hpp b/extra/yassl/taocrypt/include/rsa.hpp
new file mode 100644
index 00000000000..916476c90b7
--- /dev/null
+++ b/extra/yassl/taocrypt/include/rsa.hpp
@@ -0,0 +1,253 @@
+/* rsa.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* rsa.hpp provides RSA ES encrypt/decrypt, SSL (block type 1) sign and verify
+*/
+
+#ifndef TAO_CRYPT_RSA_HPP
+#define TAO_CRYPT_RSA_HPP
+
+#include "integer.hpp"
+#include "random.hpp"
+#include "stdexcept.hpp"
+
+
+namespace TaoCrypt {
+
+class Source;
+
+
+// Public Key Length helper
+class PK_Lengths {
+ const Integer& image_;
+public:
+ explicit PK_Lengths(const Integer& i) : image_(i) {}
+
+ word32 PaddedBlockBitLength() const {return image_.BitCount() - 1;}
+ word32 PaddedBlockByteLength() const
+ {return BitsToBytes(PaddedBlockBitLength());}
+
+ word32 FixedCiphertextLength() const {return image_.ByteCount();}
+ word32 FixedMaxPlaintextLength() const
+ {return SaturatingSubtract(PaddedBlockBitLength() / 8, 10U); }
+};
+
+
+// RSA Public Key
+class RSA_PublicKey {
+protected:
+ Integer n_;
+ Integer e_;
+public:
+ RSA_PublicKey() {}
+ explicit RSA_PublicKey(Source&);
+
+ void Initialize(const Integer& n, const Integer& e) {n_ = n; e_ = e;}
+ void Initialize(Source&);
+
+ Integer ApplyFunction(const Integer& x) const;
+
+ const Integer& GetModulus() const {return n_;}
+ const Integer& GetPublicExponent() const {return e_;}
+
+ void SetModulus(const Integer& n) {n_ = n;}
+ void SetPublicExponent(const Integer& e) {e_ = e;}
+
+ word32 FixedCiphertextLength()
+ {
+ return PK_Lengths(n_).FixedCiphertextLength();
+ }
+
+ RSA_PublicKey(const RSA_PublicKey& other) : n_(other.n_), e_(other.e_) {}
+ RSA_PublicKey& operator=(const RSA_PublicKey& that)
+ {
+ RSA_PublicKey tmp(that);
+ Swap(tmp);
+ return *this;
+ }
+
+ void Swap(RSA_PublicKey& other)
+ {
+ n_.Swap(other.n_);
+ e_.Swap(other.e_);
+ }
+};
+
+
+// RSA Private Key
+class RSA_PrivateKey : public RSA_PublicKey {
+ Integer d_;
+ Integer p_;
+ Integer q_;
+ Integer dp_;
+ Integer dq_;
+ Integer u_;
+public:
+ RSA_PrivateKey() {}
+ explicit RSA_PrivateKey(Source&);
+
+ void Initialize(const Integer& n, const Integer& e, const Integer& d,
+ const Integer& p, const Integer& q, const Integer& dp,
+ const Integer& dq, const Integer& u)
+ {n_ = n; e_ = e; d_ = d; p_ = p; q_ = q; dp_ = dp; dq_ = dq; u_ = u;}
+ void Initialize(Source&);
+
+ Integer CalculateInverse(RandomNumberGenerator&, const Integer&) const;
+
+ const Integer& GetPrime1() const {return p_;}
+ const Integer& GetPrime2() const {return q_;}
+ const Integer& GetPrivateExponent() const {return d_;}
+ const Integer& GetModPrime1PrivateExponent() const {return dp_;}
+ const Integer& GetModPrime2PrivateExponent() const {return dq_;}
+ const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const
+ {return u_;}
+
+ void SetPrime1(const Integer& p) {p_ = p;}
+ void SetPrime2(const Integer& q) {q_ = q;}
+ void SetPrivateExponent(const Integer& d) {d_ = d;}
+ void SetModPrime1PrivateExponent(const Integer& dp) {dp_ = dp;}
+ void SetModPrime2PrivateExponent(const Integer& dq) {dq_ = dq;}
+ void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer& u) {u_ = u;}
+private:
+ RSA_PrivateKey(const RSA_PrivateKey&); // hide copy
+ RSA_PrivateKey& operator=(const RSA_PrivateKey&); // and assign
+};
+
+
+// block type 2 padding
+class RSA_BlockType2 {
+public:
+ void Pad(const byte*, word32, byte*, word32,
+ RandomNumberGenerator&) const;
+ word32 UnPad(const byte*, word32, byte*) const;
+};
+
+
+// block type 1 padding
+class RSA_BlockType1 {
+public:
+ void Pad(const byte*, word32, byte*, word32,
+ RandomNumberGenerator&) const;
+ word32 UnPad(const byte*, word32, byte*) const;
+};
+
+
+// RSA Encryptor, can use any padding
+template<class Pad = RSA_BlockType2>
+class RSA_Encryptor {
+ const RSA_PublicKey& key_;
+ Pad padding_;
+public:
+ explicit RSA_Encryptor(const RSA_PublicKey& k) : key_(k) {}
+
+ void Encrypt(const byte*, word32, byte*, RandomNumberGenerator&);
+ bool SSL_Verify(const byte* msg, word32 sz, const byte* sig);
+};
+
+
+// RSA Decryptor, can use any padding
+template<class Pad = RSA_BlockType2>
+class RSA_Decryptor {
+ const RSA_PrivateKey& key_;
+ Pad padding_;
+public:
+ explicit RSA_Decryptor(const RSA_PrivateKey& k) : key_(k) {}
+
+ word32 Decrypt(const byte*, word32, byte*, RandomNumberGenerator&);
+ void SSL_Sign(const byte*, word32, byte*, RandomNumberGenerator&);
+};
+
+
+// Public Encrypt
+template<class Pad>
+void RSA_Encryptor<Pad>::Encrypt(const byte* plain, word32 sz, byte* cipher,
+ RandomNumberGenerator& rng)
+{
+ PK_Lengths lengths(key_.GetModulus());
+ assert(sz <= lengths.FixedMaxPlaintextLength());
+
+ ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
+ padding_.Pad(plain, sz, paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), rng);
+
+ key_.ApplyFunction(Integer(paddedBlock.get_buffer(), paddedBlock.size())).
+ Encode(cipher, lengths.FixedCiphertextLength());
+}
+
+
+// Private Decrypt
+template<class Pad>
+word32 RSA_Decryptor<Pad>::Decrypt(const byte* cipher, word32 sz, byte* plain,
+ RandomNumberGenerator& rng)
+{
+ PK_Lengths lengths(key_.GetModulus());
+ assert(sz == lengths.FixedCiphertextLength());
+
+ if (sz != lengths.FixedCiphertextLength())
+ return 0;
+
+ ByteBlock paddedBlock(lengths.PaddedBlockByteLength());
+ Integer x = key_.CalculateInverse(rng, Integer(cipher,
+ lengths.FixedCiphertextLength()).Ref());
+ if (x.ByteCount() > paddedBlock.size())
+ x = Integer::Zero(); // don't return false, prevents timing attack
+ x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
+ return padding_.UnPad(paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), plain);
+}
+
+
+// Private SSL type (block 1) Encrypt
+template<class Pad>
+void RSA_Decryptor<Pad>::SSL_Sign(const byte* message, word32 sz, byte* sig,
+ RandomNumberGenerator& rng)
+{
+ RSA_PublicKey inverse;
+ inverse.Initialize(key_.GetModulus(), key_.GetPrivateExponent());
+ RSA_Encryptor<RSA_BlockType1> enc(inverse); // SSL Type
+ enc.Encrypt(message, sz, sig, rng);
+}
+
+
+word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain);
+
+
+// Public SSL type (block 1) Decrypt
+template<class Pad>
+bool RSA_Encryptor<Pad>::SSL_Verify(const byte* message, word32 sz,
+ const byte* sig)
+{
+ ByteBlock plain(PK_Lengths(key_.GetModulus()).FixedMaxPlaintextLength());
+ SSL_Decrypt(key_, sig, plain.get_buffer());
+
+ if ( (memcmp(plain.get_buffer(), message, sz)) == 0)
+ return true;
+ return false;
+}
+
+
+typedef RSA_Encryptor<> RSAES_Encryptor;
+typedef RSA_Decryptor<> RSAES_Decryptor;
+
+
+} // namespace
+
+#endif // TAO_CRYPT_RSA_HPP
diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp
new file mode 100644
index 00000000000..7159611e97b
--- /dev/null
+++ b/extra/yassl/taocrypt/include/runtime.hpp
@@ -0,0 +1,91 @@
+/* runtime.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* runtime.hpp provides C++ runtime support functions when building a pure C
+ * version of yaSSL, user must define YASSL_PURE_C
+*/
+
+
+
+#if !defined(yaSSL_NEW_HPP) && defined(DEFINE_CXA_PURE_VIRTUAL)
+
+#define yaSSL_NEW_HPP
+
+
+#include <cstdlib>
+
+
+static void* operator new (size_t sz)
+{
+ return malloc (sz ? sz : 1);
+}
+
+static void* operator new[](size_t sz)
+{
+ return malloc (sz ? sz : 1);
+}
+
+static void operator delete (void* ptr)
+{
+ if (ptr) free(ptr);
+}
+
+static void operator delete[] (void* ptr)
+{
+ if (ptr) free(ptr);
+}
+
+
+#ifdef __GNUC__
+
+extern "C" {
+
+static int __cxa_pure_virtual()
+{
+ // oops, pure virtual called!
+ return 0;
+}
+
+// simple guards for now that aren't perfect
+// does yaSSL need full locking for two Integer statics,
+// the Factory, and Session list?
+// could leak ~ 8 bytes if two threads try to initialize at same time
+// gcc didn't implement until 3.4
+
+
+typedef long long __guard;
+
+
+static int __cxa_guard_acquire(__guard* g)
+{
+ return !*(char*)g;
+}
+
+static void __cxa_guard_release(__guard* g)
+{
+ *(char*)g = 1;
+}
+
+
+} // extern "C"
+#endif // __GNUC__
+
+#endif // yaSSL_NEW_HPP
diff --git a/extra/yassl/taocrypt/include/sha.hpp b/extra/yassl/taocrypt/include/sha.hpp
new file mode 100644
index 00000000000..b75d9e3f670
--- /dev/null
+++ b/extra/yassl/taocrypt/include/sha.hpp
@@ -0,0 +1,65 @@
+/* sha.hpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* sha.hpp provides SHA-1 digests, see RFC 3174
+*/
+
+#ifndef TAO_CRYPT_SHA_HPP
+#define TAO_CRYPT_SHA_HPP
+
+#include "hash.hpp"
+
+namespace TaoCrypt {
+
+
+// SHA-1 digest
+class SHA : public HASHwithTransform {
+public:
+ enum { BLOCK_SIZE = 64, DIGEST_SIZE = 20, PAD_SIZE = 56,
+ TAO_BYTE_ORDER = BigEndianOrder}; // in Bytes
+ SHA() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+ { Init(); }
+ ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
+ word32 getBlockSize() const { return BLOCK_SIZE; }
+ word32 getDigestSize() const { return DIGEST_SIZE; }
+ word32 getPadSize() const { return PAD_SIZE; }
+
+ void Init();
+
+ SHA(const SHA&);
+ SHA& operator= (const SHA&);
+
+ void Swap(SHA&);
+private:
+ void Transform();
+};
+
+
+inline void swap(SHA& a, SHA& b)
+{
+ a.Swap(b);
+}
+
+} // namespace
+
+
+#endif // TAO_CRYPT_SHA_HPP
+
diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am
new file mode 100644
index 00000000000..5a32850a3d4
--- /dev/null
+++ b/extra/yassl/taocrypt/src/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES = -I../include -I../../mySTL
+
+noinst_LIBRARIES = libtaocrypt.a
+libtaocrypt_a_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \
+ coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp integer.cpp \
+ md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp
+EXTRA_DIST = ../include/*.hpp
+CXXFLAGS=`echo "@CXXFLAGS@" | sed 's/-fno-implicit-templates//'`
diff --git a/extra/yassl/taocrypt/src/aes.cpp b/extra/yassl/taocrypt/src/aes.cpp
new file mode 100644
index 00000000000..d09a40e1578
--- /dev/null
+++ b/extra/yassl/taocrypt/src/aes.cpp
@@ -0,0 +1,401 @@
+/* aes.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's aes.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "aes.hpp"
+#include "stdexcept.hpp"
+
+
+namespace TaoCrypt {
+
+
+void AES::Process(byte* out, const byte* in, word32 sz)
+{
+ if (mode_ == ECB)
+ ECB_Process(out, in, sz);
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ CBC_Encrypt(out, in, sz);
+ else
+ CBC_Decrypt(out, in, sz);
+}
+
+
+
+void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/)
+{
+ assert( (keylen == 16) || (keylen == 24) || (keylen == 32) );
+
+ rounds_ = keylen/4 + 6;
+ key_.New(4*(rounds_+1));
+
+ word32 temp, *rk = key_.get_buffer();
+ unsigned int i=0;
+
+ GetUserKey(BigEndianOrder, rk, keylen/4, userKey, keylen);
+
+ switch(keylen)
+ {
+ case 16:
+ while (true)
+ {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10)
+ break;
+ rk += 4;
+ }
+ break;
+
+ case 24:
+ while (true) // for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack
+ {
+ temp = rk[ 5];
+ rk[ 6] = rk[ 0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8)
+ break;
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ break;
+
+ case 32:
+ while (true)
+ {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
+ (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
+ rcon_[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7)
+ break;
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
+ (Te4[GETBYTE(temp, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(temp, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(temp, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(temp, 0)] & 0x000000ff);
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+
+ rk += 8;
+ }
+ break;
+ }
+
+ if (dir_ == DECRYPTION)
+ {
+ unsigned int i, j;
+ rk = key_.get_buffer();
+
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4*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 < rounds_; i++) {
+ rk += 4;
+ rk[0] =
+ Td0[Te4[GETBYTE(rk[0], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[0], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[0], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[0], 0)] & 0xff];
+ rk[1] =
+ Td0[Te4[GETBYTE(rk[1], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[1], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[1], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[1], 0)] & 0xff];
+ rk[2] =
+ Td0[Te4[GETBYTE(rk[2], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[2], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[2], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[2], 0)] & 0xff];
+ rk[3] =
+ Td0[Te4[GETBYTE(rk[3], 3)] & 0xff] ^
+ Td1[Te4[GETBYTE(rk[3], 2)] & 0xff] ^
+ Td2[Te4[GETBYTE(rk[3], 1)] & 0xff] ^
+ Td3[Te4[GETBYTE(rk[3], 0)] & 0xff];
+ }
+ }
+}
+
+
+typedef BlockGetAndPut<word32, BigEndian> gpBlock;
+
+void AES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
+{
+ if (dir_ == ENCRYPTION)
+ encrypt(in, xOr, out);
+ else
+ decrypt(in, xOr, out);
+}
+
+
+void AES::encrypt(const byte* inBlock, const byte* xorBlock,
+ byte* outBlock) const
+{
+ word32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const word32 *rk = key_.get_buffer();
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ gpBlock::Get(inBlock)(s0)(s1)(s2)(s3);
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+ /*
+ * Nr - 1 full rounds:
+ */
+ unsigned int r = rounds_ >> 1;
+ for (;;) {
+ t0 =
+ Te0[GETBYTE(s0, 3)] ^
+ Te1[GETBYTE(s1, 2)] ^
+ Te2[GETBYTE(s2, 1)] ^
+ Te3[GETBYTE(s3, 0)] ^
+ rk[4];
+ t1 =
+ Te0[GETBYTE(s1, 3)] ^
+ Te1[GETBYTE(s2, 2)] ^
+ Te2[GETBYTE(s3, 1)] ^
+ Te3[GETBYTE(s0, 0)] ^
+ rk[5];
+ t2 =
+ Te0[GETBYTE(s2, 3)] ^
+ Te1[GETBYTE(s3, 2)] ^
+ Te2[GETBYTE(s0, 1)] ^
+ Te3[GETBYTE(s1, 0)] ^
+ rk[6];
+ t3 =
+ Te0[GETBYTE(s3, 3)] ^
+ Te1[GETBYTE(s0, 2)] ^
+ Te2[GETBYTE(s1, 1)] ^
+ Te3[GETBYTE(s2, 0)] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Te0[GETBYTE(t0, 3)] ^
+ Te1[GETBYTE(t1, 2)] ^
+ Te2[GETBYTE(t2, 1)] ^
+ Te3[GETBYTE(t3, 0)] ^
+ rk[0];
+ s1 =
+ Te0[GETBYTE(t1, 3)] ^
+ Te1[GETBYTE(t2, 2)] ^
+ Te2[GETBYTE(t3, 1)] ^
+ Te3[GETBYTE(t0, 0)] ^
+ rk[1];
+ s2 =
+ Te0[GETBYTE(t2, 3)] ^
+ Te1[GETBYTE(t3, 2)] ^
+ Te2[GETBYTE(t0, 1)] ^
+ Te3[GETBYTE(t1, 0)] ^
+ rk[2];
+ s3 =
+ Te0[GETBYTE(t3, 3)] ^
+ Te1[GETBYTE(t0, 2)] ^
+ Te2[GETBYTE(t1, 1)] ^
+ Te3[GETBYTE(t2, 0)] ^
+ rk[3];
+ }
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+
+ s0 =
+ (Te4[GETBYTE(t0, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t1, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t2, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t3, 0)] & 0x000000ff) ^
+ rk[0];
+ s1 =
+ (Te4[GETBYTE(t1, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t2, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t3, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t0, 0)] & 0x000000ff) ^
+ rk[1];
+ s2 =
+ (Te4[GETBYTE(t2, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t3, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t0, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t1, 0)] & 0x000000ff) ^
+ rk[2];
+ s3 =
+ (Te4[GETBYTE(t3, 3)] & 0xff000000) ^
+ (Te4[GETBYTE(t0, 2)] & 0x00ff0000) ^
+ (Te4[GETBYTE(t1, 1)] & 0x0000ff00) ^
+ (Te4[GETBYTE(t2, 0)] & 0x000000ff) ^
+ rk[3];
+
+ gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
+
+}
+
+
+void AES::decrypt(const byte* inBlock, const byte* xorBlock,
+ byte* outBlock) const
+{
+ word32 s0, s1, s2, s3, t0, t1, t2, t3;
+ const word32* rk = key_.get_buffer();
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ gpBlock::Get(inBlock)(s0)(s1)(s2)(s3);
+ s0 ^= rk[0];
+ s1 ^= rk[1];
+ s2 ^= rk[2];
+ s3 ^= rk[3];
+ /*
+ * Nr - 1 full rounds:
+ */
+ unsigned int r = rounds_ >> 1;
+ for (;;) {
+ t0 =
+ Td0[GETBYTE(s0, 3)] ^
+ Td1[GETBYTE(s3, 2)] ^
+ Td2[GETBYTE(s2, 1)] ^
+ Td3[GETBYTE(s1, 0)] ^
+ rk[4];
+ t1 =
+ Td0[GETBYTE(s1, 3)] ^
+ Td1[GETBYTE(s0, 2)] ^
+ Td2[GETBYTE(s3, 1)] ^
+ Td3[GETBYTE(s2, 0)] ^
+ rk[5];
+ t2 =
+ Td0[GETBYTE(s2, 3)] ^
+ Td1[GETBYTE(s1, 2)] ^
+ Td2[GETBYTE(s0, 1)] ^
+ Td3[GETBYTE(s3, 0)] ^
+ rk[6];
+ t3 =
+ Td0[GETBYTE(s3, 3)] ^
+ Td1[GETBYTE(s2, 2)] ^
+ Td2[GETBYTE(s1, 1)] ^
+ Td3[GETBYTE(s0, 0)] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Td0[GETBYTE(t0, 3)] ^
+ Td1[GETBYTE(t3, 2)] ^
+ Td2[GETBYTE(t2, 1)] ^
+ Td3[GETBYTE(t1, 0)] ^
+ rk[0];
+ s1 =
+ Td0[GETBYTE(t1, 3)] ^
+ Td1[GETBYTE(t0, 2)] ^
+ Td2[GETBYTE(t3, 1)] ^
+ Td3[GETBYTE(t2, 0)] ^
+ rk[1];
+ s2 =
+ Td0[GETBYTE(t2, 3)] ^
+ Td1[GETBYTE(t1, 2)] ^
+ Td2[GETBYTE(t0, 1)] ^
+ Td3[GETBYTE(t3, 0)] ^
+ rk[2];
+ s3 =
+ Td0[GETBYTE(t3, 3)] ^
+ Td1[GETBYTE(t2, 2)] ^
+ Td2[GETBYTE(t1, 1)] ^
+ Td3[GETBYTE(t0, 0)] ^
+ rk[3];
+ }
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Td4[GETBYTE(t0, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t3, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t2, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t1, 0)] & 0x000000ff) ^
+ rk[0];
+ s1 =
+ (Td4[GETBYTE(t1, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t0, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t3, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t2, 0)] & 0x000000ff) ^
+ rk[1];
+ s2 =
+ (Td4[GETBYTE(t2, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t1, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t0, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t3, 0)] & 0x000000ff) ^
+ rk[2];
+ s3 =
+ (Td4[GETBYTE(t3, 3)] & 0xff000000) ^
+ (Td4[GETBYTE(t2, 2)] & 0x00ff0000) ^
+ (Td4[GETBYTE(t1, 1)] & 0x0000ff00) ^
+ (Td4[GETBYTE(t0, 0)] & 0x000000ff) ^
+ rk[3];
+
+ gpBlock::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
+}
+
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/aestables.cpp b/extra/yassl/taocrypt/src/aestables.cpp
new file mode 100644
index 00000000000..7ba25bc9ffb
--- /dev/null
+++ b/extra/yassl/taocrypt/src/aestables.cpp
@@ -0,0 +1,724 @@
+/* aestables.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's aestables.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "aes.hpp"
+
+
+namespace TaoCrypt {
+
+
+/*
+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];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+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, 01, 01, 01];
+*/
+
+const word32 AES::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,
+};
+const word32 AES::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,
+};
+const word32 AES::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,
+};
+
+const word32 AES::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,
+};
+
+const word32 AES::Te4[256] = {
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+ 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+ 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+ 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+ 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+ 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+ 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+ 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+ 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+ 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+ 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+ 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+ 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+ 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+ 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+ 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+ 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+ 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+ 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+ 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+ 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+ 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+ 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+ 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+ 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+ 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+ 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+ 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+ 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+ 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+ 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+ 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+ 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+ 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+
+const word32 AES::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,
+};
+
+const word32 AES::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,
+};
+
+const word32 AES::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,
+};
+
+const word32 AES::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,
+};
+
+const word32 AES::Td4[256] = {
+ 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+ 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+ 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+ 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+ 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+ 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+ 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+ 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+ 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+ 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+ 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+ 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+ 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+ 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+ 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+ 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+ 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+ 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+ 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+ 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+ 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+ 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+ 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+ 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+ 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+ 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+ 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+ 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+ 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+ 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+ 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+ 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+ 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+ 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+ 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+ 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+ 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+ 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+ 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+ 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+ 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+ 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+ 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+ 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+ 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+ 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+ 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+ 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+ 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+ 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+ 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+ 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+ 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+ 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+ 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+ 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+ 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+ 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+ 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+ 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+ 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+ 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+ 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+ 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+
+const word32 AES::rcon_[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000,
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp
new file mode 100644
index 00000000000..1924be9b618
--- /dev/null
+++ b/extra/yassl/taocrypt/src/algebra.cpp
@@ -0,0 +1,354 @@
+/* algebra.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's algebra.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "algebra.hpp"
+#include "integer.hpp"
+#include "vector.hpp" // mySTL::vector (simple)
+
+
+namespace TaoCrypt {
+
+template <class T> const T& AbstractGroup<T>::Double(const Element &a) const
+{
+ return Add(a, a);
+}
+
+template <class T> const T& AbstractGroup<T>::Subtract(const Element &a,
+ const Element &b) const
+{
+ // make copy of a in case Inverse() overwrites it
+ Element a1(a);
+ return Add(a1, Inverse(b));
+}
+
+template <class T> T& AbstractGroup<T>::Accumulate(Element &a,
+ const Element &b) const
+{
+ return a = Add(a, b);
+}
+
+template <class T> T& AbstractGroup<T>::Reduce(Element &a,
+ const Element &b) const
+{
+ return a = Subtract(a, b);
+}
+
+template <class T> const T& AbstractRing<T>::Square(const Element &a) const
+{
+ return Multiply(a, a);
+}
+
+template <class T> const T& AbstractRing<T>::Divide(const Element &a,
+ const Element &b) const
+{
+ // make copy of a in case MultiplicativeInverse() overwrites it
+ Element a1(a);
+ return Multiply(a1, MultiplicativeInverse(b));
+}
+
+template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a,
+ const Element &b) const
+{
+ Element q;
+ DivisionAlgorithm(result, q, a, b);
+ return result;
+}
+
+template <class T> const T& AbstractEuclideanDomain<T>::Gcd(const Element &a,
+ const Element &b) const
+{
+ Element g[3]={b, a};
+ unsigned int i0=0, i1=1, i2=2;
+
+ while (!Equal(g[i1], this->Identity()))
+ {
+ g[i2] = Mod(g[i0], g[i1]);
+ unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
+ }
+
+ return result = g[i0];
+}
+
+template <class T> const typename
+ QuotientRing<T>::Element& QuotientRing<T>::MultiplicativeInverse(
+ const Element &a) const
+{
+ Element g[3]={m_modulus, a};
+#ifdef __BCPLUSPLUS__
+ // BC++50 workaround
+ Element v[3];
+ v[0]=m_domain.Identity();
+ v[1]=m_domain.MultiplicativeIdentity();
+#else
+ Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()};
+#endif
+ Element y;
+ unsigned int i0=0, i1=1, i2=2;
+
+ while (!Equal(g[i1], Identity()))
+ {
+ // y = g[i0] / g[i1];
+ // g[i2] = g[i0] % g[i1];
+ m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]);
+ // v[i2] = v[i0] - (v[i1] * y);
+ v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y));
+ unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
+ }
+
+ return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) :
+ m_domain.Identity();
+}
+
+template <class T> T AbstractGroup<T>::ScalarMultiply(const Element &base,
+ const Integer &exponent) const
+{
+ Element result;
+ SimultaneousMultiply(&result, base, &exponent, 1);
+ return result;
+}
+
+template <class T> T AbstractGroup<T>::CascadeScalarMultiply(const Element &x,
+ const Integer &e1, const Element &y, const Integer &e2) const
+{
+ const unsigned expLen = max(e1.BitCount(), e2.BitCount());
+ if (expLen==0)
+ return Identity();
+
+ const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
+ const unsigned tableSize = 1<<w;
+ mySTL::vector<Element> powerTable(tableSize << w);
+
+ powerTable[1] = x;
+ powerTable[tableSize] = y;
+ if (w==1)
+ powerTable[3] = Add(x,y);
+ else
+ {
+ powerTable[2] = Double(x);
+ powerTable[2*tableSize] = Double(y);
+
+ unsigned i, j;
+
+ for (i=3; i<tableSize; i+=2)
+ powerTable[i] = Add(powerTable[i-2], powerTable[2]);
+ for (i=1; i<tableSize; i+=2)
+ for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
+ powerTable[j] = Add(powerTable[j-tableSize], y);
+
+ for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
+ powerTable[i] = Add(powerTable[i-2*tableSize],
+ powerTable[2*tableSize]);
+ for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
+ for (j=i+2; j<i+tableSize; j+=2)
+ powerTable[j] = Add(powerTable[j-1], x);
+ }
+
+ Element result;
+ unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
+ bool firstTime = true;
+
+ for (int i = expLen-1; i>=0; i--)
+ {
+ power1 = 2*power1 + e1.GetBit(i);
+ power2 = 2*power2 + e2.GetBit(i);
+
+ if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
+ {
+ unsigned squaresBefore = prevPosition-i;
+ unsigned squaresAfter = 0;
+ prevPosition = i;
+ while ((power1 || power2) && power1%2 == 0 && power2%2==0)
+ {
+ power1 /= 2;
+ power2 /= 2;
+ squaresBefore--;
+ squaresAfter++;
+ }
+ if (firstTime)
+ {
+ result = powerTable[(power2<<w) + power1];
+ firstTime = false;
+ }
+ else
+ {
+ while (squaresBefore--)
+ result = Double(result);
+ if (power1 || power2)
+ Accumulate(result, powerTable[(power2<<w) + power1]);
+ }
+ while (squaresAfter--)
+ result = Double(result);
+ power1 = power2 = 0;
+ }
+ }
+ return result;
+}
+
+
+struct WindowSlider
+{
+ WindowSlider(const Integer &exp, bool fastNegate,
+ unsigned int windowSizeIn=0)
+ : exp(exp), windowModulus(Integer::One()), windowSize(windowSizeIn),
+ windowBegin(0), fastNegate(fastNegate), firstTime(true),
+ finished(false)
+ {
+ if (windowSize == 0)
+ {
+ unsigned int expLen = exp.BitCount();
+ windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 :
+ (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 :
+ (expLen <= 1434 ? 6 : 7)))));
+ }
+ windowModulus <<= windowSize;
+ }
+
+ void FindNextWindow()
+ {
+ unsigned int expLen = exp.WordCount() * WORD_BITS;
+ unsigned int skipCount = firstTime ? 0 : windowSize;
+ firstTime = false;
+ while (!exp.GetBit(skipCount))
+ {
+ if (skipCount >= expLen)
+ {
+ finished = true;
+ return;
+ }
+ skipCount++;
+ }
+
+ exp >>= skipCount;
+ windowBegin += skipCount;
+ expWindow = exp % (1 << windowSize);
+
+ if (fastNegate && exp.GetBit(windowSize))
+ {
+ negateNext = true;
+ expWindow = (1 << windowSize) - expWindow;
+ exp += windowModulus;
+ }
+ else
+ negateNext = false;
+ }
+
+ Integer exp, windowModulus;
+ unsigned int windowSize, windowBegin, expWindow;
+ bool fastNegate, negateNext, firstTime, finished;
+};
+
+template <class T>
+void AbstractGroup<T>::SimultaneousMultiply(T *results, const T &base,
+ const Integer *expBegin, unsigned int expCount) const
+{
+ mySTL::vector<mySTL::vector<Element> > buckets(expCount);
+ mySTL::vector<WindowSlider> exponents;
+ exponents.reserve(expCount);
+ unsigned int i;
+
+ for (i=0; i<expCount; i++)
+ {
+ assert(expBegin->NotNegative());
+ exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
+ exponents[i].FindNextWindow();
+ buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
+ }
+
+ unsigned int expBitPosition = 0;
+ Element g = base;
+ bool notDone = true;
+
+ while (notDone)
+ {
+ notDone = false;
+ for (i=0; i<expCount; i++)
+ {
+ if (!exponents[i].finished && expBitPosition ==
+ exponents[i].windowBegin)
+ {
+ Element &bucket = buckets[i][exponents[i].expWindow/2];
+ if (exponents[i].negateNext)
+ Accumulate(bucket, Inverse(g));
+ else
+ Accumulate(bucket, g);
+ exponents[i].FindNextWindow();
+ }
+ notDone = notDone || !exponents[i].finished;
+ }
+
+ if (notDone)
+ {
+ g = Double(g);
+ expBitPosition++;
+ }
+ }
+
+ for (i=0; i<expCount; i++)
+ {
+ Element &r = *results++;
+ r = buckets[i][buckets[i].size()-1];
+ if (buckets[i].size() > 1)
+ {
+ for (int j = buckets[i].size()-2; j >= 1; j--)
+ {
+ Accumulate(buckets[i][j], buckets[i][j+1]);
+ Accumulate(r, buckets[i][j]);
+ }
+ Accumulate(buckets[i][0], buckets[i][1]);
+ r = Add(Double(r), buckets[i][0]);
+ }
+ }
+}
+
+template <class T> T AbstractRing<T>::Exponentiate(const Element &base,
+ const Integer &exponent) const
+{
+ Element result;
+ SimultaneousExponentiate(&result, base, &exponent, 1);
+ return result;
+}
+
+template <class T> T AbstractRing<T>::CascadeExponentiate(const Element &x,
+ const Integer &e1, const Element &y, const Integer &e2) const
+{
+ return MultiplicativeGroup().AbstractGroup<T>::CascadeScalarMultiply(
+ x, e1, y, e2);
+}
+
+template <class Element, class Iterator> Element GeneralCascadeExponentiation(
+ const AbstractRing<Element> &ring, Iterator begin, Iterator end)
+{
+ return GeneralCascadeMultiplication<Element>(ring.MultiplicativeGroup(),
+ begin, end);
+}
+
+template <class T>
+void AbstractRing<T>::SimultaneousExponentiate(T *results, const T &base,
+ const Integer *exponents, unsigned int expCount) const
+{
+ MultiplicativeGroup().AbstractGroup<T>::SimultaneousMultiply(results, base,
+ exponents, expCount);
+}
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/arc4.cpp b/extra/yassl/taocrypt/src/arc4.cpp
new file mode 100644
index 00000000000..1e521b48f0c
--- /dev/null
+++ b/extra/yassl/taocrypt/src/arc4.cpp
@@ -0,0 +1,93 @@
+/* arc4.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's arc4.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "arc4.hpp"
+
+
+namespace TaoCrypt {
+
+void ARC4::SetKey(const byte* key, word32 length)
+{
+ x_ = 1;
+ y_ = 0;
+
+ word32 i;
+
+ for (i = 0; i < STATE_SIZE; i++)
+ state_[i] = i;
+
+ word32 keyIndex = 0, stateIndex = 0;
+
+ for (i = 0; i < STATE_SIZE; i++) {
+ word32 a = state_[i];
+ stateIndex += key[keyIndex] + a;
+ stateIndex &= 0xFF;
+ state_[i] = state_[stateIndex];
+ state_[stateIndex] = a;
+
+ if (++keyIndex >= length)
+ keyIndex = 0;
+ }
+}
+
+
+// local
+namespace {
+
+inline unsigned int MakeByte(word32& x, word32& y, byte* s)
+{
+ word32 a = s[x];
+ y = (y+a) & 0xff;
+
+ word32 b = s[y];
+ s[x] = b;
+ s[y] = a;
+ x = (x+1) & 0xff;
+
+ return s[(a+b) & 0xff];
+}
+
+} // namespace
+
+
+void ARC4::Process(byte* out, const byte* in, word32 length)
+{
+ if (length == 0) return;
+
+ byte *const s = state_;
+ word32 x = x_;
+ word32 y = y_;
+
+ if (in == out)
+ while (length--)
+ *out++ ^= MakeByte(x, y, s);
+ else
+ while(length--)
+ *out++ = *in++ ^ MakeByte(x, y, s);
+ x_ = x;
+ y_ = y;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
new file mode 100644
index 00000000000..d0d22a6c61d
--- /dev/null
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -0,0 +1,1051 @@
+ /* asn.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* asn.cpp implements ASN1 BER, PublicKey, and x509v3 decoding
+*/
+
+
+#include "runtime.hpp"
+#include "asn.hpp"
+#include "file.hpp"
+#include "integer.hpp"
+#include "rsa.hpp"
+#include "dsa.hpp"
+#include "dh.hpp"
+#include "md5.hpp"
+#include "md2.hpp"
+#include "sha.hpp"
+#include "coding.hpp"
+#include <time.h> // gmtime();
+#include "memory.hpp" // mySTL::auto_ptr
+
+namespace TaoCrypt {
+
+namespace { // locals
+
+
+// to the minute
+bool operator>(tm& a, tm& b)
+{
+ if (a.tm_year > b.tm_year)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon > b.tm_mon)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon && a.tm_mday >b.tm_mday)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon &&
+ a.tm_mday == b.tm_mday && a.tm_hour > b.tm_hour)
+ return true;
+
+ if (a.tm_year == b.tm_year && a.tm_mon == b.tm_mon &&
+ a.tm_mday == b.tm_mday && a.tm_hour == b.tm_hour &&
+ a.tm_min > b.tm_min)
+ return true;
+
+ return false;
+}
+
+
+bool operator<(tm& a, tm&b)
+{
+ return !(a>b);
+}
+
+
+// like atoi but only use first byte
+word32 btoi(byte b)
+{
+ return b - 0x30;
+}
+
+
+// two byte date/time, add to value
+void GetTime(int& value, const byte* date, int& i)
+{
+ value += btoi(date[i++]) * 10;
+ value += btoi(date[i++]);
+}
+
+
+// Make sure before and after dates are valid
+bool ValidateDate(const byte* date, byte format, CertDecoder::DateType dt)
+{
+ tm certTime;
+ memset(&certTime, 0, sizeof(certTime));
+ int i = 0;
+
+ if (format == UTC_TIME) {
+ if (btoi(date[0]) >= 5)
+ certTime.tm_year = 1900;
+ else
+ certTime.tm_year = 2000;
+ }
+ else { // format == GENERALIZED_TIME
+ certTime.tm_year += btoi(date[i++]) * 1000;
+ certTime.tm_year += btoi(date[i++]) * 100;
+ }
+
+ GetTime(certTime.tm_year, date, i); certTime.tm_year -= 1900; // adjust
+ GetTime(certTime.tm_mon, date, i); certTime.tm_mon -= 1; // adjust
+ GetTime(certTime.tm_mday, date, i);
+ GetTime(certTime.tm_hour, date, i);
+ GetTime(certTime.tm_min, date, i);
+ GetTime(certTime.tm_sec, date, i);
+
+ assert(date[i] == 'Z'); // only Zulu supported for this profile
+
+ time_t ltime = time(0);
+ tm* localTime = gmtime(&ltime);
+
+ if (dt == CertDecoder::BEFORE) {
+ if (*localTime < certTime)
+ return false;
+ }
+ else
+ if (*localTime > certTime)
+ return false;
+
+ return true;
+}
+
+
+class BadCertificate {};
+
+} // local namespace
+
+
+
+// used by Integer as well
+word32 GetLength(Source& source)
+{
+ word32 length = 0;
+
+ byte b = source.next();
+ if (b >= LONG_LENGTH) {
+ word32 bytes = b & 0x7F;
+
+ while (bytes--) {
+ b = source.next();
+ length = (length << 8) | b;
+ }
+ }
+ else
+ length = b;
+
+ return length;
+}
+
+
+word32 SetLength(word32 length, byte* output)
+{
+ word32 i = 0;
+
+ if (length < LONG_LENGTH)
+ output[i++] = length;
+ else {
+ output[i++] = BytePrecision(length) | 0x80;
+
+ for (int j = BytePrecision(length); j; --j) {
+ output[i] = length >> (j - 1) * 8;
+ i++;
+ }
+ }
+ return i;
+}
+
+
+PublicKey::PublicKey(const byte* k, word32 s) : key_(0), sz_(0)
+{
+ if (s) {
+ SetSize(s);
+ SetKey(k);
+ }
+}
+
+
+void PublicKey::SetSize(word32 s)
+{
+ sz_ = s;
+ key_ = new (tc) byte[sz_];
+}
+
+
+void PublicKey::SetKey(const byte* k)
+{
+ memcpy(key_, k, sz_);
+}
+
+
+void PublicKey::AddToEnd(const byte* data, word32 len)
+{
+ mySTL::auto_ptr<byte> tmp(new (tc) byte[sz_ + len]);
+
+ memcpy(tmp.get(), key_, sz_);
+ memcpy(tmp.get() + sz_, data, len);
+
+ byte* del = 0;
+ mySTL::swap(del, key_);
+ delete[] del;
+
+ key_ = tmp.release();
+ sz_ += len;
+}
+
+
+Signer::Signer(const byte* k, word32 kSz, const char* n, const byte* h)
+ : key_(k, kSz), name_(0)
+{
+ if (n) {
+ int sz = strlen(n);
+ name_ = new (tc) char[sz + 1];
+ memcpy(name_, n, sz);
+ name_[sz] = 0;
+ }
+
+ memcpy(hash_, h, SHA::DIGEST_SIZE);
+}
+
+Signer::~Signer()
+{
+ delete[] name_;
+}
+
+
+Error BER_Decoder::GetError()
+{
+ return source_.GetError();
+}
+
+
+Integer& BER_Decoder::GetInteger(Integer& integer)
+{
+ if (!source_.GetError().What())
+ integer.Decode(source_);
+ return integer;
+}
+
+
+// Read a Sequence, return length
+word32 BER_Decoder::GetSequence()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != (SEQUENCE | CONSTRUCTED)) {
+ source_.SetError(SEQUENCE_E);
+ return 0;
+ }
+
+ return GetLength(source_);
+}
+
+
+// Read a Sequence, return length
+word32 BER_Decoder::GetSet()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != (SET | CONSTRUCTED)) {
+ source_.SetError(SET_E);
+ return 0;
+ }
+
+ return GetLength(source_);
+}
+
+
+// Read Version, return it
+word32 BER_Decoder::GetVersion()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+ if (b != INTEGER) {
+ source_.SetError(INTEGER_E);
+ return 0;
+ }
+
+ b = source_.next();
+ if (b != 0x01) {
+ source_.SetError(VERSION_E);
+ return 0;
+ }
+
+ return source_.next();
+}
+
+
+// Read ExplicitVersion, return it or 0 if not there (not an error)
+word32 BER_Decoder::GetExplicitVersion()
+{
+ if (source_.GetError().What()) return 0;
+
+ byte b = source_.next();
+
+ if (b == (CONTEXT_SPECIFIC | CONSTRUCTED)) { // not an error if not here
+ source_.next();
+ return GetVersion();
+ }
+ else
+ source_.prev(); // put back
+
+ return 0;
+}
+
+
+// Decode a BER encoded RSA Private Key
+void RSA_Private_Decoder::Decode(RSA_PrivateKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+ // public
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetPublicExponent(GetInteger(Integer().Ref()));
+
+ // private
+ key.SetPrivateExponent(GetInteger(Integer().Ref()));
+ key.SetPrime1(GetInteger(Integer().Ref()));
+ key.SetPrime2(GetInteger(Integer().Ref()));
+ key.SetModPrime1PrivateExponent(GetInteger(Integer().Ref()));
+ key.SetModPrime2PrivateExponent(GetInteger(Integer().Ref()));
+ key.SetMultiplicativeInverseOfPrime2ModPrime1(GetInteger(Integer().Ref()));
+}
+
+
+void RSA_Private_Decoder::ReadHeader()
+{
+ GetSequence();
+ GetVersion();
+}
+
+
+// Decode a BER encoded DSA Private Key
+void DSA_Private_Decoder::Decode(DSA_PrivateKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+ // group parameters
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetSubGroupOrder(GetInteger(Integer().Ref()));
+ key.SetSubGroupGenerator(GetInteger(Integer().Ref()));
+
+ // key
+ key.SetPublicPart(GetInteger(Integer().Ref()));
+ key.SetPrivatePart(GetInteger(Integer().Ref()));
+}
+
+
+void DSA_Private_Decoder::ReadHeader()
+{
+ GetSequence();
+ GetVersion();
+}
+
+
+// Decode a BER encoded RSA Public Key
+void RSA_Public_Decoder::Decode(RSA_PublicKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // public key
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetPublicExponent(GetInteger(Integer().Ref()));
+}
+
+
+void RSA_Public_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+// Decode a BER encoded DSA Public Key
+void DSA_Public_Decoder::Decode(DSA_PublicKey& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // group parameters
+ key.SetModulus(GetInteger(Integer().Ref()));
+ key.SetSubGroupOrder(GetInteger(Integer().Ref()));
+ key.SetSubGroupGenerator(GetInteger(Integer().Ref()));
+
+ // key
+ key.SetPublicPart(GetInteger(Integer().Ref()));
+}
+
+
+void DSA_Public_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+void DH_Decoder::ReadHeader()
+{
+ GetSequence();
+}
+
+
+// Decode a BER encoded Diffie-Hellman Key
+void DH_Decoder::Decode(DH& key)
+{
+ ReadHeader();
+ if (source_.GetError().What()) return;
+
+ // group parms
+ key.SetP(GetInteger(Integer().Ref()));
+ key.SetG(GetInteger(Integer().Ref()));
+}
+
+
+CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers)
+ : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0),
+ signature_(0), issuer_(0), subject_(0)
+{
+ if (decode)
+ Decode(signers);
+}
+
+
+CertDecoder::~CertDecoder()
+{
+ delete[] subject_;
+ delete[] issuer_;
+ delete[] signature_;
+}
+
+
+// process certificate header, set signature offset
+void CertDecoder::ReadHeader()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence(); // total
+ certBegin_ = source_.get_index();
+
+ sigIndex_ = GetSequence(); // this cert
+ sigIndex_ += source_.get_index();
+
+ GetExplicitVersion(); // version
+ GetInteger(Integer().Ref()); // serial number
+}
+
+
+// Decode a x509v3 Certificate
+void CertDecoder::Decode(SignerList* signers)
+{
+ if (source_.GetError().What()) return;
+ DecodeToKey();
+ if (source_.GetError().What()) return;
+
+ if (source_.get_index() != sigIndex_)
+ source_.set_index(sigIndex_);
+
+ word32 confirmOID = GetAlgoId();
+ GetSignature();
+ if (source_.GetError().What()) return;
+
+ if ( confirmOID != signatureOID_ ) {
+ source_.SetError(SIG_OID_E);
+ return;
+ }
+
+ if ( memcmp(issuerHash_, subjectHash_, SHA::DIGEST_SIZE) == 0 ) {
+ if (!ValidateSelfSignature())
+ source_.SetError(SIG_CONFIRM_E);
+ }
+ else
+ if (!ValidateSignature(signers))
+ source_.SetError(SIG_CONFIRM_E);
+}
+
+
+void CertDecoder::DecodeToKey()
+{
+ ReadHeader();
+ signatureOID_ = GetAlgoId();
+ GetName(ISSUER);
+ GetValidity();
+ GetName(SUBJECT);
+ GetKey();
+}
+
+
+// Read public key
+void CertDecoder::GetKey()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence();
+ keyOID_ = GetAlgoId();
+
+ if (keyOID_ == RSAk) {
+ byte b = source_.next();
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return;
+ }
+ b = source_.next(); // length, future
+ b = source_.next();
+ while(b != 0)
+ b = source_.next();
+ }
+ else if (keyOID_ == DSAk)
+ ; // do nothing
+ else {
+ source_.SetError(UNKNOWN_OID_E);
+ return;
+ }
+
+ StoreKey();
+ if (keyOID_ == DSAk)
+ AddDSA();
+}
+
+
+// Save public key
+void CertDecoder::StoreKey()
+{
+ if (source_.GetError().What()) return;
+
+ word32 read = source_.get_index();
+ word32 length = GetSequence();
+
+ read = source_.get_index() - read;
+ length += read;
+
+ while (read--) source_.prev();
+
+ key_.SetSize(length);
+ key_.SetKey(source_.get_current());
+ source_.advance(length);
+}
+
+
+// DSA has public key after group
+void CertDecoder::AddDSA()
+{
+ if (source_.GetError().What()) return;
+
+ byte b = source_.next();
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return;
+ }
+ b = source_.next(); // length, future
+ b = source_.next();
+ while(b != 0)
+ b = source_.next();
+
+ word32 idx = source_.get_index();
+ b = source_.next();
+ if (b != INTEGER) {
+ source_.SetError(INTEGER_E);
+ return;
+ }
+
+ word32 length = GetLength(source_);
+ length += source_.get_index() - idx;
+
+ key_.AddToEnd(source_.get_buffer() + idx, length);
+}
+
+
+// process algo OID by summing, return it
+word32 CertDecoder::GetAlgoId()
+{
+ if (source_.GetError().What()) return 0;
+ word32 length = GetSequence();
+
+ byte b = source_.next();
+ if (b != OBJECT_IDENTIFIER) {
+ source_.SetError(OBJECT_ID_E);
+ return 0;
+ }
+
+ length = GetLength(source_);
+ word32 oid = 0;
+
+ while(length--)
+ oid += source_.next(); // just sum it up for now
+
+ if (oid != SHAwDSA && oid != DSAk) {
+ b = source_.next(); // should have NULL tag and 0
+
+ if (b != TAG_NULL) {
+ source_.SetError(TAG_NULL_E);
+ return 0;
+ }
+
+ b = source_.next();
+ if (b != 0) {
+ source_.SetError(EXPECT_0_E);
+ return 0;
+ }
+ }
+
+ return oid;
+}
+
+
+// read cert signature, store in signature_
+word32 CertDecoder::GetSignature()
+{
+ if (source_.GetError().What()) return 0;
+ byte b = source_.next();
+
+ if (b != BIT_STRING) {
+ source_.SetError(BIT_STR_E);
+ return 0;
+ }
+
+ sigLength_ = GetLength(source_);
+
+ b = source_.next();
+ if (b != 0) {
+ source_.SetError(EXPECT_0_E);
+ return 0;
+ }
+ sigLength_--;
+
+ signature_ = new (tc) byte[sigLength_];
+ memcpy(signature_, source_.get_current(), sigLength_);
+ source_.advance(sigLength_);
+
+ return sigLength_;
+}
+
+
+// read cert digest, store in signature_
+word32 CertDecoder::GetDigest()
+{
+ if (source_.GetError().What()) return 0;
+ byte b = source_.next();
+
+ if (b != OCTET_STRING) {
+ source_.SetError(OCTET_STR_E);
+ return 0;
+ }
+
+ sigLength_ = GetLength(source_);
+
+ signature_ = new (tc) byte[sigLength_];
+ memcpy(signature_, source_.get_current(), sigLength_);
+ source_.advance(sigLength_);
+
+ return sigLength_;
+}
+
+
+// process NAME, either issuer or subject
+void CertDecoder::GetName(NameType nt)
+{
+ if (source_.GetError().What()) return;
+
+ SHA sha;
+ word32 length = GetSequence(); // length of all distinguished names
+ length += source_.get_index();
+
+ while (source_.get_index() < length) {
+ GetSet();
+ GetSequence();
+
+ byte b = source_.next();
+ if (b != OBJECT_IDENTIFIER) {
+ source_.SetError(OBJECT_ID_E);
+ return;
+ }
+
+ word32 oidSz = GetLength(source_);
+ byte joint[2];
+ memcpy(joint, source_.get_current(), sizeof(joint));
+
+ // v1 name types
+ if (joint[0] == 0x55 && joint[1] == 0x04) {
+ source_.advance(2);
+ byte id = source_.next();
+ b = source_.next(); // strType
+ word32 strLen = GetLength(source_);
+
+ if (id == COMMON_NAME) {
+ char*& ptr = (nt == ISSUER) ? issuer_ : subject_;
+ ptr = new (tc) char[strLen + 1];
+ memcpy(ptr, source_.get_current(), strLen);
+ ptr[strLen] = 0;
+ }
+ sha.Update(source_.get_current(), strLen);
+ source_.advance(strLen);
+ }
+ else {
+ // skip
+ source_.advance(oidSz + 1);
+ word32 length = GetLength(source_);
+ source_.advance(length);
+ }
+ }
+ if (nt == ISSUER)
+ sha.Final(issuerHash_);
+ else
+ sha.Final(subjectHash_);
+}
+
+
+// process a Date, either BEFORE or AFTER
+void CertDecoder::GetDate(DateType dt)
+{
+ if (source_.GetError().What()) return;
+
+ byte b = source_.next();
+ if (b != UTC_TIME && b != GENERALIZED_TIME) {
+ source_.SetError(TIME_E);
+ return;
+ }
+
+ word32 length = GetLength(source_);
+ byte date[MAX_DATE_SZ];
+ if (length > MAX_DATE_SZ || length < MIN_DATE_SZ) {
+ source_.SetError(DATE_SZ_E);
+ return;
+ }
+
+ memcpy(date, source_.get_current(), length);
+ source_.advance(length);
+
+ if (!ValidateDate(date, b, dt))
+ if (dt == BEFORE)
+ source_.SetError(BEFORE_DATE_E);
+ else
+ source_.SetError(AFTER_DATE_E);
+}
+
+
+void CertDecoder::GetValidity()
+{
+ if (source_.GetError().What()) return;
+
+ GetSequence();
+ GetDate(BEFORE);
+ GetDate(AFTER);
+}
+
+
+bool CertDecoder::ValidateSelfSignature()
+{
+ Source pub(key_.GetKey(), key_.size());
+ return ConfirmSignature(pub);
+}
+
+
+// extract compare signature hash from plain and place into digest
+void CertDecoder::GetCompareHash(const byte* plain, word32 sz, byte* digest,
+ word32 digSz)
+{
+ if (source_.GetError().What()) return;
+
+ Source s(plain, sz);
+ CertDecoder dec(s, false);
+
+ dec.GetSequence();
+ dec.GetAlgoId();
+ dec.GetDigest();
+
+ if (dec.sigLength_ > digSz) {
+ source_.SetError(SIG_LEN_E);
+ return;
+ }
+
+ memcpy(digest, dec.signature_, dec.sigLength_);
+}
+
+
+// validate signature signed by someone else
+bool CertDecoder::ValidateSignature(SignerList* signers)
+{
+ assert(signers);
+
+ SignerList::iterator first = signers->begin();
+ SignerList::iterator last = signers->end();
+
+ while (first != last) {
+ if ( memcmp(issuerHash_, (*first)->GetHash(), SHA::DIGEST_SIZE) == 0) {
+
+ const PublicKey& iKey = (*first)->GetPublicKey();
+ Source pub(iKey.GetKey(), iKey.size());
+ return ConfirmSignature(pub);
+ }
+ ++first;
+ }
+ return false;
+}
+
+
+// RSA confirm
+bool CertDecoder::ConfirmSignature(Source& pub)
+{
+ HashType ht;
+ mySTL::auto_ptr<HASH> hasher;
+
+ if (signatureOID_ == MD5wRSA) {
+ hasher.reset(new (tc) MD5);
+ ht = MD5h;
+ }
+ else if (signatureOID_ == MD2wRSA) {
+ hasher.reset(new (tc) MD2);
+ ht = MD2h;
+ }
+ else if (signatureOID_ == SHAwRSA || signatureOID_ == SHAwDSA) {
+ hasher.reset(new (tc) SHA);
+ ht = SHAh;
+ }
+ else {
+ source_.SetError(UNKOWN_SIG_E);
+ return false;
+ }
+
+ byte digest[SHA::DIGEST_SIZE]; // largest size
+
+ hasher->Update(source_.get_buffer() + certBegin_, sigIndex_ - certBegin_);
+ hasher->Final(digest);
+
+ if (keyOID_ == RSAk) {
+ // put in ASN.1 signature format
+ Source build;
+ Signature_Encoder(digest, hasher->getDigestSize(), ht, build);
+
+ RSA_PublicKey pubKey(pub);
+ RSAES_Encryptor enc(pubKey);
+
+ return enc.SSL_Verify(build.get_buffer(), build.size(), signature_);
+ }
+ else { // DSA
+ // extract r and s from sequence
+ byte seqDecoded[DSA_SIG_SZ];
+ DecodeDSA_Signature(seqDecoded, signature_, sigLength_);
+
+ DSA_PublicKey pubKey(pub);
+ DSA_Verifier ver(pubKey);
+
+ return ver.Verify(digest, seqDecoded);
+ }
+}
+
+
+Signature_Encoder::Signature_Encoder(const byte* dig, word32 digSz,
+ HashType digOID, Source& source)
+{
+ // build bottom up
+
+ // Digest
+ byte digArray[MAX_DIGEST_SZ];
+ word32 digestSz = SetDigest(dig, digSz, digArray);
+
+ // AlgoID
+ byte algoArray[MAX_ALGO_SZ];
+ word32 algoSz = SetAlgoID(digOID, algoArray);
+
+ // Sequence
+ byte seqArray[MAX_SEQ_SZ];
+ word32 seqSz = SetSequence(digestSz + algoSz, seqArray);
+
+ source.grow(seqSz + algoSz + digestSz); // make sure enough room
+ source.add(seqArray, seqSz);
+ source.add(algoArray, algoSz);
+ source.add(digArray, digestSz);
+}
+
+
+
+word32 Signature_Encoder::SetDigest(const byte* d, word32 dSz, byte* output)
+{
+ output[0] = OCTET_STRING;
+ output[1] = dSz;
+ memcpy(&output[2], d, dSz);
+
+ return dSz + 2;
+}
+
+
+
+word32 DER_Encoder::SetAlgoID(HashType aOID, byte* output)
+{
+ // adding TAG_NULL and 0 to end
+ static const byte shaAlgoID[] = { 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00 };
+ static const byte md5AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x05, 0x05, 0x00 };
+ static const byte md2AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x02, 0x02, 0x05, 0x00};
+
+ int algoSz = 0;
+ const byte* algoName = 0;
+
+ switch (aOID) {
+ case SHAh:
+ algoSz = sizeof(shaAlgoID);
+ algoName = shaAlgoID;
+ break;
+
+ case MD2h:
+ algoSz = sizeof(md2AlgoID);
+ algoName = md2AlgoID;
+ break;
+
+ case MD5h:
+ algoSz = sizeof(md5AlgoID);
+ algoName = md5AlgoID;
+ break;
+
+ default:
+ error_.SetError(UNKOWN_HASH_E);
+ return 0;
+ }
+
+
+ byte ID_Length[MAX_LENGTH_SZ];
+ word32 idSz = SetLength(algoSz - 2, ID_Length); // don't include TAG_NULL/0
+
+ byte seqArray[MAX_SEQ_SZ + 1]; // add object_id to end
+ word32 seqSz = SetSequence(idSz + algoSz + 1, seqArray);
+ seqArray[seqSz++] = OBJECT_IDENTIFIER;
+
+ memcpy(output, seqArray, seqSz);
+ memcpy(output + seqSz, ID_Length, idSz);
+ memcpy(output + seqSz + idSz, algoName, algoSz);
+
+ return seqSz + idSz + algoSz;
+}
+
+
+word32 SetSequence(word32 len, byte* output)
+{
+
+ output[0] = SEQUENCE | CONSTRUCTED;
+ return SetLength(len, output + 1) + 1;
+}
+
+
+word32 EncodeDSA_Signature(const byte* signature, byte* output)
+{
+ Integer r(signature, 20);
+ Integer s(signature + 20, 20);
+
+ return EncodeDSA_Signature(r, s, output);
+}
+
+
+word32 EncodeDSA_Signature(const Integer& r, const Integer& s, byte* output)
+{
+ word32 rSz = r.ByteCount();
+ word32 sSz = s.ByteCount();
+
+ byte rLen[MAX_LENGTH_SZ + 1];
+ byte sLen[MAX_LENGTH_SZ + 1];
+
+ rLen[0] = INTEGER;
+ sLen[0] = INTEGER;
+
+ word32 rLenSz = SetLength(rSz, &rLen[1]) + 1;
+ word32 sLenSz = SetLength(sSz, &sLen[1]) + 1;
+
+ byte seqArray[MAX_SEQ_SZ];
+
+ word32 seqSz = SetSequence(rLenSz + rSz + sLenSz + sSz, seqArray);
+
+ // seq
+ memcpy(output, seqArray, seqSz);
+ // r
+ memcpy(output + seqSz, rLen, rLenSz);
+ r.Encode(output + seqSz + rLenSz, rSz);
+ // s
+ memcpy(output + seqSz + rLenSz + rSz, sLen, sLenSz);
+ s.Encode(output + seqSz + rLenSz + rSz + sLenSz, sSz);
+
+ return seqSz + rLenSz + rSz + sLenSz + sSz;
+}
+
+
+// put sequence encoded dsa signature into decoded in 2 20 byte integers
+word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz)
+{
+ Source source(encoded, sz);
+
+ if (source.next() != (SEQUENCE | CONSTRUCTED)) {
+ source.SetError(SEQUENCE_E);
+ return 0;
+ }
+
+ GetLength(source); // total
+
+ // r
+ if (source.next() != INTEGER) {
+ source.SetError(INTEGER_E);
+ return 0;
+ }
+ word32 rLen = GetLength(source);
+ if (rLen != 20)
+ if (rLen == 21) { // zero at front, eat
+ source.next();
+ --rLen;
+ }
+ else if (rLen == 19) { // add zero to front so 20 bytes
+ decoded[0] = 0;
+ decoded++;
+ }
+ else {
+ source.SetError(DSA_SZ_E);
+ return 0;
+ }
+ memcpy(decoded, source.get_buffer() + source.get_index(), rLen);
+ source.advance(rLen);
+
+ // s
+ if (source.next() != INTEGER) {
+ source.SetError(INTEGER_E);
+ return 0;
+ }
+ word32 sLen = GetLength(source);
+ if (sLen != 20)
+ if (sLen == 21) {
+ source.next(); // zero at front, eat
+ --sLen;
+ }
+ else if (sLen == 19) {
+ decoded[rLen] = 0; // add zero to front so 20 bytes
+ decoded++;
+ }
+ else {
+ source.SetError(DSA_SZ_E);
+ return 0;
+ }
+ memcpy(decoded + rLen, source.get_buffer() + source.get_index(), sLen);
+ source.advance(sLen);
+
+ return 40;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp
new file mode 100644
index 00000000000..944a47c288e
--- /dev/null
+++ b/extra/yassl/taocrypt/src/coding.cpp
@@ -0,0 +1,250 @@
+/* coding.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* coding.cpp implements hex and base64 encoding/decoing
+*/
+
+#include "runtime.hpp"
+#include "coding.hpp"
+#include "file.hpp"
+
+
+namespace TaoCrypt {
+
+
+namespace { // locals
+
+const byte bad = 0xFF; // invalid encoding
+
+const byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ bad, bad, bad, bad, bad, bad, bad,
+ 10, 11, 12, 13, 14, 15
+ }; // A starts at 0x41 not 0x3A
+
+
+const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '+', '/'
+ };
+
+const byte base64Decode[] = { 62, bad, bad, bad, 63, // + starts at 0x2B
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ bad, bad, bad, bad, bad, bad, bad,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25,
+ bad, bad, bad, bad, bad, bad,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51
+ };
+
+const byte pad = '=';
+const int pemLineSz = 64;
+
+} // local namespace
+
+
+// Hex Encode
+void HexEncoder::Encode()
+{
+ word32 bytes = plain_.size();
+ encoded_.New(bytes * 2);
+
+ word32 i = 0;
+
+ while (bytes--) {
+ byte p = plain_.next();
+
+ byte b = p >> 4;
+ byte b2 = p & 0xF;
+
+ encoded_[i++] = hexEncode[b];
+ encoded_[i++] = hexEncode[b2];
+ }
+
+ plain_.reset(encoded_);
+}
+
+
+// Hex Decode
+void HexDecoder::Decode()
+{
+ word32 bytes = coded_.size();
+ assert((bytes % 2) == 0);
+ decoded_.New(bytes / 2);
+
+ word32 i(0);
+
+ while (bytes) {
+ byte b = coded_.next() - 0x30; // 0 starts at 0x30
+ byte b2 = coded_.next() - 0x30;
+
+ // sanity checks
+ assert( b < sizeof(hexDecode)/sizeof(hexDecode[0]) );
+ assert( b2 < sizeof(hexDecode)/sizeof(hexDecode[0]) );
+ assert( b != bad && b2 != bad );
+
+ b = hexDecode[b];
+ b2 = hexDecode[b2];
+
+ decoded_[i++] = (b << 4) | b2;
+ bytes -= 2;
+ }
+
+ coded_.reset(decoded_);
+}
+
+
+// Base 64 Encode
+void Base64Encoder::Encode()
+{
+ word32 bytes = plain_.size();
+ word32 outSz = bytes * 4 / 3;
+ outSz += (outSz % 4); // 4 byte integrals
+
+ outSz += outSz / pemLineSz + ( (outSz % pemLineSz) ? 1 : 0); // new lines
+ encoded_.New(outSz);
+
+ word32 i = 0;
+ word32 j = 0;
+
+ while (bytes > 2) {
+ byte b1 = plain_.next();
+ byte b2 = plain_.next();
+ byte b3 = plain_.next();
+
+ // encoded idx
+ byte e1 = b1 >> 2;
+ byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
+ byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
+ byte e4 = b3 & 0x3F;
+
+ // store
+ encoded_[i++] = base64Encode[e1];
+ encoded_[i++] = base64Encode[e2];
+ encoded_[i++] = base64Encode[e3];
+ encoded_[i++] = base64Encode[e4];
+
+ bytes -= 3;
+
+ if ((++j % 16) == 0)
+ encoded_[i++] = '\n';
+ }
+
+ // last integral
+ if (bytes) {
+ bool twoBytes = (bytes == 2);
+
+ byte b1 = plain_.next();
+ byte b2 = (twoBytes) ? plain_.next() : 0;
+
+ byte e1 = b1 >> 2;
+ byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
+ byte e3 = (b2 & 0xF) << 2;
+
+ encoded_[i++] = base64Encode[e1];
+ encoded_[i++] = base64Encode[e2];
+ encoded_[i++] = (twoBytes) ? base64Encode[e3] : pad;
+ encoded_[i++] = pad;
+ }
+
+ encoded_[i++] = '\n';
+ assert(i == outSz);
+
+ plain_.reset(encoded_);
+}
+
+
+// Base 64 Decode
+void Base64Decoder::Decode()
+{
+ word32 bytes = coded_.size();
+ word32 plainSz = bytes - (bytes / pemLineSz + ( (bytes % pemLineSz) ?
+ 1 : 0));
+ plainSz = plainSz * 3 / 4 + (( (plainSz * 3) % 4) ? 1 : 0);
+ decoded_.New(plainSz);
+
+ word32 i = 0;
+ word32 j = 0;
+
+ while (bytes > 3) {
+ byte e1 = coded_.next();
+ byte e2 = coded_.next();
+ byte e3 = coded_.next();
+ byte e4 = coded_.next();
+
+ // do asserts first
+ if (e1 == 0) // end file 0's
+ break;
+
+ bool pad3 = false;
+ bool pad4 = false;
+ if (e3 == pad)
+ pad3 = true;
+ if (e4 == pad)
+ pad4 = true;
+
+ e1 = base64Decode[e1 - 0x2B];
+ e2 = base64Decode[e2 - 0x2B];
+ e3 = (e3 == pad) ? 0 : base64Decode[e3 - 0x2B];
+ e4 = (e4 == pad) ? 0 : base64Decode[e4 - 0x2B];
+
+ byte b1 = (e1 << 2) | (e2 >> 4);
+ byte b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
+ byte b3 = ((e3 & 0x3) << 6) | e4;
+
+ decoded_[i++] = b1;
+ if (!pad3)
+ decoded_[i++] = b2;
+ if (!pad4)
+ decoded_[i++] = b3;
+ else
+ break;
+
+ bytes -= 4;
+ if ((++j % 16) == 0) {
+ byte endLine = coded_.next();
+ bytes--;
+ if (endLine == '\r') {
+ endLine = coded_.next();
+ bytes--;
+ }
+ assert(endLine == '\n');
+ }
+ }
+
+ if (i != decoded_.size())
+ decoded_.resize(i);
+ coded_.reset(decoded_);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/des.cpp b/extra/yassl/taocrypt/src/des.cpp
new file mode 100644
index 00000000000..e5d3331500c
--- /dev/null
+++ b/extra/yassl/taocrypt/src/des.cpp
@@ -0,0 +1,435 @@
+/* des.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's des.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "des.hpp"
+#include <string.h>
+#include "algorithm.hpp" // mySTL::swap
+
+
+namespace TaoCrypt {
+
+
+/* permuted choice table (key) */
+static const byte pc1[] = {
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4
+};
+
+/* number left rotations of pc1 */
+static const byte totrot[] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
+};
+
+/* permuted choice key (table) */
+static const byte pc2[] = {
+ 14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32
+};
+
+/* End of DES-defined tables */
+
+/* bit 0 is left-most in byte */
+static const int bytebit[] = {
+ 0200,0100,040,020,010,04,02,01
+};
+
+
+void DES::SetKey(const byte* key, word32 /*length*/, CipherDir dir)
+{
+ byte buffer[56+56+8];
+ byte *const pc1m = buffer; /* place to modify pc1 into */
+ byte *const pcr = pc1m + 56; /* place to rotate pc1 into */
+ byte *const ks = pcr + 56;
+ register int i,j,l;
+ int m;
+
+ for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */
+ l = pc1[j] - 1; /* integer bit location */
+ m = l & 07; /* find bit */
+ pc1m[j] = (key[l >> 3] & /* find which key byte l is in */
+ bytebit[m]) /* and which bit of that byte */
+ ? 1 : 0; /* and store 1-bit result */
+ }
+ for (i = 0; i < 16; i++) { /* key chunk for each iteration */
+ memset(ks, 0, 8); /* Clear key schedule */
+ for (j = 0; j < 56; j++) /* rotate pc1 the right amount */
+ pcr[j] = pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l: l-28];
+ /* rotate left and right halves independently */
+ for (j = 0; j < 48; j++){ /* select bits individually */
+ /* check bit that goes to ks[j] */
+ if (pcr[pc2[j] - 1]){
+ /* mask it in if it's there */
+ l= j % 6;
+ ks[j/6] |= bytebit[l] >> 2;
+ }
+ }
+ /* Now convert to odd/even interleaved form for use in F */
+ k_[2*i] = ((word32)ks[0] << 24)
+ | ((word32)ks[2] << 16)
+ | ((word32)ks[4] << 8)
+ | ((word32)ks[6]);
+ k_[2*i + 1] = ((word32)ks[1] << 24)
+ | ((word32)ks[3] << 16)
+ | ((word32)ks[5] << 8)
+ | ((word32)ks[7]);
+ }
+
+ // reverse key schedule order
+ if (dir == DECRYPTION)
+ for (i = 0; i < 16; i += 2) {
+ mySTL::swap(k_[i], k_[32 - 2 - i]);
+ mySTL::swap(k_[i+1], k_[32 - 1 - i]);
+ }
+
+}
+
+static inline void IPERM(word32& left, word32& right)
+{
+ word32 work;
+
+ right = rotlFixed(right, 4U);
+ work = (left ^ right) & 0xf0f0f0f0;
+ left ^= work;
+ right = rotrFixed(right^work, 20U);
+ work = (left ^ right) & 0xffff0000;
+ left ^= work;
+ right = rotrFixed(right^work, 18U);
+ work = (left ^ right) & 0x33333333;
+ left ^= work;
+ right = rotrFixed(right^work, 6U);
+ work = (left ^ right) & 0x00ff00ff;
+ left ^= work;
+ right = rotlFixed(right^work, 9U);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left = rotlFixed(left^work, 1U);
+ right ^= work;
+}
+
+static inline void FPERM(word32& left, word32& right)
+{
+ word32 work;
+
+ right = rotrFixed(right, 1U);
+ work = (left ^ right) & 0xaaaaaaaa;
+ right ^= work;
+ left = rotrFixed(left^work, 9U);
+ work = (left ^ right) & 0x00ff00ff;
+ right ^= work;
+ left = rotlFixed(left^work, 6U);
+ work = (left ^ right) & 0x33333333;
+ right ^= work;
+ left = rotlFixed(left^work, 18U);
+ work = (left ^ right) & 0xffff0000;
+ right ^= work;
+ left = rotlFixed(left^work, 20U);
+ work = (left ^ right) & 0xf0f0f0f0;
+ right ^= work;
+ left = rotrFixed(left^work, 4U);
+}
+
+const word32 Spbox[DES::BOXES][DES::BOX_SIZE] = {
+{
+0x01010400,0x00000000,0x00010000,0x01010404,
+0x01010004,0x00010404,0x00000004,0x00010000,
+0x00000400,0x01010400,0x01010404,0x00000400,
+0x01000404,0x01010004,0x01000000,0x00000004,
+0x00000404,0x01000400,0x01000400,0x00010400,
+0x00010400,0x01010000,0x01010000,0x01000404,
+0x00010004,0x01000004,0x01000004,0x00010004,
+0x00000000,0x00000404,0x00010404,0x01000000,
+0x00010000,0x01010404,0x00000004,0x01010000,
+0x01010400,0x01000000,0x01000000,0x00000400,
+0x01010004,0x00010000,0x00010400,0x01000004,
+0x00000400,0x00000004,0x01000404,0x00010404,
+0x01010404,0x00010004,0x01010000,0x01000404,
+0x01000004,0x00000404,0x00010404,0x01010400,
+0x00000404,0x01000400,0x01000400,0x00000000,
+0x00010004,0x00010400,0x00000000,0x01010004},
+{
+0x80108020,0x80008000,0x00008000,0x00108020,
+0x00100000,0x00000020,0x80100020,0x80008020,
+0x80000020,0x80108020,0x80108000,0x80000000,
+0x80008000,0x00100000,0x00000020,0x80100020,
+0x00108000,0x00100020,0x80008020,0x00000000,
+0x80000000,0x00008000,0x00108020,0x80100000,
+0x00100020,0x80000020,0x00000000,0x00108000,
+0x00008020,0x80108000,0x80100000,0x00008020,
+0x00000000,0x00108020,0x80100020,0x00100000,
+0x80008020,0x80100000,0x80108000,0x00008000,
+0x80100000,0x80008000,0x00000020,0x80108020,
+0x00108020,0x00000020,0x00008000,0x80000000,
+0x00008020,0x80108000,0x00100000,0x80000020,
+0x00100020,0x80008020,0x80000020,0x00100020,
+0x00108000,0x00000000,0x80008000,0x00008020,
+0x80000000,0x80100020,0x80108020,0x00108000},
+{
+0x00000208,0x08020200,0x00000000,0x08020008,
+0x08000200,0x00000000,0x00020208,0x08000200,
+0x00020008,0x08000008,0x08000008,0x00020000,
+0x08020208,0x00020008,0x08020000,0x00000208,
+0x08000000,0x00000008,0x08020200,0x00000200,
+0x00020200,0x08020000,0x08020008,0x00020208,
+0x08000208,0x00020200,0x00020000,0x08000208,
+0x00000008,0x08020208,0x00000200,0x08000000,
+0x08020200,0x08000000,0x00020008,0x00000208,
+0x00020000,0x08020200,0x08000200,0x00000000,
+0x00000200,0x00020008,0x08020208,0x08000200,
+0x08000008,0x00000200,0x00000000,0x08020008,
+0x08000208,0x00020000,0x08000000,0x08020208,
+0x00000008,0x00020208,0x00020200,0x08000008,
+0x08020000,0x08000208,0x00000208,0x08020000,
+0x00020208,0x00000008,0x08020008,0x00020200},
+{
+0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802080,0x00800081,0x00800001,0x00002001,
+0x00000000,0x00802000,0x00802000,0x00802081,
+0x00000081,0x00000000,0x00800080,0x00800001,
+0x00000001,0x00002000,0x00800000,0x00802001,
+0x00000080,0x00800000,0x00002001,0x00002080,
+0x00800081,0x00000001,0x00002080,0x00800080,
+0x00002000,0x00802080,0x00802081,0x00000081,
+0x00800080,0x00800001,0x00802000,0x00802081,
+0x00000081,0x00000000,0x00000000,0x00802000,
+0x00002080,0x00800080,0x00800081,0x00000001,
+0x00802001,0x00002081,0x00002081,0x00000080,
+0x00802081,0x00000081,0x00000001,0x00002000,
+0x00800001,0x00002001,0x00802080,0x00800081,
+0x00002001,0x00002080,0x00800000,0x00802001,
+0x00000080,0x00800000,0x00002000,0x00802080},
+{
+0x00000100,0x02080100,0x02080000,0x42000100,
+0x00080000,0x00000100,0x40000000,0x02080000,
+0x40080100,0x00080000,0x02000100,0x40080100,
+0x42000100,0x42080000,0x00080100,0x40000000,
+0x02000000,0x40080000,0x40080000,0x00000000,
+0x40000100,0x42080100,0x42080100,0x02000100,
+0x42080000,0x40000100,0x00000000,0x42000000,
+0x02080100,0x02000000,0x42000000,0x00080100,
+0x00080000,0x42000100,0x00000100,0x02000000,
+0x40000000,0x02080000,0x42000100,0x40080100,
+0x02000100,0x40000000,0x42080000,0x02080100,
+0x40080100,0x00000100,0x02000000,0x42080000,
+0x42080100,0x00080100,0x42000000,0x42080100,
+0x02080000,0x00000000,0x40080000,0x42000000,
+0x00080100,0x02000100,0x40000100,0x00080000,
+0x00000000,0x40080000,0x02080100,0x40000100},
+{
+0x20000010,0x20400000,0x00004000,0x20404010,
+0x20400000,0x00000010,0x20404010,0x00400000,
+0x20004000,0x00404010,0x00400000,0x20000010,
+0x00400010,0x20004000,0x20000000,0x00004010,
+0x00000000,0x00400010,0x20004010,0x00004000,
+0x00404000,0x20004010,0x00000010,0x20400010,
+0x20400010,0x00000000,0x00404010,0x20404000,
+0x00004010,0x00404000,0x20404000,0x20000000,
+0x20004000,0x00000010,0x20400010,0x00404000,
+0x20404010,0x00400000,0x00004010,0x20000010,
+0x00400000,0x20004000,0x20000000,0x00004010,
+0x20000010,0x20404010,0x00404000,0x20400000,
+0x00404010,0x20404000,0x00000000,0x20400010,
+0x00000010,0x00004000,0x20400000,0x00404010,
+0x00004000,0x00400010,0x20004010,0x00000000,
+0x20404000,0x20000000,0x00400010,0x20004010},
+{
+0x00200000,0x04200002,0x04000802,0x00000000,
+0x00000800,0x04000802,0x00200802,0x04200800,
+0x04200802,0x00200000,0x00000000,0x04000002,
+0x00000002,0x04000000,0x04200002,0x00000802,
+0x04000800,0x00200802,0x00200002,0x04000800,
+0x04000002,0x04200000,0x04200800,0x00200002,
+0x04200000,0x00000800,0x00000802,0x04200802,
+0x00200800,0x00000002,0x04000000,0x00200800,
+0x04000000,0x00200800,0x00200000,0x04000802,
+0x04000802,0x04200002,0x04200002,0x00000002,
+0x00200002,0x04000000,0x04000800,0x00200000,
+0x04200800,0x00000802,0x00200802,0x04200800,
+0x00000802,0x04000002,0x04200802,0x04200000,
+0x00200800,0x00000000,0x00000002,0x04200802,
+0x00000000,0x00200802,0x04200000,0x00000800,
+0x04000002,0x04000800,0x00000800,0x00200002},
+{
+0x10001040,0x00001000,0x00040000,0x10041040,
+0x10000000,0x10001040,0x00000040,0x10000000,
+0x00040040,0x10040000,0x10041040,0x00041000,
+0x10041000,0x00041040,0x00001000,0x00000040,
+0x10040000,0x10000040,0x10001000,0x00001040,
+0x00041000,0x00040040,0x10040040,0x10041000,
+0x00001040,0x00000000,0x00000000,0x10040040,
+0x10000040,0x10001000,0x00041040,0x00040000,
+0x00041040,0x00040000,0x10041000,0x00001000,
+0x00000040,0x10040040,0x00001000,0x00041040,
+0x10001000,0x00000040,0x10000040,0x10040000,
+0x10040040,0x10000000,0x00040000,0x10001040,
+0x00000000,0x10041040,0x00040040,0x10000040,
+0x10040000,0x10001000,0x10001040,0x00000000,
+0x10041040,0x00041000,0x00041000,0x00001040,
+0x00001040,0x00040040,0x10000000,0x10041000}
+};
+
+
+
+void DES::RawProcessBlock(word32& lIn, word32& rIn) const
+{
+ word32 l = lIn, r = rIn;
+ const word32* kptr = k_;
+
+ for (unsigned i=0; i<8; i++)
+ {
+ word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ kptr[4*i+1];
+ l ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ kptr[4*i+3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+ }
+
+ lIn = l; rIn = r;
+}
+
+
+void DES_BASE::Process(byte* out, const byte* in, word32 sz)
+{
+ if (mode_ == ECB)
+ ECB_Process(out, in, sz);
+ else if (mode_ == CBC)
+ if (dir_ == ENCRYPTION)
+ CBC_Encrypt(out, in, sz);
+ else
+ CBC_Decrypt(out, in, sz);
+}
+
+
+
+typedef BlockGetAndPut<word32, BigEndian> Block;
+
+
+void DES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+
+ const word32* kptr = k_;
+
+ for (unsigned i = 0; i < 8; i++)
+ {
+ word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
+ l ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = r ^ kptr[4*i+1];
+ l ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+
+ work = rotrFixed(l, 4U) ^ kptr[4*i+2];
+ r ^= Spbox[6][(work) & 0x3f]
+ ^ Spbox[4][(work >> 8) & 0x3f]
+ ^ Spbox[2][(work >> 16) & 0x3f]
+ ^ Spbox[0][(work >> 24) & 0x3f];
+ work = l ^ kptr[4*i+3];
+ r ^= Spbox[7][(work) & 0x3f]
+ ^ Spbox[5][(work >> 8) & 0x3f]
+ ^ Spbox[3][(work >> 16) & 0x3f]
+ ^ Spbox[1][(work >> 24) & 0x3f];
+ }
+
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+void DES_EDE2::SetKey(const byte* key, word32 sz, CipherDir dir)
+{
+ des1_.SetKey(key, sz, dir);
+ des2_.SetKey(key + 8, sz, ReverseDir(dir));
+}
+
+
+void DES_EDE2::ProcessAndXorBlock(const byte* in, const byte* xOr,
+ byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+ des1_.RawProcessBlock(l, r);
+ des2_.RawProcessBlock(r, l);
+ des1_.RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+void DES_EDE3::SetKey(const byte* key, word32 sz, CipherDir dir)
+{
+ des1_.SetKey(key+(dir==ENCRYPTION?0:2*8), sz, dir);
+ des2_.SetKey(key+8, sz, ReverseDir(dir));
+ des3_.SetKey(key+(dir==DECRYPTION?0:2*8), sz, dir);
+}
+
+void DES_EDE3::ProcessAndXorBlock(const byte* in, const byte* xOr,
+ byte* out) const
+{
+ word32 l,r;
+ Block::Get(in)(l)(r);
+ IPERM(l,r);
+ des1_.RawProcessBlock(l, r);
+ des2_.RawProcessBlock(r, l);
+ des3_.RawProcessBlock(l, r);
+ FPERM(l,r);
+ Block::Put(xOr, out)(r)(l);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/dh.cpp b/extra/yassl/taocrypt/src/dh.cpp
new file mode 100644
index 00000000000..e5a6a562c52
--- /dev/null
+++ b/extra/yassl/taocrypt/src/dh.cpp
@@ -0,0 +1,85 @@
+/* dh.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* dh.cpp implements Diffie-Hellman support
+*/
+
+#include "runtime.hpp"
+#include "dh.hpp"
+#include "asn.hpp"
+#include <cmath>
+
+namespace TaoCrypt {
+
+
+// Generate a DH Key Pair
+void DH::GenerateKeyPair(RandomNumberGenerator& rng, byte* priv, byte* pub)
+{
+ GeneratePrivate(rng, priv);
+ GeneratePublic(priv, pub);
+}
+
+
+// Generate private value
+void DH::GeneratePrivate(RandomNumberGenerator& rng, byte* priv)
+{
+ Integer x(rng, Integer::One(), p_ - 1);
+ x.Encode(priv, p_.ByteCount());
+}
+
+
+// Generate public value
+void DH::GeneratePublic(const byte* priv, byte* pub)
+{
+ const word32 bc(p_.ByteCount());
+ Integer x(priv, bc);
+ Integer y(a_exp_b_mod_c(g_, x, p_));
+ y.Encode(pub, bc);
+}
+
+
+// Generate Agreement
+void DH::Agree(byte* agree, const byte* priv, const byte* otherPub)
+{
+ const word32 bc(p_.ByteCount());
+ Integer x(priv, bc);
+ Integer y(otherPub, bc);
+
+ Integer z(a_exp_b_mod_c(y, x, p_));
+ z.Encode(agree, bc);
+}
+
+
+DH::DH(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DH::Initialize(Source& source)
+{
+ DH_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/dsa.cpp b/extra/yassl/taocrypt/src/dsa.cpp
new file mode 100644
index 00000000000..4716ebb22df
--- /dev/null
+++ b/extra/yassl/taocrypt/src/dsa.cpp
@@ -0,0 +1,277 @@
+/* dsa.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "runtime.hpp"
+#include "dsa.hpp"
+#include "sha.hpp"
+#include "asn.hpp"
+#include "modarith.hpp"
+#include "stdexcept.hpp"
+
+#include "algebra.cpp" // for GCC 3.2 on aix ?
+
+
+namespace TaoCrypt {
+
+
+void DSA_PublicKey::Swap(DSA_PublicKey& other)
+{
+ p_.Swap(other.p_);
+ q_.Swap(other.q_);
+ g_.Swap(other.g_);
+ y_.Swap(other.y_);
+}
+
+
+DSA_PublicKey::DSA_PublicKey(const DSA_PublicKey& other)
+ : p_(other.p_), q_(other.q_), g_(other.g_), y_(other.y_)
+{}
+
+
+DSA_PublicKey& DSA_PublicKey::operator=(const DSA_PublicKey& that)
+{
+ DSA_PublicKey tmp(that);
+ Swap(tmp);
+ return *this;
+}
+
+
+DSA_PublicKey::DSA_PublicKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DSA_PublicKey::Initialize(Source& source)
+{
+ DSA_Public_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void DSA_PublicKey::Initialize(const Integer& p, const Integer& q,
+ const Integer& g, const Integer& y)
+{
+ p_ = p;
+ q_ = q;
+ g_ = g;
+ y_ = y;
+}
+
+
+const Integer& DSA_PublicKey::GetModulus() const
+{
+ return p_;
+}
+
+const Integer& DSA_PublicKey::GetSubGroupOrder() const
+{
+ return q_;
+}
+
+
+const Integer& DSA_PublicKey::GetSubGroupGenerator() const
+{
+ return g_;
+}
+
+
+const Integer& DSA_PublicKey::GetPublicPart() const
+{
+ return y_;
+}
+
+
+void DSA_PublicKey::SetModulus(const Integer& p)
+{
+ p_ = p;
+}
+
+
+void DSA_PublicKey::SetSubGroupOrder(const Integer& q)
+{
+ q_ = q;
+}
+
+
+void DSA_PublicKey::SetSubGroupGenerator(const Integer& g)
+{
+ g_ = g;
+}
+
+
+void DSA_PublicKey::SetPublicPart(const Integer& y)
+{
+ y_ = y;
+}
+
+
+word32 DSA_PublicKey::SignatureLength() const
+{
+ return GetSubGroupOrder().ByteCount() * 2; // r and s
+}
+
+
+
+DSA_PrivateKey::DSA_PrivateKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void DSA_PrivateKey::Initialize(Source& source)
+{
+ DSA_Private_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void DSA_PrivateKey::Initialize(const Integer& p, const Integer& q,
+ const Integer& g, const Integer& y,
+ const Integer& x)
+{
+ DSA_PublicKey::Initialize(p, q, g, y);
+ x_ = x;
+}
+
+
+const Integer& DSA_PrivateKey::GetPrivatePart() const
+{
+ return x_;
+}
+
+
+void DSA_PrivateKey::SetPrivatePart(const Integer& x)
+{
+ x_ = x;
+}
+
+
+DSA_Signer::DSA_Signer(const DSA_PrivateKey& key)
+ : key_(key)
+{}
+
+
+word32 DSA_Signer::Sign(const byte* sha_digest, byte* sig,
+ RandomNumberGenerator& rng)
+{
+ const Integer& p = key_.GetModulus();
+ const Integer& q = key_.GetSubGroupOrder();
+ const Integer& g = key_.GetSubGroupGenerator();
+ const Integer& x = key_.GetPrivatePart();
+
+ Integer k(rng, 1, q - 1);
+
+ r_ = a_exp_b_mod_c(g, k, p);
+ r_ %= q;
+
+ Integer H(sha_digest, SHA::DIGEST_SIZE); // sha Hash(m)
+
+ Integer kInv = k.InverseMod(q);
+ s_ = (kInv * (H + x*r_)) % q;
+
+ assert(!!r_ && !!s_);
+
+ int rSz = r_.ByteCount();
+
+ if (rSz == 19) {
+ sig[0] = 0;
+ sig++;
+ }
+
+ r_.Encode(sig, rSz);
+
+ int sSz = s_.ByteCount();
+
+ if (sSz == 19) {
+ sig[rSz] = 0;
+ sig++;
+ }
+
+ s_.Encode(sig + rSz, sSz);
+
+ return 40;
+}
+
+
+DSA_Verifier::DSA_Verifier(const DSA_PublicKey& key)
+ : key_(key)
+{}
+
+
+bool DSA_Verifier::Verify(const byte* sha_digest, const byte* sig)
+{
+ const Integer& p = key_.GetModulus();
+ const Integer& q = key_.GetSubGroupOrder();
+ const Integer& g = key_.GetSubGroupGenerator();
+ const Integer& y = key_.GetPublicPart();
+
+ int sz = q.ByteCount();
+
+ r_.Decode(sig, sz);
+ s_.Decode(sig + sz, sz);
+
+ if (r_ >= q || r_ < 1 || s_ >= q || s_ < 1)
+ return false;
+
+ Integer H(sha_digest, SHA::DIGEST_SIZE); // sha Hash(m)
+
+ Integer w = s_.InverseMod(q);
+ Integer u1 = (H * w) % q;
+ Integer u2 = (r_ * w) % q;
+
+ // verify r == ((g^u1 * y^u2) mod p) mod q
+ ModularArithmetic ma(p);
+ Integer v = ma.CascadeExponentiate(g, u1, y, u2);
+ v %= q;
+
+ return r_ == v;
+}
+
+
+
+
+const Integer& DSA_Signer::GetR() const
+{
+ return r_;
+}
+
+
+const Integer& DSA_Signer::GetS() const
+{
+ return s_;
+}
+
+
+const Integer& DSA_Verifier::GetR() const
+{
+ return r_;
+}
+
+
+const Integer& DSA_Verifier::GetS() const
+{
+ return s_;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/file.cpp b/extra/yassl/taocrypt/src/file.cpp
new file mode 100644
index 00000000000..4d48b9e7bca
--- /dev/null
+++ b/extra/yassl/taocrypt/src/file.cpp
@@ -0,0 +1,118 @@
+/* file.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* file.cpp implements File Sources and Sinks
+*/
+
+#include "runtime.hpp"
+#include "file.hpp"
+
+
+namespace TaoCrypt {
+
+
+FileSource::FileSource(const char* fname, Source& source)
+{
+ file_ = fopen(fname, "rb");
+ if (file_) get(source);
+}
+
+
+FileSource::~FileSource()
+{
+ if (file_)
+ fclose(file_);
+}
+
+
+
+// return size of source from beginning or current position
+word32 FileSource::size(bool use_current)
+{
+ long current = ftell(file_);
+ long begin = current;
+
+ if (!use_current) {
+ fseek(file_, 0, SEEK_SET);
+ begin = ftell(file_);
+ }
+
+ fseek(file_, 0, SEEK_END);
+ long end = ftell(file_);
+
+ fseek(file_, current, SEEK_SET);
+
+ return end - begin;
+}
+
+
+word32 FileSource::size_left()
+{
+ return size(true);
+}
+
+
+// fill file source from source
+word32 FileSource::get(Source& source)
+{
+ word32 sz(size());
+ if (source.size() < sz)
+ source.grow(sz);
+
+ size_t bytes = fread(source.buffer_.get_buffer(), 1, sz, file_);
+
+ if (bytes == 1)
+ return sz;
+ else
+ return 0;
+}
+
+
+FileSink::FileSink(const char* fname, Source& source)
+{
+ file_ = fopen(fname, "wb");
+ if (file_) put(source);
+}
+
+
+FileSink::~FileSink()
+{
+ if (file_)
+ fclose(file_);
+}
+
+
+// fill source from file sink
+void FileSink::put(Source& source)
+{
+ fwrite(source.get_buffer(), 1, source.size(), file_);
+}
+
+
+// swap with other and reset to beginning
+void Source::reset(ByteBlock& otherBlock)
+{
+ buffer_.Swap(otherBlock);
+ current_ = 0;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/hash.cpp b/extra/yassl/taocrypt/src/hash.cpp
new file mode 100644
index 00000000000..09b9fe52b2b
--- /dev/null
+++ b/extra/yassl/taocrypt/src/hash.cpp
@@ -0,0 +1,88 @@
+/* hash.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* hash.cpp implements a base for digest types
+*/
+
+#include "runtime.hpp"
+#include <string.h>
+
+#include "hash.hpp"
+
+
+namespace TaoCrypt {
+
+
+// Update digest with data of size len, do in blocks
+void HASHwithTransform::Update(const byte* data, word32 len)
+{
+ // do block size increments
+ word32 blockSz = getBlockSize();
+ while (len) {
+ word32 add = min(len, blockSz - buffLen_);
+ memcpy(&buffer_[buffLen_], data, add);
+
+ buffLen_ += add;
+ data += add;
+ len -= add;
+
+ if (buffLen_ == blockSz) {
+ ByteReverseIf(buffer_, buffer_, blockSz, getByteOrder());
+ Transform();
+ }
+ }
+}
+
+
+// Final process, place digest in hash
+void HASHwithTransform::Final(byte* hash)
+{
+ word32 blockSz = getBlockSize();
+ word32 digestSz = getDigestSize();
+ word32 padSz = getPadSize();
+ ByteOrder order = getByteOrder();
+ word32 prePadLen = length_ + buffLen_ * 8; // in bits
+
+ buffer_[buffLen_++] = 0x80; // add 1
+
+ // pad with zeros
+ if (buffLen_ > padSz) {
+ while (buffLen_ < blockSz) buffer_[buffLen_++] = 0;
+ ByteReverseIf(buffer_, buffer_, blockSz, order);
+ Transform();
+ }
+ while (buffLen_ < padSz) buffer_[buffLen_++] = 0;
+
+ ByteReverseIf(buffer_, buffer_, blockSz, order);
+
+ word32 hiSize = 0; // for future 64 bit length TODO:
+ memcpy(&buffer_[padSz], order ? &hiSize : &prePadLen, sizeof(prePadLen));
+ memcpy(&buffer_[padSz+4], order ? &prePadLen : &hiSize, sizeof(prePadLen));
+
+
+ Transform();
+ ByteReverseIf(digest_, digest_, digestSz, order);
+ memcpy(hash, digest_, digestSz);
+
+ Init(); // reset state
+}
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp
new file mode 100644
index 00000000000..513bf3e6b20
--- /dev/null
+++ b/extra/yassl/taocrypt/src/integer.cpp
@@ -0,0 +1,4174 @@
+/* integer.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+
+/* based on Wei Dai's integer.cpp from CryptoPP */
+
+#ifdef _MSC_VER
+ // 4250: dominance
+ // 4660: explicitly instantiating a class already implicitly instantiated
+ // 4661: no suitable definition provided for explicit template request
+ // 4786: identifer was truncated in debug information
+ // 4355: 'this' : used in base member initializer list
+# pragma warning(disable: 4250 4660 4661 4786 4355)
+#endif
+
+#include "runtime.hpp"
+#include "integer.hpp"
+#include "modarith.hpp"
+#include "asn.hpp"
+#include "stdexcept.hpp"
+
+#include "algebra.cpp"
+
+
+#ifdef __DECCXX
+ #include <c_asm.h> // for asm multiply overflow
+#endif
+
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ #ifdef __GNUC__
+ #include <xmmintrin.h>
+ #include <signal.h>
+ #include <setjmp.h>
+ #ifdef TAOCRYPT_MEMALIGN_AVAILABLE
+ #include <malloc.h>
+ #else
+ #include <stdlib.h>
+ #endif
+ #else
+ #include <emmintrin.h>
+ #endif
+#elif defined(_MSC_VER) && defined(_M_IX86)
+ #pragma message("You do not seem to have the Visual C++ Processor Pack ")
+ #pragma message("installed, so use of SSE2 intrinsics will be disabled.")
+#elif defined(__GNUC__) && defined(__i386__)
+/* #warning You do not have GCC 3.3 or later, or did not specify the -msse2 \
+ compiler option. Use of SSE2 intrinsics will be disabled.
+*/
+#endif
+
+
+namespace TaoCrypt {
+
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+
+template <class T>
+CPP_TYPENAME AllocatorBase<T>::pointer AlignedAllocator<T>::allocate(
+ size_type n, const void *)
+{
+ CheckSize(n);
+ if (n == 0)
+ return 0;
+ if (n >= 4)
+ {
+ void* p;
+ #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE
+ while (!(p = _mm_malloc(sizeof(T)*n, 16)))
+ #elif defined(TAOCRYPT_MEMALIGN_AVAILABLE)
+ while (!(p = memalign(16, sizeof(T)*n)))
+ #elif defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16)
+ while (!(p = malloc(sizeof(T)*n)))
+ #else
+ while (!(p = (byte *)malloc(sizeof(T)*n + 8)))
+ // assume malloc alignment is at least 8
+ #endif
+ CallNewHandler();
+
+ #ifdef TAOCRYPT_NO_ALIGNED_ALLOC
+ assert(m_pBlock == 0);
+ m_pBlock = p;
+ if (!IsAlignedOn(p, 16))
+ {
+ assert(IsAlignedOn(p, 8));
+ p = (byte *)p + 8;
+ }
+ #endif
+
+ assert(IsAlignedOn(p, 16));
+ return (T*)p;
+ }
+ return new (tc) T[n];
+}
+
+
+template <class T>
+void AlignedAllocator<T>::deallocate(void* p, size_type n)
+{
+ memset(p, 0, n*sizeof(T));
+ if (n >= 4)
+ {
+ #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE
+ _mm_free(p);
+ #elif defined(TAOCRYPT_NO_ALIGNED_ALLOC)
+ assert(m_pBlock == p || (byte*)m_pBlock+8 == p);
+ free(m_pBlock);
+ m_pBlock = 0;
+ #else
+ free(p);
+ #endif
+ }
+ else
+ delete [] (T *)p;
+}
+
+#endif // SSE2
+
+
+// ******** start of integer needs
+
+// start 5.2.1 adds DWord and Word ********
+
+// ********************************************************
+
+class DWord {
+public:
+DWord() {}
+
+#ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ explicit DWord(word low)
+ {
+ whole_ = low;
+ }
+#else
+ explicit DWord(word low)
+ {
+ halfs_.low = low;
+ halfs_.high = 0;
+ }
+#endif
+
+ DWord(word low, word high)
+ {
+ halfs_.low = low;
+ halfs_.high = high;
+ }
+
+ static DWord Multiply(word a, word b)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = (dword)a * b;
+ #elif defined(__alpha__)
+ r.halfs_.low = a*b;
+ #ifdef __GNUC__
+ __asm__("umulh %1,%2,%0" : "=r" (r.halfs_.high)
+ : "r" (a), "r" (b));
+ #elif defined(__DECCXX)
+ r.halfs_.high = asm("umulh %a0, %a1, %v0", a, b);
+ #else
+ #error unsupported alpha compiler for asm multiply overflow
+ #endif
+ #elif defined(__ia64__)
+ r.halfs_.low = a*b;
+ __asm__("xmpy.hu %0=%1,%2" : "=f" (r.halfs_.high)
+ : "f" (a), "f" (b));
+ #elif defined(_ARCH_PPC64)
+ r.halfs_.low = a*b;
+ __asm__("mulhdu %0,%1,%2" : "=r" (r.halfs_.high)
+ : "r" (a), "r" (b) : "cc");
+ #elif defined(__x86_64__)
+ __asm__("mulq %3" : "=d" (r.halfs_.high), "=a" (r.halfs_.low) :
+ "a" (a), "rm" (b) : "cc");
+ #elif defined(__mips64)
+ __asm__("dmultu %2,%3" : "=h" (r.halfs_.high), "=l" (r.halfs_.low)
+ : "r" (a), "r" (b));
+ #elif defined(_M_IX86)
+ // for testing
+ word64 t = (word64)a * b;
+ r.halfs_.high = ((word32 *)(&t))[1];
+ r.halfs_.low = (word32)t;
+ #else
+ #error can not implement DWord
+ #endif
+ return r;
+ }
+
+ static DWord MultiplyAndAdd(word a, word b, word c)
+ {
+ DWord r = Multiply(a, b);
+ return r += c;
+ }
+
+ DWord & operator+=(word a)
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ whole_ = whole_ + a;
+ #else
+ halfs_.low += a;
+ halfs_.high += (halfs_.low < a);
+ #endif
+ return *this;
+ }
+
+ DWord operator+(word a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ + a;
+ #else
+ r.halfs_.low = halfs_.low + a;
+ r.halfs_.high = halfs_.high + (r.halfs_.low < a);
+ #endif
+ return r;
+ }
+
+ DWord operator-(DWord a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ - a.whole_;
+ #else
+ r.halfs_.low = halfs_.low - a.halfs_.low;
+ r.halfs_.high = halfs_.high - a.halfs_.high -
+ (r.halfs_.low > halfs_.low);
+ #endif
+ return r;
+ }
+
+ DWord operator-(word a)
+ {
+ DWord r;
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ r.whole_ = whole_ - a;
+ #else
+ r.halfs_.low = halfs_.low - a;
+ r.halfs_.high = halfs_.high - (r.halfs_.low > halfs_.low);
+ #endif
+ return r;
+ }
+
+ // returns quotient, which must fit in a word
+ word operator/(word divisor);
+
+ word operator%(word a);
+
+ bool operator!() const
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return !whole_;
+ #else
+ return !halfs_.high && !halfs_.low;
+ #endif
+ }
+
+ word GetLowHalf() const {return halfs_.low;}
+ word GetHighHalf() const {return halfs_.high;}
+ word GetHighHalfAsBorrow() const {return 0-halfs_.high;}
+
+private:
+ union
+ {
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ dword whole_;
+ #endif
+ struct
+ {
+ #ifdef LITTLE_ENDIAN_ORDER
+ word low;
+ word high;
+ #else
+ word high;
+ word low;
+ #endif
+ } halfs_;
+ };
+};
+
+
+class Word {
+public:
+ Word() {}
+
+ Word(word value)
+ {
+ whole_ = value;
+ }
+
+ Word(hword low, hword high)
+ {
+ whole_ = low | (word(high) << (WORD_BITS/2));
+ }
+
+ static Word Multiply(hword a, hword b)
+ {
+ Word r;
+ r.whole_ = (word)a * b;
+ return r;
+ }
+
+ Word operator-(Word a)
+ {
+ Word r;
+ r.whole_ = whole_ - a.whole_;
+ return r;
+ }
+
+ Word operator-(hword a)
+ {
+ Word r;
+ r.whole_ = whole_ - a;
+ return r;
+ }
+
+ // returns quotient, which must fit in a word
+ hword operator/(hword divisor)
+ {
+ return hword(whole_ / divisor);
+ }
+
+ bool operator!() const
+ {
+ return !whole_;
+ }
+
+ word GetWhole() const {return whole_;}
+ hword GetLowHalf() const {return hword(whole_);}
+ hword GetHighHalf() const {return hword(whole_>>(WORD_BITS/2));}
+ hword GetHighHalfAsBorrow() const {return 0-hword(whole_>>(WORD_BITS/2));}
+
+private:
+ word whole_;
+};
+
+
+// dummy is VC60 compiler bug workaround
+// do a 3 word by 2 word divide, returns quotient and leaves remainder in A
+template <class S, class D>
+S DivideThreeWordsByTwo(S* A, S B0, S B1, D* dummy_VC6_WorkAround = 0)
+{
+ // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S
+ assert(A[2] < B1 || (A[2]==B1 && A[1] < B0));
+
+ // estimate the quotient: do a 2 S by 1 S divide
+ S Q;
+ if (S(B1+1) == 0)
+ Q = A[2];
+ else
+ Q = D(A[1], A[2]) / S(B1+1);
+
+ // now subtract Q*B from A
+ D p = D::Multiply(B0, Q);
+ D u = (D) A[0] - p.GetLowHalf();
+ A[0] = u.GetLowHalf();
+ u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() -
+ D::Multiply(B1, Q);
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+
+ // Q <= actual quotient, so fix it
+ while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0))
+ {
+ u = (D) A[0] - B0;
+ A[0] = u.GetLowHalf();
+ u = (D) A[1] - B1 - u.GetHighHalfAsBorrow();
+ A[1] = u.GetLowHalf();
+ A[2] += u.GetHighHalf();
+ Q++;
+ assert(Q); // shouldn't overflow
+ }
+
+ return Q;
+}
+
+// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1
+template <class S, class D>
+inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B)
+{
+ if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS)
+ return D(Ah.GetLowHalf(), Ah.GetHighHalf());
+ else
+ {
+ S Q[2];
+ T[0] = Al.GetLowHalf();
+ T[1] = Al.GetHighHalf();
+ T[2] = Ah.GetLowHalf();
+ T[3] = Ah.GetHighHalf();
+ Q[1] = DivideThreeWordsByTwo<S, D>(T+1, B.GetLowHalf(),
+ B.GetHighHalf());
+ Q[0] = DivideThreeWordsByTwo<S, D>(T, B.GetLowHalf(), B.GetHighHalf());
+ return D(Q[0], Q[1]);
+ }
+}
+
+
+// returns quotient, which must fit in a word
+inline word DWord::operator/(word a)
+{
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return word(whole_ / a);
+ #else
+ hword r[4];
+ return DivideFourWordsByTwo<hword, Word>(r, halfs_.low,
+ halfs_.high, a).GetWhole();
+ #endif
+}
+
+inline word DWord::operator%(word a)
+{
+ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE
+ return word(whole_ % a);
+ #else
+ if (a < (word(1) << (WORD_BITS/2)))
+ {
+ hword h = hword(a);
+ word r = halfs_.high % h;
+ r = ((halfs_.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h;
+ return hword((hword(halfs_.low) + (r << (WORD_BITS/2))) % h);
+ }
+ else
+ {
+ hword r[4];
+ DivideFourWordsByTwo<hword, Word>(r, halfs_.low, halfs_.high, a);
+ return Word(r[0], r[1]).GetWhole();
+ }
+ #endif
+}
+
+
+
+// end 5.2.1 DWord and Word adds
+
+
+
+
+
+static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8};
+
+static inline unsigned int RoundupSize(unsigned int n)
+{
+ if (n<=8)
+ return RoundupSizeTable[n];
+ else if (n<=16)
+ return 16;
+ else if (n<=32)
+ return 32;
+ else if (n<=64)
+ return 64;
+ else return 1U << BitPrecision(n-1);
+}
+
+
+template <class T>
+static Integer StringToInteger(const T *str)
+{
+ word radix;
+
+ unsigned int length;
+ for (length = 0; str[length] != 0; length++) {}
+
+ Integer v;
+
+ if (length == 0)
+ return v;
+
+ switch (str[length-1])
+ {
+ case 'h':
+ case 'H':
+ radix=16;
+ break;
+ case 'o':
+ case 'O':
+ radix=8;
+ break;
+ case 'b':
+ case 'B':
+ radix=2;
+ break;
+ default:
+ radix=10;
+ }
+
+ if (length > 2 && str[0] == '0' && str[1] == 'x')
+ radix = 16;
+
+ for (unsigned i=0; i<length; i++)
+ {
+ word digit;
+
+ if (str[i] >= '0' && str[i] <= '9')
+ digit = str[i] - '0';
+ else if (str[i] >= 'A' && str[i] <= 'F')
+ digit = str[i] - 'A' + 10;
+ else if (str[i] >= 'a' && str[i] <= 'f')
+ digit = str[i] - 'a' + 10;
+ else
+ digit = radix;
+
+ if (digit < radix)
+ {
+ v *= radix;
+ v += digit;
+ }
+ }
+
+ if (str[0] == '-')
+ v.Negate();
+
+ return v;
+}
+
+static int Compare(const word *A, const word *B, unsigned int N)
+{
+ while (N--)
+ if (A[N] > B[N])
+ return 1;
+ else if (A[N] < B[N])
+ return -1;
+
+ return 0;
+}
+
+static word Increment(word *A, unsigned int N, word B=1)
+{
+ assert(N);
+ word t = A[0];
+ A[0] = t+B;
+ if (A[0] >= t)
+ return 0;
+ for (unsigned i=1; i<N; i++)
+ if (++A[i])
+ return 0;
+ return 1;
+}
+
+static word Decrement(word *A, unsigned int N, word B=1)
+{
+ assert(N);
+ word t = A[0];
+ A[0] = t-B;
+ if (A[0] <= t)
+ return 0;
+ for (unsigned i=1; i<N; i++)
+ if (A[i]--)
+ return 0;
+ return 1;
+}
+
+static void TwosComplement(word *A, unsigned int N)
+{
+ Decrement(A, N);
+ for (unsigned i=0; i<N; i++)
+ A[i] = ~A[i];
+}
+
+
+static word LinearMultiply(word *C, const word *A, word B, unsigned int N)
+{
+ word carry=0;
+ for(unsigned i=0; i<N; i++)
+ {
+ DWord p = DWord::MultiplyAndAdd(A[i], B, carry);
+ C[i] = p.GetLowHalf();
+ carry = p.GetHighHalf();
+ }
+ return carry;
+}
+
+
+static word AtomicInverseModPower2(word A)
+{
+ assert(A%2==1);
+
+ word R=A%8;
+
+ for (unsigned i=3; i<WORD_BITS; i*=2)
+ R = R*(2-R*A);
+
+ assert(R*A==1);
+ return R;
+}
+
+
+// ********************************************************
+
+class Portable
+{
+public:
+ static word Add(word *C, const word *A, const word *B, unsigned int N);
+ static word Subtract(word *C, const word *A, const word*B, unsigned int N);
+
+ static inline void Multiply2(word *C, const word *A, const word *B);
+ static inline word Multiply2Add(word *C, const word *A, const word *B);
+ static void Multiply4(word *C, const word *A, const word *B);
+ static void Multiply8(word *C, const word *A, const word *B);
+ static inline unsigned int MultiplyRecursionLimit() {return 8;}
+
+ static inline void Multiply2Bottom(word *C, const word *A, const word *B);
+ static void Multiply4Bottom(word *C, const word *A, const word *B);
+ static void Multiply8Bottom(word *C, const word *A, const word *B);
+ static inline unsigned int MultiplyBottomRecursionLimit() {return 8;}
+
+ static void Square2(word *R, const word *A);
+ static void Square4(word *R, const word *A);
+ static void Square8(word *R, const word *A) {assert(false);}
+ static inline unsigned int SquareRecursionLimit() {return 4;}
+};
+
+word Portable::Add(word *C, const word *A, const word *B, unsigned int N)
+{
+ assert (N%2 == 0);
+
+ DWord u(0, 0);
+ for (unsigned int i = 0; i < N; i+=2)
+ {
+ u = DWord(A[i]) + B[i] + u.GetHighHalf();
+ C[i] = u.GetLowHalf();
+ u = DWord(A[i+1]) + B[i+1] + u.GetHighHalf();
+ C[i+1] = u.GetLowHalf();
+ }
+ return u.GetHighHalf();
+}
+
+word Portable::Subtract(word *C, const word *A, const word *B, unsigned int N)
+{
+ assert (N%2 == 0);
+
+ DWord u(0, 0);
+ for (unsigned int i = 0; i < N; i+=2)
+ {
+ u = (DWord) A[i] - B[i] - u.GetHighHalfAsBorrow();
+ C[i] = u.GetLowHalf();
+ u = (DWord) A[i+1] - B[i+1] - u.GetHighHalfAsBorrow();
+ C[i+1] = u.GetLowHalf();
+ }
+ return 0-u.GetHighHalf();
+}
+
+void Portable::Multiply2(word *C, const word *A, const word *B)
+{
+/*
+ word s;
+ dword d;
+
+ if (A1 >= A0)
+ if (B0 >= B1)
+ {
+ s = 0;
+ d = (dword)(A1-A0)*(B0-B1);
+ }
+ else
+ {
+ s = (A1-A0);
+ d = (dword)s*(word)(B0-B1);
+ }
+ else
+ if (B0 > B1)
+ {
+ s = (B0-B1);
+ d = (word)(A1-A0)*(dword)s;
+ }
+ else
+ {
+ s = 0;
+ d = (dword)(A0-A1)*(B1-B0);
+ }
+*/
+ // this segment is the branchless equivalent of above
+ word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]};
+ unsigned int ai = A[1] < A[0];
+ unsigned int bi = B[0] < B[1];
+ unsigned int di = ai & bi;
+ DWord d = DWord::Multiply(D[di], D[di+2]);
+ D[1] = D[3] = 0;
+ unsigned int si = ai + !bi;
+ word s = D[si];
+
+ DWord A0B0 = DWord::Multiply(A[0], B[0]);
+ C[0] = A0B0.GetLowHalf();
+
+ DWord A1B1 = DWord::Multiply(A[1], B[1]);
+ DWord t = (DWord) A0B0.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf()
+ + A1B1.GetLowHalf();
+ C[1] = t.GetLowHalf();
+
+ t = A1B1 + t.GetHighHalf() + A0B0.GetHighHalf() + d.GetHighHalf()
+ + A1B1.GetHighHalf() - s;
+ C[2] = t.GetLowHalf();
+ C[3] = t.GetHighHalf();
+}
+
+inline void Portable::Multiply2Bottom(word *C, const word *A, const word *B)
+{
+ DWord t = DWord::Multiply(A[0], B[0]);
+ C[0] = t.GetLowHalf();
+ C[1] = t.GetHighHalf() + A[0]*B[1] + A[1]*B[0];
+}
+
+word Portable::Multiply2Add(word *C, const word *A, const word *B)
+{
+ word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]};
+ unsigned int ai = A[1] < A[0];
+ unsigned int bi = B[0] < B[1];
+ unsigned int di = ai & bi;
+ DWord d = DWord::Multiply(D[di], D[di+2]);
+ D[1] = D[3] = 0;
+ unsigned int si = ai + !bi;
+ word s = D[si];
+
+ DWord A0B0 = DWord::Multiply(A[0], B[0]);
+ DWord t = A0B0 + C[0];
+ C[0] = t.GetLowHalf();
+
+ DWord A1B1 = DWord::Multiply(A[1], B[1]);
+ t = (DWord) t.GetHighHalf() + A0B0.GetLowHalf() + d.GetLowHalf() +
+ A1B1.GetLowHalf() + C[1];
+ C[1] = t.GetLowHalf();
+
+ t = (DWord) t.GetHighHalf() + A1B1.GetLowHalf() + A0B0.GetHighHalf() +
+ d.GetHighHalf() + A1B1.GetHighHalf() - s + C[2];
+ C[2] = t.GetLowHalf();
+
+ t = (DWord) t.GetHighHalf() + A1B1.GetHighHalf() + C[3];
+ C[3] = t.GetLowHalf();
+ return t.GetHighHalf();
+}
+
+
+#define MulAcc(x, y) \
+ p = DWord::MultiplyAndAdd(A[x], B[y], c); \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+#define SaveMulAcc(s, x, y) \
+ R[s] = c; \
+ p = DWord::MultiplyAndAdd(A[x], B[y], d); \
+ c = p.GetLowHalf(); \
+ p = (DWord) e + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e = p.GetHighHalf();
+
+#define SquAcc(x, y) \
+ q = DWord::Multiply(A[x], A[y]); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf(); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+#define SaveSquAcc(s, x, y) \
+ R[s] = c; \
+ q = DWord::Multiply(A[x], A[y]); \
+ p = q + d; \
+ c = p.GetLowHalf(); \
+ p = (DWord) e + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e = p.GetHighHalf(); \
+ p = q + c; \
+ c = p.GetLowHalf(); \
+ p = (DWord) d + p.GetHighHalf(); \
+ d = p.GetLowHalf(); \
+ e += p.GetHighHalf();
+
+
+void Portable::Multiply4(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 3, 1);
+ MulAcc(2, 2);
+ MulAcc(1, 3);
+
+ SaveMulAcc(4, 2, 3);
+ MulAcc(3, 2);
+
+ R[5] = c;
+ p = DWord::MultiplyAndAdd(A[3], B[3], d);
+ R[6] = p.GetLowHalf();
+ R[7] = e + p.GetHighHalf();
+}
+
+void Portable::Square2(word *R, const word *A)
+{
+ DWord p, q;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], A[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ SquAcc(0, 1);
+
+ R[1] = c;
+ p = DWord::MultiplyAndAdd(A[1], A[1], d);
+ R[2] = p.GetLowHalf();
+ R[3] = e + p.GetHighHalf();
+}
+
+void Portable::Square4(word *R, const word *A)
+{
+#ifdef _MSC_VER
+ // VC60 workaround: MSVC 6.0 has an optimization bug that makes
+ // (dword)A*B where either A or B has been cast to a dword before
+ // very expensive. Revisit this function when this
+ // bug is fixed.
+ Multiply4(R, A, A);
+#else
+ const word *B = A;
+ DWord p, q;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], A[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ SquAcc(0, 1);
+
+ SaveSquAcc(1, 2, 0);
+ MulAcc(1, 1);
+
+ SaveSquAcc(2, 0, 3);
+ SquAcc(1, 2);
+
+ SaveSquAcc(3, 3, 1);
+ MulAcc(2, 2);
+
+ SaveSquAcc(4, 2, 3);
+
+ R[5] = c;
+ p = DWord::MultiplyAndAdd(A[3], A[3], d);
+ R[6] = p.GetLowHalf();
+ R[7] = e + p.GetHighHalf();
+#endif
+}
+
+void Portable::Multiply8(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 0, 4);
+ MulAcc(1, 3);
+ MulAcc(2, 2);
+ MulAcc(3, 1);
+ MulAcc(4, 0);
+
+ SaveMulAcc(4, 0, 5);
+ MulAcc(1, 4);
+ MulAcc(2, 3);
+ MulAcc(3, 2);
+ MulAcc(4, 1);
+ MulAcc(5, 0);
+
+ SaveMulAcc(5, 0, 6);
+ MulAcc(1, 5);
+ MulAcc(2, 4);
+ MulAcc(3, 3);
+ MulAcc(4, 2);
+ MulAcc(5, 1);
+ MulAcc(6, 0);
+
+ SaveMulAcc(6, 0, 7);
+ MulAcc(1, 6);
+ MulAcc(2, 5);
+ MulAcc(3, 4);
+ MulAcc(4, 3);
+ MulAcc(5, 2);
+ MulAcc(6, 1);
+ MulAcc(7, 0);
+
+ SaveMulAcc(7, 1, 7);
+ MulAcc(2, 6);
+ MulAcc(3, 5);
+ MulAcc(4, 4);
+ MulAcc(5, 3);
+ MulAcc(6, 2);
+ MulAcc(7, 1);
+
+ SaveMulAcc(8, 2, 7);
+ MulAcc(3, 6);
+ MulAcc(4, 5);
+ MulAcc(5, 4);
+ MulAcc(6, 3);
+ MulAcc(7, 2);
+
+ SaveMulAcc(9, 3, 7);
+ MulAcc(4, 6);
+ MulAcc(5, 5);
+ MulAcc(6, 4);
+ MulAcc(7, 3);
+
+ SaveMulAcc(10, 4, 7);
+ MulAcc(5, 6);
+ MulAcc(6, 5);
+ MulAcc(7, 4);
+
+ SaveMulAcc(11, 5, 7);
+ MulAcc(6, 6);
+ MulAcc(7, 5);
+
+ SaveMulAcc(12, 6, 7);
+ MulAcc(7, 6);
+
+ R[13] = c;
+ p = DWord::MultiplyAndAdd(A[7], B[7], d);
+ R[14] = p.GetLowHalf();
+ R[15] = e + p.GetHighHalf();
+}
+
+void Portable::Multiply4Bottom(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ R[2] = c;
+ R[3] = d + A[0] * B[3] + A[1] * B[2] + A[2] * B[1] + A[3] * B[0];
+}
+
+void Portable::Multiply8Bottom(word *R, const word *A, const word *B)
+{
+ DWord p;
+ word c, d, e;
+
+ p = DWord::Multiply(A[0], B[0]);
+ R[0] = p.GetLowHalf();
+ c = p.GetHighHalf();
+ d = e = 0;
+
+ MulAcc(0, 1);
+ MulAcc(1, 0);
+
+ SaveMulAcc(1, 2, 0);
+ MulAcc(1, 1);
+ MulAcc(0, 2);
+
+ SaveMulAcc(2, 0, 3);
+ MulAcc(1, 2);
+ MulAcc(2, 1);
+ MulAcc(3, 0);
+
+ SaveMulAcc(3, 0, 4);
+ MulAcc(1, 3);
+ MulAcc(2, 2);
+ MulAcc(3, 1);
+ MulAcc(4, 0);
+
+ SaveMulAcc(4, 0, 5);
+ MulAcc(1, 4);
+ MulAcc(2, 3);
+ MulAcc(3, 2);
+ MulAcc(4, 1);
+ MulAcc(5, 0);
+
+ SaveMulAcc(5, 0, 6);
+ MulAcc(1, 5);
+ MulAcc(2, 4);
+ MulAcc(3, 3);
+ MulAcc(4, 2);
+ MulAcc(5, 1);
+ MulAcc(6, 0);
+
+ R[6] = c;
+ R[7] = d + A[0] * B[7] + A[1] * B[6] + A[2] * B[5] + A[3] * B[4] +
+ A[4] * B[3] + A[5] * B[2] + A[6] * B[1] + A[7] * B[0];
+}
+
+
+#undef MulAcc
+#undef SaveMulAcc
+#undef SquAcc
+#undef SaveSquAcc
+
+// optimized
+
+#ifdef TAOCRYPT_X86ASM_AVAILABLE
+
+// ************** x86 feature detection ***************
+
+static bool s_sse2Enabled = true;
+
+static void CpuId(word32 input, word32 *output)
+{
+#ifdef __GNUC__
+ __asm__
+ (
+ // save ebx in case -fPIC is being used
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+ : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d"(output[3])
+ : "a" (input)
+ );
+#else
+ __asm
+ {
+ mov eax, input
+ cpuid
+ mov edi, output
+ mov [edi], eax
+ mov [edi+4], ebx
+ mov [edi+8], ecx
+ mov [edi+12], edx
+ }
+#endif
+}
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+#ifndef _MSC_VER
+static jmp_buf s_env;
+static void SigIllHandler(int)
+{
+ longjmp(s_env, 1);
+}
+#endif
+
+static bool HasSSE2()
+{
+ if (!s_sse2Enabled)
+ return false;
+
+ word32 cpuid[4];
+ CpuId(1, cpuid);
+ if ((cpuid[3] & (1 << 26)) == 0)
+ return false;
+
+#ifdef _MSC_VER
+ __try
+ {
+ __asm xorpd xmm0, xmm0 // executing SSE2 instruction
+ }
+ __except (1)
+ {
+ return false;
+ }
+ return true;
+#else
+ typedef void (*SigHandler)(int);
+
+ SigHandler oldHandler = signal(SIGILL, SigIllHandler);
+ if (oldHandler == SIG_ERR)
+ return false;
+
+ bool result = true;
+ if (setjmp(s_env))
+ result = false;
+ else
+ __asm __volatile ("xorps %xmm0, %xmm0");
+
+ signal(SIGILL, oldHandler);
+ return result;
+#endif
+}
+#endif
+
+static bool IsP4()
+{
+ word32 cpuid[4];
+
+ CpuId(0, cpuid);
+ mySTL::swap(cpuid[2], cpuid[3]);
+ if (memcmp(cpuid+1, "GenuineIntel", 12) != 0)
+ return false;
+
+ CpuId(1, cpuid);
+ return ((cpuid[0] >> 8) & 0xf) == 0xf;
+}
+
+// ************** Pentium/P4 optimizations ***************
+
+class PentiumOptimized : public Portable
+{
+public:
+ static word TAOCRYPT_CDECL Add(word *C, const word *A, const word *B,
+ unsigned int N);
+ static word TAOCRYPT_CDECL Subtract(word *C, const word *A, const word *B,
+ unsigned int N);
+ static void TAOCRYPT_CDECL Multiply4(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8Bottom(word *C, const word *A,
+ const word *B);
+};
+
+class P4Optimized
+{
+public:
+ static word TAOCRYPT_CDECL Add(word *C, const word *A, const word *B,
+ unsigned int N);
+ static word TAOCRYPT_CDECL Subtract(word *C, const word *A, const word *B,
+ unsigned int N);
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ static void TAOCRYPT_CDECL Multiply4(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8(word *C, const word *A,
+ const word *B);
+ static void TAOCRYPT_CDECL Multiply8Bottom(word *C, const word *A,
+ const word *B);
+#endif
+};
+
+typedef word (TAOCRYPT_CDECL * PAddSub)(word *C, const word *A, const word *B,
+ unsigned int N);
+typedef void (TAOCRYPT_CDECL * PMul)(word *C, const word *A, const word *B);
+
+static PAddSub s_pAdd, s_pSub;
+#ifdef SSE2_INTRINSICS_AVAILABLE
+static PMul s_pMul4, s_pMul8, s_pMul8B;
+#endif
+
+static void SetPentiumFunctionPointers()
+{
+ if (IsP4())
+ {
+ s_pAdd = &P4Optimized::Add;
+ s_pSub = &P4Optimized::Subtract;
+ }
+ else
+ {
+ s_pAdd = &PentiumOptimized::Add;
+ s_pSub = &PentiumOptimized::Subtract;
+ }
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ if (HasSSE2())
+ {
+ s_pMul4 = &P4Optimized::Multiply4;
+ s_pMul8 = &P4Optimized::Multiply8;
+ s_pMul8B = &P4Optimized::Multiply8Bottom;
+ }
+ else
+ {
+ s_pMul4 = &PentiumOptimized::Multiply4;
+ s_pMul8 = &PentiumOptimized::Multiply8;
+ s_pMul8B = &PentiumOptimized::Multiply8Bottom;
+ }
+#endif
+}
+
+static const char s_RunAtStartupSetPentiumFunctionPointers =
+ (SetPentiumFunctionPointers(), 0);
+
+void DisableSSE2()
+{
+ s_sse2Enabled = false;
+ SetPentiumFunctionPointers();
+}
+
+class LowLevel : public PentiumOptimized
+{
+public:
+ inline static word Add(word *C, const word *A, const word *B,
+ unsigned int N)
+ {return s_pAdd(C, A, B, N);}
+ inline static word Subtract(word *C, const word *A, const word *B,
+ unsigned int N)
+ {return s_pSub(C, A, B, N);}
+ inline static void Square4(word *R, const word *A)
+ {Multiply4(R, A, A);}
+#ifdef SSE2_INTRINSICS_AVAILABLE
+ inline static void Multiply4(word *C, const word *A, const word *B)
+ {s_pMul4(C, A, B);}
+ inline static void Multiply8(word *C, const word *A, const word *B)
+ {s_pMul8(C, A, B);}
+ inline static void Multiply8Bottom(word *C, const word *A, const word *B)
+ {s_pMul8B(C, A, B);}
+#endif
+};
+
+// use some tricks to share assembly code between MSVC and GCC
+#ifdef _MSC_VER
+ #define TAOCRYPT_NAKED __declspec(naked)
+ #define AS1(x) __asm x
+ #define AS2(x, y) __asm x, y
+ #define AddPrologue \
+ __asm push ebp \
+ __asm push ebx \
+ __asm push esi \
+ __asm push edi \
+ __asm mov ecx, [esp+20] \
+ __asm mov edx, [esp+24] \
+ __asm mov ebx, [esp+28] \
+ __asm mov esi, [esp+32]
+ #define AddEpilogue \
+ __asm pop edi \
+ __asm pop esi \
+ __asm pop ebx \
+ __asm pop ebp \
+ __asm ret
+ #define MulPrologue \
+ __asm push ebp \
+ __asm push ebx \
+ __asm push esi \
+ __asm push edi \
+ __asm mov ecx, [esp+28] \
+ __asm mov esi, [esp+24] \
+ __asm push [esp+20]
+ #define MulEpilogue \
+ __asm add esp, 4 \
+ __asm pop edi \
+ __asm pop esi \
+ __asm pop ebx \
+ __asm pop ebp \
+ __asm ret
+#else
+ #define TAOCRYPT_NAKED
+ #define AS1(x) #x ";"
+ #define AS2(x, y) #x ", " #y ";"
+ #define AddPrologue \
+ __asm__ __volatile__ \
+ ( \
+ "push %%ebx;" /* save this manually, in case of -fPIC */ \
+ "mov %2, %%ebx;" \
+ ".intel_syntax noprefix;" \
+ "push ebp;"
+ #define AddEpilogue \
+ "pop ebp;" \
+ ".att_syntax prefix;" \
+ "pop %%ebx;" \
+ : \
+ : "c" (C), "d" (A), "m" (B), "S" (N) \
+ : "%edi", "memory", "cc" \
+ );
+ #define MulPrologue \
+ __asm__ __volatile__ \
+ ( \
+ "push %%ebx;" /* save this manually, in case of -fPIC */ \
+ "push %%ebp;" \
+ "push %0;" \
+ ".intel_syntax noprefix;"
+ #define MulEpilogue \
+ "add esp, 4;" \
+ "pop ebp;" \
+ "pop ebx;" \
+ ".att_syntax prefix;" \
+ : \
+ : "rm" (Z), "S" (X), "c" (Y) \
+ : "%eax", "%edx", "%edi", "memory", "cc" \
+ );
+#endif
+
+TAOCRYPT_NAKED word PentiumOptimized::Add(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( sub ecx, edx) // hold the distance between C & A so we
+ // can add this to A to get C
+ AS2( xor eax, eax) // clear eax
+
+ AS2( sub eax, esi) // eax is a negative index from end of B
+ AS2( lea ebx, [ebx+4*esi]) // ebx is end of B
+
+ AS2( sar eax, 1) // unit of eax is now dwords; this also
+ // clears the carry flag
+ AS1( jz loopendAdd) // if no dwords then nothing to do
+
+ AS1(loopstartAdd:)
+ AS2( mov esi,[edx]) // load lower word of A
+ AS2( mov ebp,[edx+4]) // load higher word of A
+
+ AS2( mov edi,[ebx+8*eax]) // load lower word of B
+ AS2( lea edx,[edx+8]) // advance A and C
+
+ AS2( adc esi,edi) // add lower words
+ AS2( mov edi,[ebx+8*eax+4]) // load higher word of B
+
+ AS2( adc ebp,edi) // add higher words
+ AS1( inc eax) // advance B
+
+ AS2( mov [edx+ecx-8],esi) // store lower word result
+ AS2( mov [edx+ecx-4],ebp) // store higher word result
+
+ AS1( jnz loopstartAdd) // loop until eax overflows and becomes zero
+
+ AS1(loopendAdd:)
+ AS2( adc eax, 0) // store carry into eax (return result register)
+
+ AddEpilogue
+}
+
+TAOCRYPT_NAKED word PentiumOptimized::Subtract(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( sub ecx, edx) // hold the distance between C & A so we
+ // can add this to A to get C
+ AS2( xor eax, eax) // clear eax
+
+ AS2( sub eax, esi) // eax is a negative index from end of B
+ AS2( lea ebx, [ebx+4*esi]) // ebx is end of B
+
+ AS2( sar eax, 1) // unit of eax is now dwords; this also
+ // clears the carry flag
+ AS1( jz loopendSub) // if no dwords then nothing to do
+
+ AS1(loopstartSub:)
+ AS2( mov esi,[edx]) // load lower word of A
+ AS2( mov ebp,[edx+4]) // load higher word of A
+
+ AS2( mov edi,[ebx+8*eax]) // load lower word of B
+ AS2( lea edx,[edx+8]) // advance A and C
+
+ AS2( sbb esi,edi) // subtract lower words
+ AS2( mov edi,[ebx+8*eax+4]) // load higher word of B
+
+ AS2( sbb ebp,edi) // subtract higher words
+ AS1( inc eax) // advance B
+
+ AS2( mov [edx+ecx-8],esi) // store lower word result
+ AS2( mov [edx+ecx-4],ebp) // store higher word result
+
+ AS1( jnz loopstartSub) // loop until eax overflows and becomes zero
+
+ AS1(loopendSub:)
+ AS2( adc eax, 0) // store carry into eax (return result register)
+
+ AddEpilogue
+}
+
+// On Pentium 4, the adc and sbb instructions are very expensive, so avoid them.
+
+TAOCRYPT_NAKED word P4Optimized::Add(word *C, const word *A, const word *B,
+ unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( xor eax, eax)
+ AS1( neg esi)
+ AS1( jz loopendAddP4) // if no dwords then nothing to do
+
+ AS2( mov edi, [edx])
+ AS2( mov ebp, [ebx])
+ AS1( jmp carry1AddP4)
+
+ AS1(loopstartAddP4:)
+ AS2( mov edi, [edx+8])
+ AS2( add ecx, 8)
+ AS2( add edx, 8)
+ AS2( mov ebp, [ebx])
+ AS2( add edi, eax)
+ AS1( jc carry1AddP4)
+ AS2( xor eax, eax)
+
+ AS1(carry1AddP4:)
+ AS2( add edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( mov [ecx], edi)
+ AS2( mov edi, [edx+4])
+ AS2( cmovc eax, ebp)
+ AS2( mov ebp, [ebx+4])
+ AS2( add ebx, 8)
+ AS2( add edi, eax)
+ AS1( jc carry2AddP4)
+ AS2( xor eax, eax)
+
+ AS1(carry2AddP4:)
+ AS2( add edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( cmovc eax, ebp)
+ AS2( mov [ecx+4], edi)
+ AS2( add esi, 2)
+ AS1( jnz loopstartAddP4)
+
+ AS1(loopendAddP4:)
+
+ AddEpilogue
+}
+
+TAOCRYPT_NAKED word P4Optimized::Subtract(word *C, const word *A,
+ const word *B, unsigned int N)
+{
+ AddPrologue
+
+ // now: ebx = B, ecx = C, edx = A, esi = N
+ AS2( xor eax, eax)
+ AS1( neg esi)
+ AS1( jz loopendSubP4) // if no dwords then nothing to do
+
+ AS2( mov edi, [edx])
+ AS2( mov ebp, [ebx])
+ AS1( jmp carry1SubP4)
+
+ AS1(loopstartSubP4:)
+ AS2( mov edi, [edx+8])
+ AS2( add edx, 8)
+ AS2( add ecx, 8)
+ AS2( mov ebp, [ebx])
+ AS2( sub edi, eax)
+ AS1( jc carry1SubP4)
+ AS2( xor eax, eax)
+
+ AS1(carry1SubP4:)
+ AS2( sub edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( mov [ecx], edi)
+ AS2( mov edi, [edx+4])
+ AS2( cmovc eax, ebp)
+ AS2( mov ebp, [ebx+4])
+ AS2( add ebx, 8)
+ AS2( sub edi, eax)
+ AS1( jc carry2SubP4)
+ AS2( xor eax, eax)
+
+ AS1(carry2SubP4:)
+ AS2( sub edi, ebp)
+ AS2( mov ebp, 1)
+ AS2( cmovc eax, ebp)
+ AS2( mov [ecx+4], edi)
+ AS2( add esi, 2)
+ AS1( jnz loopstartSubP4)
+
+ AS1(loopendSubP4:)
+
+ AddEpilogue
+}
+
+// multiply assembly code originally contributed by Leonard Janke
+
+#define MulStartup \
+ AS2(xor ebp, ebp) \
+ AS2(xor edi, edi) \
+ AS2(xor ebx, ebx)
+
+#define MulShiftCarry \
+ AS2(mov ebp, edx) \
+ AS2(mov edi, ebx) \
+ AS2(xor ebx, ebx)
+
+#define MulAccumulateBottom(i,j) \
+ AS2(mov eax, [ecx+4*j]) \
+ AS2(imul eax, dword ptr [esi+4*i]) \
+ AS2(add ebp, eax)
+
+#define MulAccumulate(i,j) \
+ AS2(mov eax, [ecx+4*j]) \
+ AS1(mul dword ptr [esi+4*i]) \
+ AS2(add ebp, eax) \
+ AS2(adc edi, edx) \
+ AS2(adc bl, bh)
+
+#define MulStoreDigit(i) \
+ AS2(mov edx, edi) \
+ AS2(mov edi, [esp]) \
+ AS2(mov [edi+4*i], ebp)
+
+#define MulLastDiagonal(digits) \
+ AS2(mov eax, [ecx+4*(digits-1)]) \
+ AS1(mul dword ptr [esi+4*(digits-1)]) \
+ AS2(add ebp, eax) \
+ AS2(adc edx, edi) \
+ AS2(mov edi, [esp]) \
+ AS2(mov [edi+4*(2*digits-2)], ebp) \
+ AS2(mov [edi+4*(2*digits-1)], edx)
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply4(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulLastDiagonal(4)
+ MulEpilogue
+}
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply8(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(4,0)
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulAccumulate(0,4)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(5,0)
+ MulAccumulate(4,1)
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulAccumulate(1,4)
+ MulAccumulate(0,5)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulAccumulate(6,0)
+ MulAccumulate(5,1)
+ MulAccumulate(4,2)
+ MulAccumulate(3,3)
+ MulAccumulate(2,4)
+ MulAccumulate(1,5)
+ MulAccumulate(0,6)
+ MulStoreDigit(6)
+ MulShiftCarry
+
+ MulAccumulate(7,0)
+ MulAccumulate(6,1)
+ MulAccumulate(5,2)
+ MulAccumulate(4,3)
+ MulAccumulate(3,4)
+ MulAccumulate(2,5)
+ MulAccumulate(1,6)
+ MulAccumulate(0,7)
+ MulStoreDigit(7)
+ MulShiftCarry
+
+ MulAccumulate(7,1)
+ MulAccumulate(6,2)
+ MulAccumulate(5,3)
+ MulAccumulate(4,4)
+ MulAccumulate(3,5)
+ MulAccumulate(2,6)
+ MulAccumulate(1,7)
+ MulStoreDigit(8)
+ MulShiftCarry
+
+ MulAccumulate(7,2)
+ MulAccumulate(6,3)
+ MulAccumulate(5,4)
+ MulAccumulate(4,5)
+ MulAccumulate(3,6)
+ MulAccumulate(2,7)
+ MulStoreDigit(9)
+ MulShiftCarry
+
+ MulAccumulate(7,3)
+ MulAccumulate(6,4)
+ MulAccumulate(5,5)
+ MulAccumulate(4,6)
+ MulAccumulate(3,7)
+ MulStoreDigit(10)
+ MulShiftCarry
+
+ MulAccumulate(7,4)
+ MulAccumulate(6,5)
+ MulAccumulate(5,6)
+ MulAccumulate(4,7)
+ MulStoreDigit(11)
+ MulShiftCarry
+
+ MulAccumulate(7,5)
+ MulAccumulate(6,6)
+ MulAccumulate(5,7)
+ MulStoreDigit(12)
+ MulShiftCarry
+
+ MulAccumulate(7,6)
+ MulAccumulate(6,7)
+ MulStoreDigit(13)
+ MulShiftCarry
+
+ MulLastDiagonal(8)
+ MulEpilogue
+}
+
+TAOCRYPT_NAKED void PentiumOptimized::Multiply8Bottom(word* Z, const word* X,
+ const word* Y)
+{
+ MulPrologue
+ // now: [esp] = Z, esi = X, ecx = Y
+ MulStartup
+ MulAccumulate(0,0)
+ MulStoreDigit(0)
+ MulShiftCarry
+
+ MulAccumulate(1,0)
+ MulAccumulate(0,1)
+ MulStoreDigit(1)
+ MulShiftCarry
+
+ MulAccumulate(2,0)
+ MulAccumulate(1,1)
+ MulAccumulate(0,2)
+ MulStoreDigit(2)
+ MulShiftCarry
+
+ MulAccumulate(3,0)
+ MulAccumulate(2,1)
+ MulAccumulate(1,2)
+ MulAccumulate(0,3)
+ MulStoreDigit(3)
+ MulShiftCarry
+
+ MulAccumulate(4,0)
+ MulAccumulate(3,1)
+ MulAccumulate(2,2)
+ MulAccumulate(1,3)
+ MulAccumulate(0,4)
+ MulStoreDigit(4)
+ MulShiftCarry
+
+ MulAccumulate(5,0)
+ MulAccumulate(4,1)
+ MulAccumulate(3,2)
+ MulAccumulate(2,3)
+ MulAccumulate(1,4)
+ MulAccumulate(0,5)
+ MulStoreDigit(5)
+ MulShiftCarry
+
+ MulAccumulate(6,0)
+ MulAccumulate(5,1)
+ MulAccumulate(4,2)
+ MulAccumulate(3,3)
+ MulAccumulate(2,4)
+ MulAccumulate(1,5)
+ MulAccumulate(0,6)
+ MulStoreDigit(6)
+ MulShiftCarry
+
+ MulAccumulateBottom(7,0)
+ MulAccumulateBottom(6,1)
+ MulAccumulateBottom(5,2)
+ MulAccumulateBottom(4,3)
+ MulAccumulateBottom(3,4)
+ MulAccumulateBottom(2,5)
+ MulAccumulateBottom(1,6)
+ MulAccumulateBottom(0,7)
+ MulStoreDigit(7)
+ MulEpilogue
+}
+
+#undef AS1
+#undef AS2
+
+#else // not x86 - no processor specific code at this layer
+
+typedef Portable LowLevel;
+
+#endif
+
+#ifdef SSE2_INTRINSICS_AVAILABLE
+
+#ifdef __GNUC__
+#define TAOCRYPT_FASTCALL
+#else
+#define TAOCRYPT_FASTCALL __fastcall
+#endif
+
+static void TAOCRYPT_FASTCALL P4_Mul(__m128i *C, const __m128i *A,
+ const __m128i *B)
+{
+ __m128i a3210 = _mm_load_si128(A);
+ __m128i b3210 = _mm_load_si128(B);
+
+ __m128i sum;
+
+ __m128i z = _mm_setzero_si128();
+ __m128i a2b2_a0b0 = _mm_mul_epu32(a3210, b3210);
+ C[0] = a2b2_a0b0;
+
+ __m128i a3120 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(3, 1, 2, 0));
+ __m128i b3021 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 2, 1));
+ __m128i a1b0_a0b1 = _mm_mul_epu32(a3120, b3021);
+ __m128i a1b0 = _mm_unpackhi_epi32(a1b0_a0b1, z);
+ __m128i a0b1 = _mm_unpacklo_epi32(a1b0_a0b1, z);
+ C[1] = _mm_add_epi64(a1b0, a0b1);
+
+ __m128i a31 = _mm_srli_epi64(a3210, 32);
+ __m128i b31 = _mm_srli_epi64(b3210, 32);
+ __m128i a3b3_a1b1 = _mm_mul_epu32(a31, b31);
+ C[6] = a3b3_a1b1;
+
+ __m128i a1b1 = _mm_unpacklo_epi32(a3b3_a1b1, z);
+ __m128i b3012 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(3, 0, 1, 2));
+ __m128i a2b0_a0b2 = _mm_mul_epu32(a3210, b3012);
+ __m128i a0b2 = _mm_unpacklo_epi32(a2b0_a0b2, z);
+ __m128i a2b0 = _mm_unpackhi_epi32(a2b0_a0b2, z);
+ sum = _mm_add_epi64(a1b1, a0b2);
+ C[2] = _mm_add_epi64(sum, a2b0);
+
+ __m128i a2301 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i b2103 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(2, 1, 0, 3));
+ __m128i a3b0_a1b2 = _mm_mul_epu32(a2301, b3012);
+ __m128i a2b1_a0b3 = _mm_mul_epu32(a3210, b2103);
+ __m128i a3b0 = _mm_unpackhi_epi32(a3b0_a1b2, z);
+ __m128i a1b2 = _mm_unpacklo_epi32(a3b0_a1b2, z);
+ __m128i a2b1 = _mm_unpackhi_epi32(a2b1_a0b3, z);
+ __m128i a0b3 = _mm_unpacklo_epi32(a2b1_a0b3, z);
+ __m128i sum1 = _mm_add_epi64(a3b0, a1b2);
+ sum = _mm_add_epi64(a2b1, a0b3);
+ C[3] = _mm_add_epi64(sum, sum1);
+
+ __m128i a3b1_a1b3 = _mm_mul_epu32(a2301, b2103);
+ __m128i a2b2 = _mm_unpackhi_epi32(a2b2_a0b0, z);
+ __m128i a3b1 = _mm_unpackhi_epi32(a3b1_a1b3, z);
+ __m128i a1b3 = _mm_unpacklo_epi32(a3b1_a1b3, z);
+ sum = _mm_add_epi64(a2b2, a3b1);
+ C[4] = _mm_add_epi64(sum, a1b3);
+
+ __m128i a1302 = _mm_shuffle_epi32(a3210, _MM_SHUFFLE(1, 3, 0, 2));
+ __m128i b1203 = _mm_shuffle_epi32(b3210, _MM_SHUFFLE(1, 2, 0, 3));
+ __m128i a3b2_a2b3 = _mm_mul_epu32(a1302, b1203);
+ __m128i a3b2 = _mm_unpackhi_epi32(a3b2_a2b3, z);
+ __m128i a2b3 = _mm_unpacklo_epi32(a3b2_a2b3, z);
+ C[5] = _mm_add_epi64(a3b2, a2b3);
+}
+
+void P4Optimized::Multiply4(word *C, const word *A, const word *B)
+{
+ __m128i temp[7];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ C[0] = w[0];
+
+ __m64 s1, s2;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w18, w20);
+ s1 = _mm_add_si64(s1, s2);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w22, w26);
+ s1 = _mm_add_si64(s1, s2);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[7] = _mm_cvtsi64_si32(s1) + w[27];
+ _mm_empty();
+}
+
+void P4Optimized::Multiply8(word *C, const word *A, const word *B)
+{
+ __m128i temp[28];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+ const word *x = (word *)temp+7*4;
+ const __m64 *mx = (__m64 *)x;
+ const word *y = (word *)temp+7*4*2;
+ const __m64 *my = (__m64 *)y;
+ const word *z = (word *)temp+7*4*3;
+ const __m64 *mz = (__m64 *)z;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ P4_Mul(temp+7, (__m128i *)A+1, (__m128i *)B);
+
+ P4_Mul(temp+14, (__m128i *)A, (__m128i *)B+1);
+
+ P4_Mul(temp+21, (__m128i *)A+1, (__m128i *)B+1);
+
+ C[0] = w[0];
+
+ __m64 s1, s2, s3, s4;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+ __m64 w27 = _mm_cvtsi32_si64(w[27]);
+
+ __m64 x0 = _mm_cvtsi32_si64(x[0]);
+ __m64 x1 = _mm_cvtsi32_si64(x[1]);
+ __m64 x4 = mx[2];
+ __m64 x6 = mx[3];
+ __m64 x8 = mx[4];
+ __m64 x10 = mx[5];
+ __m64 x12 = mx[6];
+ __m64 x14 = mx[7];
+ __m64 x16 = mx[8];
+ __m64 x18 = mx[9];
+ __m64 x20 = mx[10];
+ __m64 x22 = mx[11];
+ __m64 x26 = _mm_cvtsi32_si64(x[26]);
+ __m64 x27 = _mm_cvtsi32_si64(x[27]);
+
+ __m64 y0 = _mm_cvtsi32_si64(y[0]);
+ __m64 y1 = _mm_cvtsi32_si64(y[1]);
+ __m64 y4 = my[2];
+ __m64 y6 = my[3];
+ __m64 y8 = my[4];
+ __m64 y10 = my[5];
+ __m64 y12 = my[6];
+ __m64 y14 = my[7];
+ __m64 y16 = my[8];
+ __m64 y18 = my[9];
+ __m64 y20 = my[10];
+ __m64 y22 = my[11];
+ __m64 y26 = _mm_cvtsi32_si64(y[26]);
+ __m64 y27 = _mm_cvtsi32_si64(y[27]);
+
+ __m64 z0 = _mm_cvtsi32_si64(z[0]);
+ __m64 z1 = _mm_cvtsi32_si64(z[1]);
+ __m64 z4 = mz[2];
+ __m64 z6 = mz[3];
+ __m64 z8 = mz[4];
+ __m64 z10 = mz[5];
+ __m64 z12 = mz[6];
+ __m64 z14 = mz[7];
+ __m64 z16 = mz[8];
+ __m64 z18 = mz[9];
+ __m64 z20 = mz[10];
+ __m64 z22 = mz[11];
+ __m64 z26 = _mm_cvtsi32_si64(z[26]);
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x0, y0);
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s3);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x1, y1);
+ s4 = _mm_add_si64(x4, y4);
+ s1 = _mm_add_si64(s1, w18);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w20);
+ s1 = _mm_add_si64(s1, s3);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x6, y6);
+ s4 = _mm_add_si64(x8, y8);
+ s1 = _mm_add_si64(s1, w22);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w26);
+ s1 = _mm_add_si64(s1, s3);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x10, y10);
+ s4 = _mm_add_si64(x12, y12);
+ s1 = _mm_add_si64(s1, w27);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, s3);
+ C[7] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x14, y14);
+ s4 = _mm_add_si64(x16, y16);
+ s1 = _mm_add_si64(s1, z0);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, s3);
+ C[8] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x18, y18);
+ s4 = _mm_add_si64(x20, y20);
+ s1 = _mm_add_si64(s1, z1);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, z4);
+ s1 = _mm_add_si64(s1, s3);
+ C[9] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x22, y22);
+ s4 = _mm_add_si64(x26, y26);
+ s1 = _mm_add_si64(s1, z6);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, z8);
+ s1 = _mm_add_si64(s1, s3);
+ C[10] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x27, y27);
+ s1 = _mm_add_si64(s1, z10);
+ s1 = _mm_add_si64(s1, z12);
+ s1 = _mm_add_si64(s1, s3);
+ C[11] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z14, z16);
+ s1 = _mm_add_si64(s1, s3);
+ C[12] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z18, z20);
+ s1 = _mm_add_si64(s1, s3);
+ C[13] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(z22, z26);
+ s1 = _mm_add_si64(s1, s3);
+ C[14] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[15] = z[27] + _mm_cvtsi64_si32(s1);
+ _mm_empty();
+}
+
+void P4Optimized::Multiply8Bottom(word *C, const word *A, const word *B)
+{
+ __m128i temp[21];
+ const word *w = (word *)temp;
+ const __m64 *mw = (__m64 *)w;
+ const word *x = (word *)temp+7*4;
+ const __m64 *mx = (__m64 *)x;
+ const word *y = (word *)temp+7*4*2;
+ const __m64 *my = (__m64 *)y;
+
+ P4_Mul(temp, (__m128i *)A, (__m128i *)B);
+
+ P4_Mul(temp+7, (__m128i *)A+1, (__m128i *)B);
+
+ P4_Mul(temp+14, (__m128i *)A, (__m128i *)B+1);
+
+ C[0] = w[0];
+
+ __m64 s1, s2, s3, s4;
+
+ __m64 w1 = _mm_cvtsi32_si64(w[1]);
+ __m64 w4 = mw[2];
+ __m64 w6 = mw[3];
+ __m64 w8 = mw[4];
+ __m64 w10 = mw[5];
+ __m64 w12 = mw[6];
+ __m64 w14 = mw[7];
+ __m64 w16 = mw[8];
+ __m64 w18 = mw[9];
+ __m64 w20 = mw[10];
+ __m64 w22 = mw[11];
+ __m64 w26 = _mm_cvtsi32_si64(w[26]);
+
+ __m64 x0 = _mm_cvtsi32_si64(x[0]);
+ __m64 x1 = _mm_cvtsi32_si64(x[1]);
+ __m64 x4 = mx[2];
+ __m64 x6 = mx[3];
+ __m64 x8 = mx[4];
+
+ __m64 y0 = _mm_cvtsi32_si64(y[0]);
+ __m64 y1 = _mm_cvtsi32_si64(y[1]);
+ __m64 y4 = my[2];
+ __m64 y6 = my[3];
+ __m64 y8 = my[4];
+
+ s1 = _mm_add_si64(w1, w4);
+ C[1] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w6, w8);
+ s1 = _mm_add_si64(s1, s2);
+ C[2] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s2 = _mm_add_si64(w10, w12);
+ s1 = _mm_add_si64(s1, s2);
+ C[3] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x0, y0);
+ s2 = _mm_add_si64(w14, w16);
+ s1 = _mm_add_si64(s1, s3);
+ s1 = _mm_add_si64(s1, s2);
+ C[4] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x1, y1);
+ s4 = _mm_add_si64(x4, y4);
+ s1 = _mm_add_si64(s1, w18);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w20);
+ s1 = _mm_add_si64(s1, s3);
+ C[5] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ s3 = _mm_add_si64(x6, y6);
+ s4 = _mm_add_si64(x8, y8);
+ s1 = _mm_add_si64(s1, w22);
+ s3 = _mm_add_si64(s3, s4);
+ s1 = _mm_add_si64(s1, w26);
+ s1 = _mm_add_si64(s1, s3);
+ C[6] = _mm_cvtsi64_si32(s1);
+ s1 = _mm_srli_si64(s1, 32);
+
+ C[7] = _mm_cvtsi64_si32(s1) + w[27] + x[10] + y[10] + x[12] + y[12];
+ _mm_empty();
+}
+
+#endif // #ifdef SSE2_INTRINSICS_AVAILABLE
+
+// end optimized
+
+// ********************************************************
+
+#define A0 A
+#define A1 (A+N2)
+#define B0 B
+#define B1 (B+N2)
+
+#define T0 T
+#define T1 (T+N2)
+#define T2 (T+N)
+#define T3 (T+N+N2)
+
+#define R0 R
+#define R1 (R+N2)
+#define R2 (R+N)
+#define R3 (R+N+N2)
+
+//VC60 workaround: compiler bug triggered without the extra dummy parameters
+
+// R[2*N] - result = A*B
+// T[2*N] - temporary work space
+// A[N] --- multiplier
+// B[N] --- multiplicant
+
+
+void RecursiveMultiply(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (LowLevel::MultiplyRecursionLimit() >= 8 && N==8)
+ LowLevel::Multiply8(R, A, B);
+ else if (LowLevel::MultiplyRecursionLimit() >= 4 && N==4)
+ LowLevel::Multiply4(R, A, B);
+ else if (N==2)
+ LowLevel::Multiply2(R, A, B);
+ else
+ {
+ const unsigned int N2 = N/2;
+ int carry;
+
+ int aComp = Compare(A0, A1, N2);
+ int bComp = Compare(B0, B1, N2);
+
+ switch (2*aComp + aComp + bComp)
+ {
+ case -4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R0, N2);
+ carry = -1;
+ break;
+ case -2:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 2:
+ LowLevel::Subtract(R0, A0, A1, N2);
+ LowLevel::Subtract(R1, B1, B0, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R1, N2);
+ carry = -1;
+ break;
+ default:
+ SetWords(T0, 0, N);
+ carry = 0;
+ }
+
+ RecursiveMultiply(R0, T2, A0, B0, N2);
+ RecursiveMultiply(R2, T2, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1),R[01] holds A0*B0, R[23] holds A1*B1
+
+ carry += LowLevel::Add(T0, T0, R0, N);
+ carry += LowLevel::Add(T0, T0, R2, N);
+ carry += LowLevel::Add(R1, R1, T0, N);
+
+ assert (carry >= 0 && carry <= 2);
+ Increment(R3, N2, carry);
+ }
+}
+
+
+void RecursiveSquare(word *R, word *T, const word *A, unsigned int N)
+{
+ assert(N && N%2==0);
+ if (LowLevel::SquareRecursionLimit() >= 8 && N==8)
+ LowLevel::Square8(R, A);
+ if (LowLevel::SquareRecursionLimit() >= 4 && N==4)
+ LowLevel::Square4(R, A);
+ else if (N==2)
+ LowLevel::Square2(R, A);
+ else
+ {
+ const unsigned int N2 = N/2;
+
+ RecursiveSquare(R0, T2, A0, N2);
+ RecursiveSquare(R2, T2, A1, N2);
+ RecursiveMultiply(T0, T2, A0, A1, N2);
+
+ word carry = LowLevel::Add(R1, R1, T0, N);
+ carry += LowLevel::Add(R1, R1, T0, N);
+ Increment(R3, N2, carry);
+ }
+}
+
+
+// R[N] - bottom half of A*B
+// T[N] - temporary work space
+// A[N] - multiplier
+// B[N] - multiplicant
+
+
+void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+ if (LowLevel::MultiplyBottomRecursionLimit() >= 8 && N==8)
+ LowLevel::Multiply8Bottom(R, A, B);
+ else if (LowLevel::MultiplyBottomRecursionLimit() >= 4 && N==4)
+ LowLevel::Multiply4Bottom(R, A, B);
+ else if (N==2)
+ LowLevel::Multiply2Bottom(R, A, B);
+ else
+ {
+ const unsigned int N2 = N/2;
+
+ RecursiveMultiply(R, T, A0, B0, N2);
+ RecursiveMultiplyBottom(T0, T1, A1, B0, N2);
+ LowLevel::Add(R1, R1, T0, N2);
+ RecursiveMultiplyBottom(T0, T1, A0, B1, N2);
+ LowLevel::Add(R1, R1, T0, N2);
+ }
+}
+
+/*
+template <class P>
+void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A,
+ const word *B, unsigned int N, const P *dummy=0)
+{
+ assert(N>=2 && N%2==0);
+
+ if (N==4)
+ {
+ P::Multiply4(T, A, B);
+ ((dword *)R)[0] = ((dword *)T)[2];
+ ((dword *)R)[1] = ((dword *)T)[3];
+ }
+ else if (N==2)
+ {
+ P::Multiply2(T, A, B);
+ ((dword *)R)[0] = ((dword *)T)[1];
+ }
+ else
+ {
+ const unsigned int N2 = N/2;
+ int carry;
+
+ int aComp = Compare(A0, A1, N2);
+ int bComp = Compare(B0, B1, N2);
+
+ switch (2*aComp + aComp + bComp)
+ {
+ case -4:
+ P::Subtract(R0, A1, A0, N2);
+ P::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply<P>(T0, T2, R0, R1, N2);
+ P::Subtract(T1, T1, R0, N2);
+ carry = -1;
+ break;
+ case -2:
+ P::Subtract(R0, A1, A0, N2);
+ P::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply<P>(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 2:
+ P::Subtract(R0, A0, A1, N2);
+ P::Subtract(R1, B1, B0, N2);
+ RecursiveMultiply<P>(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 4:
+ P::Subtract(R0, A1, A0, N2);
+ P::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply<P>(T0, T2, R0, R1, N2);
+ P::Subtract(T1, T1, R1, N2);
+ carry = -1;
+ break;
+ default:
+ SetWords(T0, 0, N);
+ carry = 0;
+ }
+
+ RecursiveMultiply<P>(T2, R0, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1), T[23] holds A1*B1
+
+ word c2 = P::Subtract(R0, L+N2, L, N2);
+ c2 += P::Subtract(R0, R0, T0, N2);
+ word t = (Compare(R0, T2, N2) == -1);
+
+ carry += t;
+ carry += Increment(R0, N2, c2+t);
+ carry += P::Add(R0, R0, T1, N2);
+ carry += P::Add(R0, R0, T3, N2);
+ assert (carry >= 0 && carry <= 2);
+
+ CopyWords(R1, T3, N2);
+ Increment(R1, N2, carry);
+ }
+}
+*/
+
+
+void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A,
+ const word *B, unsigned int N)
+{
+ assert(N>=2 && N%2==0);
+
+ if (N==4)
+ {
+ LowLevel::Multiply4(T, A, B);
+ memcpy(R, T+4, 4*WORD_SIZE);
+ }
+ else if (N==2)
+ {
+ LowLevel::Multiply2(T, A, B);
+ memcpy(R, T+2, 2*WORD_SIZE);
+ }
+ else
+ {
+ const unsigned int N2 = N/2;
+ int carry;
+
+ int aComp = Compare(A0, A1, N2);
+ int bComp = Compare(B0, B1, N2);
+
+ switch (2*aComp + aComp + bComp)
+ {
+ case -4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R0, N2);
+ carry = -1;
+ break;
+ case -2:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 2:
+ LowLevel::Subtract(R0, A0, A1, N2);
+ LowLevel::Subtract(R1, B1, B0, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ carry = 0;
+ break;
+ case 4:
+ LowLevel::Subtract(R0, A1, A0, N2);
+ LowLevel::Subtract(R1, B0, B1, N2);
+ RecursiveMultiply(T0, T2, R0, R1, N2);
+ LowLevel::Subtract(T1, T1, R1, N2);
+ carry = -1;
+ break;
+ default:
+ SetWords(T0, 0, N);
+ carry = 0;
+ }
+
+ RecursiveMultiply(T2, R0, A1, B1, N2);
+
+ // now T[01] holds (A1-A0)*(B0-B1), T[23] holds A1*B1
+
+ word c2 = LowLevel::Subtract(R0, L+N2, L, N2);
+ c2 += LowLevel::Subtract(R0, R0, T0, N2);
+ word t = (Compare(R0, T2, N2) == -1);
+
+ carry += t;
+ carry += Increment(R0, N2, c2+t);
+ carry += LowLevel::Add(R0, R0, T1, N2);
+ carry += LowLevel::Add(R0, R0, T3, N2);
+ assert (carry >= 0 && carry <= 2);
+
+ CopyWords(R1, T3, N2);
+ Increment(R1, N2, carry);
+ }
+}
+
+
+inline word Add(word *C, const word *A, const word *B, unsigned int N)
+{
+ return LowLevel::Add(C, A, B, N);
+}
+
+inline word Subtract(word *C, const word *A, const word *B, unsigned int N)
+{
+ return LowLevel::Subtract(C, A, B, N);
+}
+
+inline void Multiply(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ RecursiveMultiply(R, T, A, B, N);
+}
+
+inline void Square(word *R, word *T, const word *A, unsigned int N)
+{
+ RecursiveSquare(R, T, A, N);
+}
+
+
+void AsymmetricMultiply(word *R, word *T, const word *A, unsigned int NA,
+ const word *B, unsigned int NB)
+{
+ if (NA == NB)
+ {
+ if (A == B)
+ Square(R, T, A, NA);
+ else
+ Multiply(R, T, A, B, NA);
+
+ return;
+ }
+
+ if (NA > NB)
+ {
+ mySTL::swap(A, B);
+ mySTL::swap(NA, NB);
+ }
+
+ assert(NB % NA == 0);
+ assert((NB/NA)%2 == 0); // NB is an even multiple of NA
+
+ if (NA==2 && !A[1])
+ {
+ switch (A[0])
+ {
+ case 0:
+ SetWords(R, 0, NB+2);
+ return;
+ case 1:
+ CopyWords(R, B, NB);
+ R[NB] = R[NB+1] = 0;
+ return;
+ default:
+ R[NB] = LinearMultiply(R, B, A[0], NB);
+ R[NB+1] = 0;
+ return;
+ }
+ }
+
+ Multiply(R, T, A, B, NA);
+ CopyWords(T+2*NA, R+NA, NA);
+
+ unsigned i;
+
+ for (i=2*NA; i<NB; i+=2*NA)
+ Multiply(T+NA+i, T, A, B+i, NA);
+ for (i=NA; i<NB; i+=2*NA)
+ Multiply(R+i, T, A, B+i, NA);
+
+ if (Add(R+NA, R+NA, T+2*NA, NB-NA))
+ Increment(R+NB, NA);
+}
+
+
+void PositiveMultiply(Integer& product, const Integer& a, const Integer& b)
+{
+ unsigned int aSize = RoundupSize(a.WordCount());
+ unsigned int bSize = RoundupSize(b.WordCount());
+
+ product.reg_.CleanNew(RoundupSize(aSize + bSize));
+ product.sign_ = Integer::POSITIVE;
+
+ WordBlock workspace(aSize + bSize);
+ AsymmetricMultiply(product.reg_.get_buffer(), workspace.get_buffer(),
+ a.reg_.get_buffer(), aSize, b.reg_.get_buffer(), bSize);
+}
+
+void Multiply(Integer &product, const Integer &a, const Integer &b)
+{
+ PositiveMultiply(product, a, b);
+
+ if (a.NotNegative() != b.NotNegative())
+ product.Negate();
+}
+
+
+static inline unsigned int EvenWordCount(const word *X, unsigned int N)
+{
+ while (N && X[N-2]==0 && X[N-1]==0)
+ N-=2;
+ return N;
+}
+
+
+unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA,
+ const word *M, unsigned int N)
+{
+ assert(NA<=N && N && N%2==0);
+
+ word *b = T;
+ word *c = T+N;
+ word *f = T+2*N;
+ word *g = T+3*N;
+ unsigned int bcLen=2, fgLen=EvenWordCount(M, N);
+ unsigned int k=0, s=0;
+
+ SetWords(T, 0, 3*N);
+ b[0]=1;
+ CopyWords(f, A, NA);
+ CopyWords(g, M, N);
+
+ while (1)
+ {
+ word t=f[0];
+ while (!t)
+ {
+ if (EvenWordCount(f, fgLen)==0)
+ {
+ SetWords(R, 0, N);
+ return 0;
+ }
+
+ ShiftWordsRightByWords(f, fgLen, 1);
+ if (c[bcLen-1]) bcLen+=2;
+ assert(bcLen <= N);
+ ShiftWordsLeftByWords(c, bcLen, 1);
+ k+=WORD_BITS;
+ t=f[0];
+ }
+
+ unsigned int i=0;
+ while (t%2 == 0)
+ {
+ t>>=1;
+ i++;
+ }
+ k+=i;
+
+ if (t==1 && f[1]==0 && EvenWordCount(f, fgLen)==2)
+ {
+ if (s%2==0)
+ CopyWords(R, b, N);
+ else
+ Subtract(R, M, b, N);
+ return k;
+ }
+
+ ShiftWordsRightByBits(f, fgLen, i);
+ t=ShiftWordsLeftByBits(c, bcLen, i);
+ if (t)
+ {
+ c[bcLen] = t;
+ bcLen+=2;
+ assert(bcLen <= N);
+ }
+
+ if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0)
+ fgLen-=2;
+
+ if (Compare(f, g, fgLen)==-1)
+ {
+ mySTL::swap(f, g);
+ mySTL::swap(b, c);
+ s++;
+ }
+
+ Subtract(f, f, g, fgLen);
+
+ if (Add(b, b, c, bcLen))
+ {
+ b[bcLen] = 1;
+ bcLen+=2;
+ assert(bcLen <= N);
+ }
+ }
+}
+
+// R[N] - result = A/(2^k) mod M
+// A[N] - input
+// M[N] - modulus
+
+void DivideByPower2Mod(word *R, const word *A, unsigned int k, const word *M,
+ unsigned int N)
+{
+ CopyWords(R, A, N);
+
+ while (k--)
+ {
+ if (R[0]%2==0)
+ ShiftWordsRightByBits(R, N, 1);
+ else
+ {
+ word carry = Add(R, R, M, N);
+ ShiftWordsRightByBits(R, N, 1);
+ R[N-1] += carry<<(WORD_BITS-1);
+ }
+ }
+}
+
+// R[N] - result = A*(2^k) mod M
+// A[N] - input
+// M[N] - modulus
+
+void MultiplyByPower2Mod(word *R, const word *A, unsigned int k, const word *M,
+ unsigned int N)
+{
+ CopyWords(R, A, N);
+
+ while (k--)
+ if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0)
+ Subtract(R, R, M, N);
+}
+
+
+// ********** end of integer needs
+
+
+Integer::Integer()
+ : reg_(2), sign_(POSITIVE)
+{
+ reg_[0] = reg_[1] = 0;
+}
+
+
+Integer::Integer(const Integer& t)
+ : reg_(RoundupSize(t.WordCount())), sign_(t.sign_)
+{
+ CopyWords(reg_.get_buffer(), t.reg_.get_buffer(), reg_.size());
+}
+
+
+Integer::Integer(signed long value)
+ : reg_(2)
+{
+ if (value >= 0)
+ sign_ = POSITIVE;
+ else
+ {
+ sign_ = NEGATIVE;
+ value = -value;
+ }
+ reg_[0] = word(value);
+ reg_[1] = word(SafeRightShift<WORD_BITS, unsigned long>(value));
+}
+
+
+Integer::Integer(Sign s, word high, word low)
+ : reg_(2), sign_(s)
+{
+ reg_[0] = low;
+ reg_[1] = high;
+}
+
+
+Integer::Integer(word value, unsigned int length)
+ : reg_(RoundupSize(length)), sign_(POSITIVE)
+{
+ reg_[0] = value;
+ SetWords(reg_ + 1, 0, reg_.size() - 1);
+}
+
+
+Integer::Integer(const char *str)
+ : reg_(2), sign_(POSITIVE)
+{
+ *this = StringToInteger(str);
+}
+
+
+Integer::Integer(const wchar_t *str)
+ : reg_(2), sign_(POSITIVE)
+{
+ *this = StringToInteger(str);
+}
+
+
+Integer::Integer(const byte *encodedInteger, unsigned int byteCount,
+ Signedness s)
+{
+ Decode(encodedInteger, byteCount, s);
+}
+
+class BadBER {};
+
+// BER Decode Source
+Integer::Integer(Source& source)
+ : reg_(2), sign_(POSITIVE)
+{
+ Decode(source);
+}
+
+void Integer::Decode(Source& source)
+{
+ byte b = source.next();
+ if (b != INTEGER) {
+ source.SetError(INTEGER_E);
+ return;
+ }
+
+ word32 length = GetLength(source);
+
+ if ( (b = source.next()) == 0x00)
+ length--;
+ else
+ source.prev();
+
+ unsigned int words = (length + WORD_SIZE - 1) / WORD_SIZE;
+ words = RoundupSize(words);
+ if (words > reg_.size()) reg_.CleanNew(words);
+
+ for (int j = length; j > 0; j--) {
+ b = source.next();
+ reg_ [(j-1) / WORD_SIZE] |= (word)b << ((j-1) % WORD_SIZE) * 8;
+ }
+}
+
+
+void Integer::Decode(const byte* input, unsigned int inputLen, Signedness s)
+{
+ unsigned int idx(0);
+ byte b = input[idx++];
+ sign_ = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE;
+
+ while (inputLen>0 && (sign_==POSITIVE ? b==0 : b==0xff))
+ {
+ inputLen--;
+ b = input[idx++];
+ }
+
+ reg_.CleanNew(RoundupSize(BytesToWords(inputLen)));
+
+ --idx;
+ for (unsigned int i=inputLen; i > 0; i--)
+ {
+ b = input[idx++];
+ reg_[(i-1)/WORD_SIZE] |= (word)b << ((i-1)%WORD_SIZE)*8;
+ }
+
+ if (sign_ == NEGATIVE)
+ {
+ for (unsigned i=inputLen; i<reg_.size()*WORD_SIZE; i++)
+ reg_[i/WORD_SIZE] |= (word)0xff << (i%WORD_SIZE)*8;
+ TwosComplement(reg_.get_buffer(), reg_.size());
+ }
+}
+
+
+unsigned int Integer::Encode(byte* output, unsigned int outputLen,
+ Signedness signedness) const
+{
+ unsigned int idx(0);
+ if (signedness == UNSIGNED || NotNegative())
+ {
+ for (unsigned int i=outputLen; i > 0; i--)
+ output[idx++] = GetByte(i-1);
+ }
+ else
+ {
+ // take two's complement of *this
+ Integer temp = Integer::Power2(8*max(ByteCount(), outputLen)) + *this;
+ for (unsigned i=0; i<outputLen; i++)
+ output[idx++] = temp.GetByte(outputLen-i-1);
+ }
+ return outputLen;
+}
+
+
+const Integer &Integer::Zero()
+{
+ static const Integer zero;
+ return zero;
+}
+
+
+const Integer &Integer::One()
+{
+ static const Integer one(1,2);
+ return one;
+}
+
+
+const Integer &Integer::Two()
+{
+ static const Integer two(2,2);
+ return two;
+}
+
+
+Integer::Integer(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max)
+{
+ Randomize(rng, min, max);
+}
+
+
+void Integer::Randomize(RandomNumberGenerator& rng, unsigned int nbits)
+{
+ const unsigned int nbytes = nbits/8 + 1;
+ ByteBlock buf(nbytes);
+ rng.GenerateBlock(buf.get_buffer(), nbytes);
+ if (nbytes)
+ buf[0] = (byte)Crop(buf[0], nbits % 8);
+ Decode(buf.get_buffer(), nbytes, UNSIGNED);
+}
+
+void Integer::Randomize(RandomNumberGenerator& rng, const Integer& min,
+ const Integer& max)
+{
+ assert(min <= max);
+
+ Integer range = max - min;
+ const unsigned int nbits = range.BitCount();
+
+ do
+ {
+ Randomize(rng, nbits);
+ }
+ while (*this > range);
+
+ *this += min;
+}
+
+
+Integer Integer::Power2(unsigned int e)
+{
+ Integer r((word)0, BitsToWords(e + 1));
+ r.SetBit(e);
+ return r;
+}
+
+
+void Integer::SetBit(unsigned int n, bool value)
+{
+ if (value)
+ {
+ reg_.CleanGrow(RoundupSize(BitsToWords(n + 1)));
+ reg_[n / WORD_BITS] |= (word(1) << (n % WORD_BITS));
+ }
+ else
+ {
+ if (n / WORD_BITS < reg_.size())
+ reg_[n / WORD_BITS] &= ~(word(1) << (n % WORD_BITS));
+ }
+}
+
+
+void Integer::SetByte(unsigned int n, byte value)
+{
+ reg_.CleanGrow(RoundupSize(BytesToWords(n+1)));
+ reg_[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
+ reg_[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
+}
+
+
+void Integer::Negate()
+{
+ if (!!(*this)) // don't flip sign if *this==0
+ sign_ = Sign(1 - sign_);
+}
+
+
+bool Integer::operator!() const
+{
+ return IsNegative() ? false : (reg_[0]==0 && WordCount()==0);
+}
+
+
+Integer& Integer::operator=(const Integer& t)
+{
+ if (this != &t)
+ {
+ reg_.New(RoundupSize(t.WordCount()));
+ CopyWords(reg_.get_buffer(), t.reg_.get_buffer(), reg_.size());
+ sign_ = t.sign_;
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator+=(const Integer& t)
+{
+ reg_.CleanGrow(t.reg_.size());
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ PositiveAdd(*this, *this, t);
+ else
+ PositiveSubtract(*this, *this, t);
+ }
+ else
+ {
+ if (t.NotNegative())
+ PositiveSubtract(*this, t, *this);
+ else
+ {
+ PositiveAdd(*this, *this, t);
+ sign_ = Integer::NEGATIVE;
+ }
+ }
+ return *this;
+}
+
+
+Integer Integer::operator-() const
+{
+ Integer result(*this);
+ result.Negate();
+ return result;
+}
+
+
+Integer& Integer::operator-=(const Integer& t)
+{
+ reg_.CleanGrow(t.reg_.size());
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ PositiveSubtract(*this, *this, t);
+ else
+ PositiveAdd(*this, *this, t);
+ }
+ else
+ {
+ if (t.NotNegative())
+ {
+ PositiveAdd(*this, *this, t);
+ sign_ = Integer::NEGATIVE;
+ }
+ else
+ PositiveSubtract(*this, t, *this);
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator++()
+{
+ if (NotNegative())
+ {
+ if (Increment(reg_.get_buffer(), reg_.size()))
+ {
+ reg_.CleanGrow(2*reg_.size());
+ reg_[reg_.size()/2]=1;
+ }
+ }
+ else
+ {
+ word borrow = Decrement(reg_.get_buffer(), reg_.size());
+ assert(!borrow);
+ if (WordCount()==0)
+ *this = Zero();
+ }
+ return *this;
+}
+
+Integer& Integer::operator--()
+{
+ if (IsNegative())
+ {
+ if (Increment(reg_.get_buffer(), reg_.size()))
+ {
+ reg_.CleanGrow(2*reg_.size());
+ reg_[reg_.size()/2]=1;
+ }
+ }
+ else
+ {
+ if (Decrement(reg_.get_buffer(), reg_.size()))
+ *this = -One();
+ }
+ return *this;
+}
+
+
+Integer& Integer::operator<<=(unsigned int n)
+{
+ const unsigned int wordCount = WordCount();
+ const unsigned int shiftWords = n / WORD_BITS;
+ const unsigned int shiftBits = n % WORD_BITS;
+
+ reg_.CleanGrow(RoundupSize(wordCount+BitsToWords(n)));
+ ShiftWordsLeftByWords(reg_.get_buffer(), wordCount + shiftWords,
+ shiftWords);
+ ShiftWordsLeftByBits(reg_+shiftWords, wordCount+BitsToWords(shiftBits),
+ shiftBits);
+ return *this;
+}
+
+Integer& Integer::operator>>=(unsigned int n)
+{
+ const unsigned int wordCount = WordCount();
+ const unsigned int shiftWords = n / WORD_BITS;
+ const unsigned int shiftBits = n % WORD_BITS;
+
+ ShiftWordsRightByWords(reg_.get_buffer(), wordCount, shiftWords);
+ if (wordCount > shiftWords)
+ ShiftWordsRightByBits(reg_.get_buffer(), wordCount-shiftWords,
+ shiftBits);
+ if (IsNegative() && WordCount()==0) // avoid -0
+ *this = Zero();
+ return *this;
+}
+
+
+void PositiveAdd(Integer& sum, const Integer& a, const Integer& b)
+{
+ word carry;
+ if (a.reg_.size() == b.reg_.size())
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size());
+ else if (a.reg_.size() > b.reg_.size())
+ {
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), b.reg_.size());
+ CopyWords(sum.reg_+b.reg_.size(), a.reg_+b.reg_.size(),
+ a.reg_.size()-b.reg_.size());
+ carry = Increment(sum.reg_+b.reg_.size(), a.reg_.size()-b.reg_.size(),
+ carry);
+ }
+ else
+ {
+ carry = Add(sum.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size());
+ CopyWords(sum.reg_+a.reg_.size(), b.reg_+a.reg_.size(),
+ b.reg_.size()-a.reg_.size());
+ carry = Increment(sum.reg_+a.reg_.size(), b.reg_.size()-a.reg_.size(),
+ carry);
+ }
+
+ if (carry)
+ {
+ sum.reg_.CleanGrow(2*sum.reg_.size());
+ sum.reg_[sum.reg_.size()/2] = 1;
+ }
+ sum.sign_ = Integer::POSITIVE;
+}
+
+void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b)
+{
+ unsigned aSize = a.WordCount();
+ aSize += aSize%2;
+ unsigned bSize = b.WordCount();
+ bSize += bSize%2;
+
+ if (aSize == bSize)
+ {
+ if (Compare(a.reg_.get_buffer(), b.reg_.get_buffer(), aSize) >= 0)
+ {
+ Subtract(diff.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), aSize);
+ diff.sign_ = Integer::POSITIVE;
+ }
+ else
+ {
+ Subtract(diff.reg_.get_buffer(), b.reg_.get_buffer(),
+ a.reg_.get_buffer(), aSize);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+ }
+ else if (aSize > bSize)
+ {
+ word borrow = Subtract(diff.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), bSize);
+ CopyWords(diff.reg_+bSize, a.reg_+bSize, aSize-bSize);
+ borrow = Decrement(diff.reg_+bSize, aSize-bSize, borrow);
+ assert(!borrow);
+ diff.sign_ = Integer::POSITIVE;
+ }
+ else
+ {
+ word borrow = Subtract(diff.reg_.get_buffer(), b.reg_.get_buffer(),
+ a.reg_.get_buffer(), aSize);
+ CopyWords(diff.reg_+aSize, b.reg_+aSize, bSize-aSize);
+ borrow = Decrement(diff.reg_+aSize, bSize-aSize, borrow);
+ assert(!borrow);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+}
+
+
+unsigned int Integer::MinEncodedSize(Signedness signedness) const
+{
+ unsigned int outputLen = max(1U, ByteCount());
+ if (signedness == UNSIGNED)
+ return outputLen;
+ if (NotNegative() && (GetByte(outputLen-1) & 0x80))
+ outputLen++;
+ if (IsNegative() && *this < -Power2(outputLen*8-1))
+ outputLen++;
+ return outputLen;
+}
+
+
+int Integer::Compare(const Integer& t) const
+{
+ if (NotNegative())
+ {
+ if (t.NotNegative())
+ return PositiveCompare(t);
+ else
+ return 1;
+ }
+ else
+ {
+ if (t.NotNegative())
+ return -1;
+ else
+ return -PositiveCompare(t);
+ }
+}
+
+
+int Integer::PositiveCompare(const Integer& t) const
+{
+ unsigned size = WordCount(), tSize = t.WordCount();
+
+ if (size == tSize)
+ return TaoCrypt::Compare(reg_.get_buffer(), t.reg_.get_buffer(), size);
+ else
+ return size > tSize ? 1 : -1;
+}
+
+
+bool Integer::GetBit(unsigned int n) const
+{
+ if (n/WORD_BITS >= reg_.size())
+ return 0;
+ else
+ return bool((reg_[n/WORD_BITS] >> (n % WORD_BITS)) & 1);
+}
+
+
+unsigned long Integer::GetBits(unsigned int i, unsigned int n) const
+{
+ assert(n <= sizeof(unsigned long)*8);
+ unsigned long v = 0;
+ for (unsigned int j=0; j<n; j++)
+ v |= GetBit(i+j) << j;
+ return v;
+}
+
+
+byte Integer::GetByte(unsigned int n) const
+{
+ if (n/WORD_SIZE >= reg_.size())
+ return 0;
+ else
+ return byte(reg_[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
+}
+
+
+unsigned int Integer::BitCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_BITS + BitPrecision(reg_[wordCount-1]);
+ else
+ return 0;
+}
+
+
+unsigned int Integer::ByteCount() const
+{
+ unsigned wordCount = WordCount();
+ if (wordCount)
+ return (wordCount-1)*WORD_SIZE + BytePrecision(reg_[wordCount-1]);
+ else
+ return 0;
+}
+
+
+unsigned int Integer::WordCount() const
+{
+ return CountWords(reg_.get_buffer(), reg_.size());
+}
+
+
+bool Integer::IsConvertableToLong() const
+{
+ if (ByteCount() > sizeof(long))
+ return false;
+
+ unsigned long value = reg_[0];
+ value += SafeLeftShift<WORD_BITS, unsigned long>(reg_[1]);
+
+ if (sign_ == POSITIVE)
+ return (signed long)value >= 0;
+ else
+ return -(signed long)value < 0;
+}
+
+
+signed long Integer::ConvertToLong() const
+{
+ assert(IsConvertableToLong());
+
+ unsigned long value = reg_[0];
+ value += SafeLeftShift<WORD_BITS, unsigned long>(reg_[1]);
+ return sign_ == POSITIVE ? value : -(signed long)value;
+}
+
+
+void Integer::Swap(Integer& a)
+{
+ reg_.Swap(a.reg_);
+ mySTL::swap(sign_, a.sign_);
+}
+
+
+Integer Integer::Plus(const Integer& b) const
+{
+ Integer sum((word)0, max(reg_.size(), b.reg_.size()));
+ if (NotNegative())
+ {
+ if (b.NotNegative())
+ PositiveAdd(sum, *this, b);
+ else
+ PositiveSubtract(sum, *this, b);
+ }
+ else
+ {
+ if (b.NotNegative())
+ PositiveSubtract(sum, b, *this);
+ else
+ {
+ PositiveAdd(sum, *this, b);
+ sum.sign_ = Integer::NEGATIVE;
+ }
+ }
+ return sum;
+}
+
+
+Integer Integer::Minus(const Integer& b) const
+{
+ Integer diff((word)0, max(reg_.size(), b.reg_.size()));
+ if (NotNegative())
+ {
+ if (b.NotNegative())
+ PositiveSubtract(diff, *this, b);
+ else
+ PositiveAdd(diff, *this, b);
+ }
+ else
+ {
+ if (b.NotNegative())
+ {
+ PositiveAdd(diff, *this, b);
+ diff.sign_ = Integer::NEGATIVE;
+ }
+ else
+ PositiveSubtract(diff, b, *this);
+ }
+ return diff;
+}
+
+
+Integer Integer::Times(const Integer &b) const
+{
+ Integer product;
+ Multiply(product, *this, b);
+ return product;
+}
+
+
+#undef A0
+#undef A1
+#undef B0
+#undef B1
+
+#undef T0
+#undef T1
+#undef T2
+#undef T3
+
+#undef R0
+#undef R1
+#undef R2
+#undef R3
+
+/*
+// do a 3 word by 2 word divide, returns quotient and leaves remainder in A
+static word SubatomicDivide(word *A, word B0, word B1)
+{
+ // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a word
+ assert(A[2] < B1 || (A[2]==B1 && A[1] < B0));
+
+ dword p, u;
+ word Q;
+
+ // estimate the quotient: do a 2 word by 1 word divide
+ if (B1+1 == 0)
+ Q = A[2];
+ else
+ Q = word(MAKE_DWORD(A[1], A[2]) / (B1+1));
+
+ // now subtract Q*B from A
+ p = (dword) B0*Q;
+ u = (dword) A[0] - LOW_WORD(p);
+ A[0] = LOW_WORD(u);
+ u = (dword) A[1] - HIGH_WORD(p) - (word)(0-HIGH_WORD(u)) - (dword)B1*Q;
+ A[1] = LOW_WORD(u);
+ A[2] += HIGH_WORD(u);
+
+ // Q <= actual quotient, so fix it
+ while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0))
+ {
+ u = (dword) A[0] - B0;
+ A[0] = LOW_WORD(u);
+ u = (dword) A[1] - B1 - (word)(0-HIGH_WORD(u));
+ A[1] = LOW_WORD(u);
+ A[2] += HIGH_WORD(u);
+ Q++;
+ assert(Q); // shouldn't overflow
+ }
+
+ return Q;
+}
+*/
+
+
+/*
+// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1
+static inline void AtomicDivide(word *Q, const word *A, const word *B)
+{
+ if (!B[0] && !B[1]) // if divisor is 0, we assume divisor==2**(2*WORD_BITS)
+ {
+ Q[0] = A[2];
+ Q[1] = A[3];
+ }
+ else
+ {
+ word T[4];
+ T[0] = A[0]; T[1] = A[1]; T[2] = A[2]; T[3] = A[3];
+ Q[1] = SubatomicDivide(T+1, B[0], B[1]);
+ Q[0] = SubatomicDivide(T, B[0], B[1]);
+
+#ifndef NDEBUG
+ // multiply quotient and divisor and add remainder
+ // make sure it equals dividend
+ assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0])));
+ word P[4];
+ LowLevel::Multiply2(P, Q, B);
+ Add(P, P, T, 4);
+ assert(memcmp(P, A, 4*WORD_SIZE)==0);
+#endif
+ }
+}
+*/
+
+
+static inline void AtomicDivide(word *Q, const word *A, const word *B)
+{
+ word T[4];
+ DWord q = DivideFourWordsByTwo<word, DWord>(T, DWord(A[0], A[1]),
+ DWord(A[2], A[3]), DWord(B[0], B[1]));
+ Q[0] = q.GetLowHalf();
+ Q[1] = q.GetHighHalf();
+
+#ifndef NDEBUG
+ if (B[0] || B[1])
+ {
+ // multiply quotient and divisor and add remainder, make sure it
+ // equals dividend
+ assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0])));
+ word P[4];
+ Portable::Multiply2(P, Q, B);
+ Add(P, P, T, 4);
+ assert(memcmp(P, A, 4*WORD_SIZE)==0);
+ }
+#endif
+}
+
+
+// for use by Divide(), corrects the underestimated quotient {Q1,Q0}
+static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B,
+ unsigned int N)
+{
+ assert(N && N%2==0);
+
+ if (Q[1])
+ {
+ T[N] = T[N+1] = 0;
+ unsigned i;
+ for (i=0; i<N; i+=4)
+ LowLevel::Multiply2(T+i, Q, B+i);
+ for (i=2; i<N; i+=4)
+ if (LowLevel::Multiply2Add(T+i, Q, B+i))
+ T[i+5] += (++T[i+4]==0);
+ }
+ else
+ {
+ T[N] = LinearMultiply(T, B, Q[0], N);
+ T[N+1] = 0;
+ }
+
+ word borrow = Subtract(R, R, T, N+2);
+ assert(!borrow && !R[N+1]);
+
+ while (R[N] || Compare(R, B, N) >= 0)
+ {
+ R[N] -= Subtract(R, R, B, N);
+ Q[1] += (++Q[0]==0);
+ assert(Q[0] || Q[1]); // no overflow
+ }
+}
+
+// R[NB] -------- remainder = A%B
+// Q[NA-NB+2] --- quotient = A/B
+// T[NA+2*NB+4] - temp work space
+// A[NA] -------- dividend
+// B[NB] -------- divisor
+
+
+void Divide(word* R, word* Q, word* T, const word* A, unsigned int NA,
+ const word* B, unsigned int NB)
+{
+ assert(NA && NB && NA%2==0 && NB%2==0);
+ assert(B[NB-1] || B[NB-2]);
+ assert(NB <= NA);
+
+ // set up temporary work space
+ word *const TA=T;
+ word *const TB=T+NA+2;
+ word *const TP=T+NA+2+NB;
+
+ // copy B into TB and normalize it so that TB has highest bit set to 1
+ unsigned shiftWords = (B[NB-1]==0);
+ TB[0] = TB[NB-1] = 0;
+ CopyWords(TB+shiftWords, B, NB-shiftWords);
+ unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]);
+ assert(shiftBits < WORD_BITS);
+ ShiftWordsLeftByBits(TB, NB, shiftBits);
+
+ // copy A into TA and normalize it
+ TA[0] = TA[NA] = TA[NA+1] = 0;
+ CopyWords(TA+shiftWords, A, NA);
+ ShiftWordsLeftByBits(TA, NA+2, shiftBits);
+
+ if (TA[NA+1]==0 && TA[NA] <= 1)
+ {
+ Q[NA-NB+1] = Q[NA-NB] = 0;
+ while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0)
+ {
+ TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB);
+ ++Q[NA-NB];
+ }
+ }
+ else
+ {
+ NA+=2;
+ assert(Compare(TA+NA-NB, TB, NB) < 0);
+ }
+
+ word BT[2];
+ BT[0] = TB[NB-2] + 1;
+ BT[1] = TB[NB-1] + (BT[0]==0);
+
+ // start reducing TA mod TB, 2 words at a time
+ for (unsigned i=NA-2; i>=NB; i-=2)
+ {
+ AtomicDivide(Q+i-NB, TA+i-2, BT);
+ CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB);
+ }
+
+ // copy TA into R, and denormalize it
+ CopyWords(R, TA+shiftWords, NB);
+ ShiftWordsRightByBits(R, NB, shiftBits);
+}
+
+
+void PositiveDivide(Integer& remainder, Integer& quotient,
+ const Integer& a, const Integer& b)
+{
+ unsigned aSize = a.WordCount();
+ unsigned bSize = b.WordCount();
+
+ assert(bSize);
+
+ if (a.PositiveCompare(b) == -1)
+ {
+ remainder = a;
+ remainder.sign_ = Integer::POSITIVE;
+ quotient = Integer::Zero();
+ return;
+ }
+
+ aSize += aSize%2; // round up to next even number
+ bSize += bSize%2;
+
+ remainder.reg_.CleanNew(RoundupSize(bSize));
+ remainder.sign_ = Integer::POSITIVE;
+ quotient.reg_.CleanNew(RoundupSize(aSize-bSize+2));
+ quotient.sign_ = Integer::POSITIVE;
+
+ WordBlock T(aSize+2*bSize+4);
+ Divide(remainder.reg_.get_buffer(), quotient.reg_.get_buffer(),
+ T.get_buffer(), a.reg_.get_buffer(), aSize, b.reg_.get_buffer(),
+ bSize);
+}
+
+void Integer::Divide(Integer &remainder, Integer &quotient,
+ const Integer &dividend, const Integer &divisor)
+{
+ PositiveDivide(remainder, quotient, dividend, divisor);
+
+ if (dividend.IsNegative())
+ {
+ quotient.Negate();
+ if (remainder.NotZero())
+ {
+ --quotient;
+ remainder = divisor.AbsoluteValue() - remainder;
+ }
+ }
+
+ if (divisor.IsNegative())
+ quotient.Negate();
+}
+
+void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a,
+ unsigned int n)
+{
+ q = a;
+ q >>= n;
+
+ const unsigned int wordCount = BitsToWords(n);
+ if (wordCount <= a.WordCount())
+ {
+ r.reg_.resize(RoundupSize(wordCount));
+ CopyWords(r.reg_.get_buffer(), a.reg_.get_buffer(), wordCount);
+ SetWords(r.reg_+wordCount, 0, r.reg_.size()-wordCount);
+ if (n % WORD_BITS != 0)
+ r.reg_[wordCount-1] %= (1 << (n % WORD_BITS));
+ }
+ else
+ {
+ r.reg_.resize(RoundupSize(a.WordCount()));
+ CopyWords(r.reg_.get_buffer(), a.reg_.get_buffer(), r.reg_.size());
+ }
+ r.sign_ = POSITIVE;
+
+ if (a.IsNegative() && r.NotZero())
+ {
+ --q;
+ r = Power2(n) - r;
+ }
+}
+
+Integer Integer::DividedBy(const Integer &b) const
+{
+ Integer remainder, quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+Integer Integer::Modulo(const Integer &b) const
+{
+ Integer remainder, quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return remainder;
+}
+
+void Integer::Divide(word &remainder, Integer &quotient,
+ const Integer &dividend, word divisor)
+{
+ assert(divisor);
+
+ if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
+ {
+ quotient = dividend >> (BitPrecision(divisor)-1);
+ remainder = dividend.reg_[0] & (divisor-1);
+ return;
+ }
+
+ unsigned int i = dividend.WordCount();
+ quotient.reg_.CleanNew(RoundupSize(i));
+ remainder = 0;
+ while (i--)
+ {
+ quotient.reg_[i] = DWord(dividend.reg_[i], remainder) / divisor;
+ remainder = DWord(dividend.reg_[i], remainder) % divisor;
+ }
+
+ if (dividend.NotNegative())
+ quotient.sign_ = POSITIVE;
+ else
+ {
+ quotient.sign_ = NEGATIVE;
+ if (remainder)
+ {
+ --quotient;
+ remainder = divisor - remainder;
+ }
+ }
+}
+
+Integer Integer::DividedBy(word b) const
+{
+ word remainder;
+ Integer quotient;
+ Integer::Divide(remainder, quotient, *this, b);
+ return quotient;
+}
+
+word Integer::Modulo(word divisor) const
+{
+ assert(divisor);
+
+ word remainder;
+
+ if ((divisor & (divisor-1)) == 0) // divisor is a power of 2
+ remainder = reg_[0] & (divisor-1);
+ else
+ {
+ unsigned int i = WordCount();
+
+ if (divisor <= 5)
+ {
+ DWord sum(0, 0);
+ while (i--)
+ sum += reg_[i];
+ remainder = sum % divisor;
+ }
+ else
+ {
+ remainder = 0;
+ while (i--)
+ remainder = DWord(reg_[i], remainder) % divisor;
+ }
+ }
+
+ if (IsNegative() && remainder)
+ remainder = divisor - remainder;
+
+ return remainder;
+}
+
+
+Integer Integer::AbsoluteValue() const
+{
+ Integer result(*this);
+ result.sign_ = POSITIVE;
+ return result;
+}
+
+
+Integer Integer::SquareRoot() const
+{
+ if (!IsPositive())
+ return Zero();
+
+ // overestimate square root
+ Integer x, y = Power2((BitCount()+1)/2);
+ assert(y*y >= *this);
+
+ do
+ {
+ x = y;
+ y = (x + *this/x) >> 1;
+ } while (y<x);
+
+ return x;
+}
+
+bool Integer::IsSquare() const
+{
+ Integer r = SquareRoot();
+ return *this == r.Squared();
+}
+
+bool Integer::IsUnit() const
+{
+ return (WordCount() == 1) && (reg_[0] == 1);
+}
+
+Integer Integer::MultiplicativeInverse() const
+{
+ return IsUnit() ? *this : Zero();
+}
+
+Integer a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m)
+{
+ return x*y%m;
+}
+
+Integer a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m)
+{
+ ModularArithmetic mr(m);
+ return mr.Exponentiate(x, e);
+}
+
+Integer Integer::Gcd(const Integer &a, const Integer &b)
+{
+ return EuclideanDomainOf<Integer>().Gcd(a, b);
+}
+
+Integer Integer::InverseMod(const Integer &m) const
+{
+ assert(m.NotNegative());
+
+ if (IsNegative() || *this>=m)
+ return (*this%m).InverseMod(m);
+
+ if (m.IsEven())
+ {
+ if (!m || IsEven())
+ return Zero(); // no inverse
+ if (*this == One())
+ return One();
+
+ Integer u = m.InverseMod(*this);
+ return !u ? Zero() : (m*(*this-u)+1)/(*this);
+ }
+
+ WordBlock T(m.reg_.size() * 4);
+ Integer r((word)0, m.reg_.size());
+ unsigned k = AlmostInverse(r.reg_.get_buffer(), T.get_buffer(),
+ reg_.get_buffer(), reg_.size(),
+ m.reg_.get_buffer(), m.reg_.size());
+ DivideByPower2Mod(r.reg_.get_buffer(), r.reg_.get_buffer(), k,
+ m.reg_.get_buffer(), m.reg_.size());
+ return r;
+}
+
+word Integer::InverseMod(const word mod) const
+{
+ word g0 = mod, g1 = *this % mod;
+ word v0 = 0, v1 = 1;
+ word y;
+
+ while (g1)
+ {
+ if (g1 == 1)
+ return v1;
+ y = g0 / g1;
+ g0 = g0 % g1;
+ v0 += y * v1;
+
+ if (!g0)
+ break;
+ if (g0 == 1)
+ return mod-v0;
+ y = g1 / g0;
+ g1 = g1 % g0;
+ v1 += y * v0;
+ }
+ return 0;
+}
+
+// ********* ModArith stuff
+
+const Integer& ModularArithmetic::Half(const Integer &a) const
+{
+ if (a.reg_.size()==modulus.reg_.size())
+ {
+ TaoCrypt::DivideByPower2Mod(result.reg_.begin(), a.reg_.begin(), 1,
+ modulus.reg_.begin(), a.reg_.size());
+ return result;
+ }
+ else
+ return result1 = (a.IsEven() ? (a >> 1) : ((a+modulus) >> 1));
+}
+
+const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Add(result.reg_.begin(), a.reg_.begin(), b.reg_.begin(),
+ a.reg_.size())
+ || Compare(result.reg_.get_buffer(), modulus.reg_.get_buffer(),
+ a.reg_.size()) >= 0)
+ {
+ TaoCrypt::Subtract(result.reg_.begin(), result.reg_.begin(),
+ modulus.reg_.begin(), a.reg_.size());
+ }
+ return result;
+ }
+ else
+ {
+ result1 = a+b;
+ if (result1 >= modulus)
+ result1 -= modulus;
+ return result1;
+ }
+}
+
+Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Add(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size())
+ || Compare(a.reg_.get_buffer(), modulus.reg_.get_buffer(),
+ a.reg_.size()) >= 0)
+ {
+ TaoCrypt::Subtract(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ modulus.reg_.get_buffer(), a.reg_.size());
+ }
+ }
+ else
+ {
+ a+=b;
+ if (a>=modulus)
+ a-=modulus;
+ }
+
+ return a;
+}
+
+const Integer& ModularArithmetic::Subtract(const Integer &a,
+ const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Subtract(result.reg_.begin(), a.reg_.begin(),
+ b.reg_.begin(), a.reg_.size()))
+ TaoCrypt::Add(result.reg_.begin(), result.reg_.begin(),
+ modulus.reg_.begin(), a.reg_.size());
+ return result;
+ }
+ else
+ {
+ result1 = a-b;
+ if (result1.IsNegative())
+ result1 += modulus;
+ return result1;
+ }
+}
+
+Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const
+{
+ if (a.reg_.size()==modulus.reg_.size() &&
+ b.reg_.size()==modulus.reg_.size())
+ {
+ if (TaoCrypt::Subtract(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ b.reg_.get_buffer(), a.reg_.size()))
+ TaoCrypt::Add(a.reg_.get_buffer(), a.reg_.get_buffer(),
+ modulus.reg_.get_buffer(), a.reg_.size());
+ }
+ else
+ {
+ a-=b;
+ if (a.IsNegative())
+ a+=modulus;
+ }
+
+ return a;
+}
+
+const Integer& ModularArithmetic::Inverse(const Integer &a) const
+{
+ if (!a)
+ return a;
+
+ CopyWords(result.reg_.begin(), modulus.reg_.begin(), modulus.reg_.size());
+ if (TaoCrypt::Subtract(result.reg_.begin(), result.reg_.begin(),
+ a.reg_.begin(), a.reg_.size()))
+ Decrement(result.reg_.begin()+a.reg_.size(), 1,
+ modulus.reg_.size()-a.reg_.size());
+
+ return result;
+}
+
+Integer ModularArithmetic::CascadeExponentiate(const Integer &x,
+ const Integer &e1, const Integer &y, const Integer &e2) const
+{
+ if (modulus.IsOdd())
+ {
+ MontgomeryRepresentation dr(modulus);
+ return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1,
+ dr.ConvertIn(y), e2));
+ }
+ else
+ return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);
+}
+
+void ModularArithmetic::SimultaneousExponentiate(Integer *results,
+ const Integer &base, const Integer *exponents,
+ unsigned int exponentsCount) const
+{
+ if (modulus.IsOdd())
+ {
+ MontgomeryRepresentation dr(modulus);
+ dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents,
+ exponentsCount);
+ for (unsigned int i=0; i<exponentsCount; i++)
+ results[i] = dr.ConvertOut(results[i]);
+ }
+ else
+ AbstractRing<Integer>::SimultaneousExponentiate(results, base,
+ exponents, exponentsCount);
+}
+
+
+// ********************************************************
+
+#define A0 A
+#define A1 (A+N2)
+#define B0 B
+#define B1 (B+N2)
+
+#define T0 T
+#define T1 (T+N2)
+#define T2 (T+N)
+#define T3 (T+N+N2)
+
+#define R0 R
+#define R1 (R+N2)
+#define R2 (R+N)
+#define R3 (R+N+N2)
+
+
+inline void MultiplyBottom(word *R, word *T, const word *A, const word *B,
+ unsigned int N)
+{
+ RecursiveMultiplyBottom(R, T, A, B, N);
+}
+
+inline void MultiplyTop(word *R, word *T, const word *L, const word *A,
+ const word *B, unsigned int N)
+{
+ RecursiveMultiplyTop(R, T, L, A, B, N);
+}
+
+
+// R[N] --- result = X/(2**(WORD_BITS*N)) mod M
+// T[3*N] - temporary work space
+// X[2*N] - number to be reduced
+// M[N] --- modulus
+// U[N] --- multiplicative inverse of M mod 2**(WORD_BITS*N)
+
+void MontgomeryReduce(word *R, word *T, const word *X, const word *M,
+ const word *U, unsigned int N)
+{
+ MultiplyBottom(R, T, X, U, N);
+ MultiplyTop(T, T+N, X, R, M, N);
+ word borrow = Subtract(T, X+N, T, N);
+ // defend against timing attack by doing this Add even when not needed
+ word carry = Add(T+N, T, M, N);
+ assert(carry || !borrow);
+ CopyWords(R, T + (borrow ? N : 0), N);
+}
+
+// R[N] ----- result = A inverse mod 2**(WORD_BITS*N)
+// T[3*N/2] - temporary work space
+// A[N] ----- an odd number as input
+
+void RecursiveInverseModPower2(word *R, word *T, const word *A, unsigned int N)
+{
+ if (N==2)
+ {
+ T[0] = AtomicInverseModPower2(A[0]);
+ T[1] = 0;
+ LowLevel::Multiply2Bottom(T+2, T, A);
+ TwosComplement(T+2, 2);
+ Increment(T+2, 2, 2);
+ LowLevel::Multiply2Bottom(R, T, T+2);
+ }
+ else
+ {
+ const unsigned int N2 = N/2;
+ RecursiveInverseModPower2(R0, T0, A0, N2);
+ T0[0] = 1;
+ SetWords(T0+1, 0, N2-1);
+ MultiplyTop(R1, T1, T0, R0, A0, N2);
+ MultiplyBottom(T0, T1, R0, A1, N2);
+ Add(T0, R1, T0, N2);
+ TwosComplement(T0, N2);
+ MultiplyBottom(R1, T1, R0, T0, N2);
+ }
+}
+
+
+#undef A0
+#undef A1
+#undef B0
+#undef B1
+
+#undef T0
+#undef T1
+#undef T2
+#undef T3
+
+#undef R0
+#undef R1
+#undef R2
+#undef R3
+
+
+// modulus must be odd
+MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m)
+ : ModularArithmetic(m),
+ u((word)0, modulus.reg_.size()),
+ workspace(5*modulus.reg_.size())
+{
+ assert(modulus.IsOdd());
+ RecursiveInverseModPower2(u.reg_.get_buffer(), workspace.get_buffer(),
+ modulus.reg_.get_buffer(), modulus.reg_.size());
+}
+
+const Integer& MontgomeryRepresentation::Multiply(const Integer &a,
+ const Integer &b) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N && b.reg_.size()<=N);
+
+ AsymmetricMultiply(T, T+2*N, a.reg_.get_buffer(), a.reg_.size(),
+ b.reg_.get_buffer(), b.reg_.size());
+ SetWords(T+a.reg_.size()+b.reg_.size(),0, 2*N-a.reg_.size()-b.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+const Integer& MontgomeryRepresentation::Square(const Integer &a) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ TaoCrypt::Square(T, T+2*N, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+2*a.reg_.size(), 0, 2*N-2*a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const
+{
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ CopyWords(T, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+a.reg_.size(), 0, 2*N-a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ return result;
+}
+
+const Integer& MontgomeryRepresentation::MultiplicativeInverse(
+ const Integer &a) const
+{
+// return (EuclideanMultiplicativeInverse(a, modulus)<<
+// (2*WORD_BITS*modulus.reg_.size()))%modulus;
+ word *const T = workspace.begin();
+ word *const R = result.reg_.begin();
+ const unsigned int N = modulus.reg_.size();
+ assert(a.reg_.size()<=N);
+
+ CopyWords(T, a.reg_.get_buffer(), a.reg_.size());
+ SetWords(T+a.reg_.size(), 0, 2*N-a.reg_.size());
+ MontgomeryReduce(R, T+2*N, T, modulus.reg_.get_buffer(),
+ u.reg_.get_buffer(), N);
+ unsigned k = AlmostInverse(R, T, R, N, modulus.reg_.get_buffer(), N);
+
+// cout << "k=" << k << " N*32=" << 32*N << endl;
+
+ if (k>N*WORD_BITS)
+ DivideByPower2Mod(R, R, k-N*WORD_BITS, modulus.reg_.get_buffer(), N);
+ else
+ MultiplyByPower2Mod(R, R, N*WORD_BITS-k, modulus.reg_.get_buffer(), N);
+
+ return result;
+}
+
+
+// mod Root stuff
+Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
+ const Integer &p, const Integer &q, const Integer &u)
+{
+ Integer p2 = ModularExponentiation((a % p), dp, p);
+ Integer q2 = ModularExponentiation((a % q), dq, q);
+ return CRT(p2, p, q2, q, u);
+}
+
+Integer CRT(const Integer &xp, const Integer &p, const Integer &xq,
+ const Integer &q, const Integer &u)
+{
+ // isn't operator overloading great?
+ return p * (u * (xq-xp) % q) + xp;
+}
+
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/md2.cpp b/extra/yassl/taocrypt/src/md2.cpp
new file mode 100644
index 00000000000..16834b6bc89
--- /dev/null
+++ b/extra/yassl/taocrypt/src/md2.cpp
@@ -0,0 +1,128 @@
+/* md2.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* based on Wei Dai's md2.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "md2.hpp"
+#include <string.h>
+
+namespace TaoCrypt {
+
+
+MD2::MD2()
+ : X_(X_SIZE), C_(BLOCK_SIZE), buffer_(BLOCK_SIZE)
+{
+ Init();
+}
+
+void MD2::Init()
+{
+ memset(X_.get_buffer(), 0, X_SIZE);
+ memset(C_.get_buffer(), 0, BLOCK_SIZE);
+ memset(buffer_.get_buffer(), 0, BLOCK_SIZE);
+ count_ = 0;
+}
+
+
+void MD2::Update(const byte* data, word32 len)
+{
+
+ static const byte S[256] =
+ {
+ 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+ 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+ 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+ 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+ 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+ 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+ 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+ 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+ 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+ 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+ 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+ 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+ 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+ 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+ 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+ 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+ 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+ 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+ };
+
+ while (len) {
+ word32 L = (PAD_SIZE - count_) < len ? (PAD_SIZE - count_) : len;
+ memcpy(buffer_.get_buffer() + count_, data, L);
+ count_ += L;
+ data += L;
+ len -= L;
+
+ if (count_==PAD_SIZE) {
+ count_ = 0;
+ memcpy(X_.get_buffer() + PAD_SIZE, buffer_.get_buffer(), PAD_SIZE);
+ byte t = C_[15];
+
+ int i;
+ for(i = 0; i < PAD_SIZE; i++) {
+ X_[32 + i] = X_[PAD_SIZE + i] ^ X_[i];
+ t = C_[i] ^= S[buffer_[i] ^ t];
+ }
+
+ t=0;
+ for(i = 0; i < 18; i++) {
+ for(int j = 0; j < X_SIZE; j += 8) {
+ t = X_[j+0] ^= S[t];
+ t = X_[j+1] ^= S[t];
+ t = X_[j+2] ^= S[t];
+ t = X_[j+3] ^= S[t];
+ t = X_[j+4] ^= S[t];
+ t = X_[j+5] ^= S[t];
+ t = X_[j+6] ^= S[t];
+ t = X_[j+7] ^= S[t];
+ }
+ t = (t + i) & 0xFF;
+ }
+ }
+ }
+}
+
+
+void MD2::Final(byte *hash)
+{
+ byte padding[BLOCK_SIZE];
+ word32 padLen = PAD_SIZE - count_;
+
+ for (word32 i = 0; i < padLen; i++)
+ padding[i] = static_cast<byte>(padLen);
+
+ Update(padding, padLen);
+ Update(C_.get_buffer(), BLOCK_SIZE);
+
+ memcpy(hash, X_.get_buffer(), DIGEST_SIZE);
+
+ Init();
+}
+
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp
new file mode 100644
index 00000000000..b9777e93216
--- /dev/null
+++ b/extra/yassl/taocrypt/src/md5.cpp
@@ -0,0 +1,169 @@
+/* md5.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* based on Wei Dai's md5.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "md5.hpp"
+#include "algorithm.hpp" // mySTL::swap
+
+namespace TaoCrypt {
+
+void MD5::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xefcdab89L;
+ digest_[2] = 0x98badcfeL;
+ digest_[3] = 0x10325476L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+MD5::MD5(const MD5& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
+ BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+MD5& MD5::operator= (const MD5& that)
+{
+ MD5 tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void MD5::Swap(MD5& other)
+{
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(buffLen_, other.buffLen_);
+ mySTL::swap(digest_, other.digest_);
+ mySTL::swap(length_, other.length_);
+}
+
+
+void MD5::Transform()
+{
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) \
+ w = rotlFixed(w + f(x, y, z) + data, s) + x
+
+ // Copy context->state[] to working vars
+ word32 a = digest_[0];
+ word32 b = digest_[1];
+ word32 c = digest_[2];
+ word32 d = digest_[3];
+
+ MD5STEP(F1, a, b, c, d, *(word32*)&buffer_[0*4] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, *(word32*)&buffer_[1*4] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, *(word32*)&buffer_[2*4] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, *(word32*)&buffer_[3*4] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, *(word32*)&buffer_[4*4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, *(word32*)&buffer_[5*4] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, *(word32*)&buffer_[6*4] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, *(word32*)&buffer_[7*4] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, *(word32*)&buffer_[8*4] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, *(word32*)&buffer_[9*4] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, *(word32*)&buffer_[10*4] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, *(word32*)&buffer_[11*4] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, *(word32*)&buffer_[12*4] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, *(word32*)&buffer_[13*4] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, *(word32*)&buffer_[14*4] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, *(word32*)&buffer_[15*4] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, *(word32*)&buffer_[1*4] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, *(word32*)&buffer_[6*4] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, *(word32*)&buffer_[11*4] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, *(word32*)&buffer_[0*4] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, *(word32*)&buffer_[5*4] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, *(word32*)&buffer_[10*4] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, *(word32*)&buffer_[15*4] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, *(word32*)&buffer_[4*4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, *(word32*)&buffer_[9*4] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, *(word32*)&buffer_[14*4] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, *(word32*)&buffer_[3*4] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, *(word32*)&buffer_[8*4] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, *(word32*)&buffer_[13*4] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, *(word32*)&buffer_[2*4] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, *(word32*)&buffer_[7*4] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, *(word32*)&buffer_[12*4] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, *(word32*)&buffer_[5*4] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, *(word32*)&buffer_[8*4] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, *(word32*)&buffer_[11*4] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, *(word32*)&buffer_[14*4] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, *(word32*)&buffer_[1*4] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, *(word32*)&buffer_[4*4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, *(word32*)&buffer_[7*4] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, *(word32*)&buffer_[10*4] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, *(word32*)&buffer_[13*4] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, *(word32*)&buffer_[0*4] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, *(word32*)&buffer_[3*4] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, *(word32*)&buffer_[6*4] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, *(word32*)&buffer_[9*4] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, *(word32*)&buffer_[12*4] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, *(word32*)&buffer_[15*4] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, *(word32*)&buffer_[2*4] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, *(word32*)&buffer_[0*4] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, *(word32*)&buffer_[7*4] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, *(word32*)&buffer_[14*4] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, *(word32*)&buffer_[5*4] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, *(word32*)&buffer_[12*4] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, *(word32*)&buffer_[3*4] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, *(word32*)&buffer_[10*4] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, *(word32*)&buffer_[1*4] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, *(word32*)&buffer_[8*4] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, *(word32*)&buffer_[15*4] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, *(word32*)&buffer_[6*4] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, *(word32*)&buffer_[13*4] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, *(word32*)&buffer_[4*4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, *(word32*)&buffer_[11*4] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, *(word32*)&buffer_[2*4] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, *(word32*)&buffer_[9*4] + 0xeb86d391, 21);
+
+ // Add the working vars back into digest state[]
+ digest_[0] += a;
+ digest_[1] += b;
+ digest_[2] += c;
+ digest_[3] += d;
+
+ // Wipe variables
+ a = b = c = d = 0;
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp
new file mode 100644
index 00000000000..e4573abac3f
--- /dev/null
+++ b/extra/yassl/taocrypt/src/misc.cpp
@@ -0,0 +1,132 @@
+/* misc.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's misc.cpp from CryptoPP */
+
+
+#include "runtime.hpp"
+#include "misc.hpp"
+#include <new> // for NewHandler
+
+
+void* operator new(size_t sz, TaoCrypt::new_t)
+{
+ void* ptr = ::operator new(sz);
+
+ if (!ptr) abort();
+
+ return ptr;
+}
+
+void* operator new[](size_t sz, TaoCrypt::new_t tc)
+{
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+ void* ptr = ::operator new(sz); // no ::operator new[]
+#else
+ void* ptr = ::operator new[](sz);
+#endif
+
+ if (!ptr) abort();
+
+ return ptr;
+}
+
+
+
+namespace TaoCrypt {
+
+
+new_t tc; // for library new
+
+
+inline void XorWords(word* r, const word* a, unsigned int n)
+{
+ for (unsigned int i=0; i<n; i++)
+ r[i] ^= a[i];
+}
+
+
+void xorbuf(byte* buf, const byte* mask, unsigned int count)
+{
+ if (((size_t)buf | (size_t)mask | count) % WORD_SIZE == 0)
+ XorWords((word *)buf, (const word *)mask, count/WORD_SIZE);
+ else
+ {
+ for (unsigned int i=0; i<count; i++)
+ buf[i] ^= mask[i];
+ }
+}
+
+
+unsigned int BytePrecision(unsigned long value)
+{
+ unsigned int i;
+ for (i=sizeof(value); i; --i)
+ if (value >> (i-1)*8)
+ break;
+
+ return i;
+}
+
+
+unsigned int BitPrecision(unsigned long value)
+{
+ if (!value)
+ return 0;
+
+ unsigned int l = 0,
+ h = 8 * sizeof(value);
+
+ while (h-l > 1)
+ {
+ unsigned int t = (l+h)/2;
+ if (value >> t)
+ l = t;
+ else
+ h = t;
+ }
+
+ return h;
+}
+
+
+unsigned long Crop(unsigned long value, unsigned int size)
+{
+ if (size < 8*sizeof(value))
+ return (value & ((1L << size) - 1));
+ else
+ return value;
+}
+
+
+#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
+using std::new_handler;
+using std::set_new_handler;
+#endif
+
+void CallNewHandler()
+{
+ abort();
+}
+
+
+} // namespace
+
diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp
new file mode 100644
index 00000000000..5c9e3b0f02a
--- /dev/null
+++ b/extra/yassl/taocrypt/src/random.cpp
@@ -0,0 +1,131 @@
+/* random.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* random.cpp implements a crypto secure Random Number Generator using an OS
+ specific seed, switch to /dev/random for more security but may block
+*/
+
+#include "runtime.hpp"
+#include "random.hpp"
+#include "stdexcept.hpp"
+
+#if defined(WIN32)
+ #define _WIN32_WINNT 0x0400
+ #include <windows.h>
+ #include <wincrypt.h>
+#else
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+#endif // WIN32
+
+namespace TaoCrypt {
+
+
+// Get seed and key cipher
+RandomNumberGenerator::RandomNumberGenerator()
+{
+ byte key[32];
+ seed_.GenerateSeed(key, sizeof(key));
+ cipher_.SetKey(key, sizeof(key));
+}
+
+
+// place a generated block in output
+void RandomNumberGenerator::GenerateBlock(byte* output, word32 sz)
+{
+ cipher_.Process(output, output, sz);
+}
+
+
+byte RandomNumberGenerator::GenerateByte()
+{
+ byte b;
+ GenerateBlock(&b, 1);
+
+ return b;
+}
+
+
+#if defined(WIN32)
+
+OS_Seed::OS_Seed()
+{
+ if(!CryptAcquireContext(&handle_, 0, 0, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ error_.SetError(WINCRYPT_E);
+}
+
+
+OS_Seed::~OS_Seed()
+{
+ CryptReleaseContext(handle_, 0);
+}
+
+
+void OS_Seed::GenerateSeed(byte* output, word32 sz)
+{
+ if (!CryptGenRandom(handle_, sz, output))
+ error_.SetError(CRYPTGEN_E);
+}
+
+
+#else // WIN32
+
+
+OS_Seed::OS_Seed()
+{
+ fd_ = open("/dev/urandom",O_RDONLY);
+ if (fd_ == -1)
+ error_.SetError(OPEN_RAN_E);
+}
+
+
+OS_Seed::~OS_Seed()
+{
+ close(fd_);
+}
+
+
+// may block
+void OS_Seed::GenerateSeed(byte* output, word32 sz)
+{
+ while (sz) {
+ int len = read(fd_, output, sz);
+ if (len == -1) {
+ error_.SetError(READ_RAN_E);
+ return;
+ }
+
+ sz -= len;
+ output += len;
+
+ if (sz)
+ sleep(1);
+ }
+}
+
+#endif // WIN32
+
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp
new file mode 100644
index 00000000000..53f573cac32
--- /dev/null
+++ b/extra/yassl/taocrypt/src/ripemd.cpp
@@ -0,0 +1,289 @@
+/* ripemd.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* based on Wei Dai's ripemd.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "ripemd.hpp"
+#include "algorithm.hpp" // mySTL::swap
+
+namespace TaoCrypt {
+
+void RIPEMD160::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xefcdab89L;
+ digest_[2] = 0x98badcfeL;
+ digest_[3] = 0x10325476L;
+ digest_[4] = 0xc3d2e1f0L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+RIPEMD160::RIPEMD160(const RIPEMD160& that)
+ : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+
+RIPEMD160& RIPEMD160::operator= (const RIPEMD160& that)
+{
+ RIPEMD160 tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void RIPEMD160::Swap(RIPEMD160& other)
+{
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(buffLen_, other.buffLen_);
+ mySTL::swap(digest_, other.digest_);
+ mySTL::swap(length_, other.length_);
+}
+
+
+// for all
+#define F(x, y, z) (x ^ y ^ z)
+#define G(x, y, z) (z ^ (x & (y^z)))
+#define H(x, y, z) (z ^ (x | ~y))
+#define I(x, y, z) (y ^ (z & (x^y)))
+#define J(x, y, z) (x ^ (y | ~z))
+
+#define k0 0
+#define k1 0x5a827999UL
+#define k2 0x6ed9eba1UL
+#define k3 0x8f1bbcdcUL
+#define k4 0xa953fd4eUL
+#define k5 0x50a28be6UL
+#define k6 0x5c4dd124UL
+#define k7 0x6d703ef3UL
+#define k8 0x7a6d76e9UL
+#define k9 0
+
+// for 160 and 320
+#define Subround(f, a, b, c, d, e, x, s, k) \
+ a += f(b, c, d) + x + k;\
+ a = rotlFixed((word32)a, s) + e;\
+ c = rotlFixed((word32)c, 10U)
+
+
+void RIPEMD160::Transform()
+{
+ unsigned long a1, b1, c1, d1, e1, a2, b2, c2, d2, e2;
+ a1 = a2 = digest_[0];
+ b1 = b2 = digest_[1];
+ c1 = c2 = digest_[2];
+ d1 = d2 = digest_[3];
+ e1 = e2 = digest_[4];
+
+ Subround(F, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 0*4], 11, k0);
+ Subround(F, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 1*4], 14, k0);
+ Subround(F, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 2*4], 15, k0);
+ Subround(F, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 3*4], 12, k0);
+ Subround(F, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 4*4], 5, k0);
+ Subround(F, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 5*4], 8, k0);
+ Subround(F, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 6*4], 7, k0);
+ Subround(F, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 7*4], 9, k0);
+ Subround(F, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 8*4], 11, k0);
+ Subround(F, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 9*4], 13, k0);
+ Subround(F, a1, b1, c1, d1, e1, *(word32*)&buffer_[10*4], 14, k0);
+ Subround(F, e1, a1, b1, c1, d1, *(word32*)&buffer_[11*4], 15, k0);
+ Subround(F, d1, e1, a1, b1, c1, *(word32*)&buffer_[12*4], 6, k0);
+ Subround(F, c1, d1, e1, a1, b1, *(word32*)&buffer_[13*4], 7, k0);
+ Subround(F, b1, c1, d1, e1, a1, *(word32*)&buffer_[14*4], 9, k0);
+ Subround(F, a1, b1, c1, d1, e1, *(word32*)&buffer_[15*4], 8, k0);
+
+ Subround(G, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 7*4], 7, k1);
+ Subround(G, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 4*4], 6, k1);
+ Subround(G, c1, d1, e1, a1, b1, *(word32*)&buffer_[13*4], 8, k1);
+ Subround(G, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 1*4], 13, k1);
+ Subround(G, a1, b1, c1, d1, e1, *(word32*)&buffer_[10*4], 11, k1);
+ Subround(G, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 6*4], 9, k1);
+ Subround(G, d1, e1, a1, b1, c1, *(word32*)&buffer_[15*4], 7, k1);
+ Subround(G, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 3*4], 15, k1);
+ Subround(G, b1, c1, d1, e1, a1, *(word32*)&buffer_[12*4], 7, k1);
+ Subround(G, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 0*4], 12, k1);
+ Subround(G, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 9*4], 15, k1);
+ Subround(G, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 5*4], 9, k1);
+ Subround(G, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 2*4], 11, k1);
+ Subround(G, b1, c1, d1, e1, a1, *(word32*)&buffer_[14*4], 7, k1);
+ Subround(G, a1, b1, c1, d1, e1, *(word32*)&buffer_[11*4], 13, k1);
+ Subround(G, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 8*4], 12, k1);
+
+ Subround(H, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 3*4], 11, k2);
+ Subround(H, c1, d1, e1, a1, b1, *(word32*)&buffer_[10*4], 13, k2);
+ Subround(H, b1, c1, d1, e1, a1, *(word32*)&buffer_[14*4], 6, k2);
+ Subround(H, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 4*4], 7, k2);
+ Subround(H, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 9*4], 14, k2);
+ Subround(H, d1, e1, a1, b1, c1, *(word32*)&buffer_[15*4], 9, k2);
+ Subround(H, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 8*4], 13, k2);
+ Subround(H, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 1*4], 15, k2);
+ Subround(H, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 2*4], 14, k2);
+ Subround(H, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 7*4], 8, k2);
+ Subround(H, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 0*4], 13, k2);
+ Subround(H, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 6*4], 6, k2);
+ Subround(H, b1, c1, d1, e1, a1, *(word32*)&buffer_[13*4], 5, k2);
+ Subround(H, a1, b1, c1, d1, e1, *(word32*)&buffer_[11*4], 12, k2);
+ Subround(H, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 5*4], 7, k2);
+ Subround(H, d1, e1, a1, b1, c1, *(word32*)&buffer_[12*4], 5, k2);
+
+ Subround(I, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 1*4], 11, k3);
+ Subround(I, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 9*4], 12, k3);
+ Subround(I, a1, b1, c1, d1, e1, *(word32*)&buffer_[11*4], 14, k3);
+ Subround(I, e1, a1, b1, c1, d1, *(word32*)&buffer_[10*4], 15, k3);
+ Subround(I, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 0*4], 14, k3);
+ Subround(I, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 8*4], 15, k3);
+ Subround(I, b1, c1, d1, e1, a1, *(word32*)&buffer_[12*4], 9, k3);
+ Subround(I, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 4*4], 8, k3);
+ Subround(I, e1, a1, b1, c1, d1, *(word32*)&buffer_[13*4], 9, k3);
+ Subround(I, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 3*4], 14, k3);
+ Subround(I, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 7*4], 5, k3);
+ Subround(I, b1, c1, d1, e1, a1, *(word32*)&buffer_[15*4], 6, k3);
+ Subround(I, a1, b1, c1, d1, e1, *(word32*)&buffer_[14*4], 8, k3);
+ Subround(I, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 5*4], 6, k3);
+ Subround(I, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 6*4], 5, k3);
+ Subround(I, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 2*4], 12, k3);
+
+ Subround(J, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 4*4], 9, k4);
+ Subround(J, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 0*4], 15, k4);
+ Subround(J, e1, a1, b1, c1, d1, *(word32*)&buffer_[ 5*4], 5, k4);
+ Subround(J, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 9*4], 11, k4);
+ Subround(J, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 7*4], 6, k4);
+ Subround(J, b1, c1, d1, e1, a1, *(word32*)&buffer_[12*4], 8, k4);
+ Subround(J, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 2*4], 13, k4);
+ Subround(J, e1, a1, b1, c1, d1, *(word32*)&buffer_[10*4], 12, k4);
+ Subround(J, d1, e1, a1, b1, c1, *(word32*)&buffer_[14*4], 5, k4);
+ Subround(J, c1, d1, e1, a1, b1, *(word32*)&buffer_[ 1*4], 12, k4);
+ Subround(J, b1, c1, d1, e1, a1, *(word32*)&buffer_[ 3*4], 13, k4);
+ Subround(J, a1, b1, c1, d1, e1, *(word32*)&buffer_[ 8*4], 14, k4);
+ Subround(J, e1, a1, b1, c1, d1, *(word32*)&buffer_[11*4], 11, k4);
+ Subround(J, d1, e1, a1, b1, c1, *(word32*)&buffer_[ 6*4], 8, k4);
+ Subround(J, c1, d1, e1, a1, b1, *(word32*)&buffer_[15*4], 5, k4);
+ Subround(J, b1, c1, d1, e1, a1, *(word32*)&buffer_[13*4], 6, k4);
+
+ Subround(J, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 5*4], 8, k5);
+ Subround(J, e2, a2, b2, c2, d2, *(word32*)&buffer_[14*4], 9, k5);
+ Subround(J, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 7*4], 9, k5);
+ Subround(J, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 0*4], 11, k5);
+ Subround(J, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 9*4], 13, k5);
+ Subround(J, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 2*4], 15, k5);
+ Subround(J, e2, a2, b2, c2, d2, *(word32*)&buffer_[11*4], 15, k5);
+ Subround(J, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 4*4], 5, k5);
+ Subround(J, c2, d2, e2, a2, b2, *(word32*)&buffer_[13*4], 7, k5);
+ Subround(J, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 6*4], 7, k5);
+ Subround(J, a2, b2, c2, d2, e2, *(word32*)&buffer_[15*4], 8, k5);
+ Subround(J, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 8*4], 11, k5);
+ Subround(J, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 1*4], 14, k5);
+ Subround(J, c2, d2, e2, a2, b2, *(word32*)&buffer_[10*4], 14, k5);
+ Subround(J, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 3*4], 12, k5);
+ Subround(J, a2, b2, c2, d2, e2, *(word32*)&buffer_[12*4], 6, k5);
+
+ Subround(I, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 6*4], 9, k6);
+ Subround(I, d2, e2, a2, b2, c2, *(word32*)&buffer_[11*4], 13, k6);
+ Subround(I, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 3*4], 15, k6);
+ Subround(I, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 7*4], 7, k6);
+ Subround(I, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 0*4], 12, k6);
+ Subround(I, e2, a2, b2, c2, d2, *(word32*)&buffer_[13*4], 8, k6);
+ Subround(I, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 5*4], 9, k6);
+ Subround(I, c2, d2, e2, a2, b2, *(word32*)&buffer_[10*4], 11, k6);
+ Subround(I, b2, c2, d2, e2, a2, *(word32*)&buffer_[14*4], 7, k6);
+ Subround(I, a2, b2, c2, d2, e2, *(word32*)&buffer_[15*4], 7, k6);
+ Subround(I, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 8*4], 12, k6);
+ Subround(I, d2, e2, a2, b2, c2, *(word32*)&buffer_[12*4], 7, k6);
+ Subround(I, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 4*4], 6, k6);
+ Subround(I, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 9*4], 15, k6);
+ Subround(I, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 1*4], 13, k6);
+ Subround(I, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 2*4], 11, k6);
+
+ Subround(H, d2, e2, a2, b2, c2, *(word32*)&buffer_[15*4], 9, k7);
+ Subround(H, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 5*4], 7, k7);
+ Subround(H, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 1*4], 15, k7);
+ Subround(H, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 3*4], 11, k7);
+ Subround(H, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 7*4], 8, k7);
+ Subround(H, d2, e2, a2, b2, c2, *(word32*)&buffer_[14*4], 6, k7);
+ Subround(H, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 6*4], 6, k7);
+ Subround(H, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 9*4], 14, k7);
+ Subround(H, a2, b2, c2, d2, e2, *(word32*)&buffer_[11*4], 12, k7);
+ Subround(H, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 8*4], 13, k7);
+ Subround(H, d2, e2, a2, b2, c2, *(word32*)&buffer_[12*4], 5, k7);
+ Subround(H, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 2*4], 14, k7);
+ Subround(H, b2, c2, d2, e2, a2, *(word32*)&buffer_[10*4], 13, k7);
+ Subround(H, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 0*4], 13, k7);
+ Subround(H, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 4*4], 7, k7);
+ Subround(H, d2, e2, a2, b2, c2, *(word32*)&buffer_[13*4], 5, k7);
+
+ Subround(G, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 8*4], 15, k8);
+ Subround(G, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 6*4], 5, k8);
+ Subround(G, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 4*4], 8, k8);
+ Subround(G, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 1*4], 11, k8);
+ Subround(G, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 3*4], 14, k8);
+ Subround(G, c2, d2, e2, a2, b2, *(word32*)&buffer_[11*4], 14, k8);
+ Subround(G, b2, c2, d2, e2, a2, *(word32*)&buffer_[15*4], 6, k8);
+ Subround(G, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 0*4], 14, k8);
+ Subround(G, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 5*4], 6, k8);
+ Subround(G, d2, e2, a2, b2, c2, *(word32*)&buffer_[12*4], 9, k8);
+ Subround(G, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 2*4], 12, k8);
+ Subround(G, b2, c2, d2, e2, a2, *(word32*)&buffer_[13*4], 9, k8);
+ Subround(G, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 9*4], 12, k8);
+ Subround(G, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 7*4], 5, k8);
+ Subround(G, d2, e2, a2, b2, c2, *(word32*)&buffer_[10*4], 15, k8);
+ Subround(G, c2, d2, e2, a2, b2, *(word32*)&buffer_[14*4], 8, k8);
+
+ Subround(F, b2, c2, d2, e2, a2, *(word32*)&buffer_[12*4], 8, k9);
+ Subround(F, a2, b2, c2, d2, e2, *(word32*)&buffer_[15*4], 5, k9);
+ Subround(F, e2, a2, b2, c2, d2, *(word32*)&buffer_[10*4], 12, k9);
+ Subround(F, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 4*4], 9, k9);
+ Subround(F, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 1*4], 12, k9);
+ Subround(F, b2, c2, d2, e2, a2, *(word32*)&buffer_[ 5*4], 5, k9);
+ Subround(F, a2, b2, c2, d2, e2, *(word32*)&buffer_[ 8*4], 14, k9);
+ Subround(F, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 7*4], 6, k9);
+ Subround(F, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 6*4], 8, k9);
+ Subround(F, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 2*4], 13, k9);
+ Subround(F, b2, c2, d2, e2, a2, *(word32*)&buffer_[13*4], 6, k9);
+ Subround(F, a2, b2, c2, d2, e2, *(word32*)&buffer_[14*4], 5, k9);
+ Subround(F, e2, a2, b2, c2, d2, *(word32*)&buffer_[ 0*4], 15, k9);
+ Subround(F, d2, e2, a2, b2, c2, *(word32*)&buffer_[ 3*4], 13, k9);
+ Subround(F, c2, d2, e2, a2, b2, *(word32*)&buffer_[ 9*4], 11, k9);
+ Subround(F, b2, c2, d2, e2, a2, *(word32*)&buffer_[11*4], 11, k9);
+
+ c1 = digest_[1] + c1 + d2;
+ digest_[1] = digest_[2] + d1 + e2;
+ digest_[2] = digest_[3] + e1 + a2;
+ digest_[3] = digest_[4] + a1 + b2;
+ digest_[4] = digest_[0] + b1 + c2;
+ digest_[0] = c1;
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+
+} // namespace TaoCrypt
diff --git a/extra/yassl/taocrypt/src/rsa.cpp b/extra/yassl/taocrypt/src/rsa.cpp
new file mode 100644
index 00000000000..fdc70d4a7cf
--- /dev/null
+++ b/extra/yassl/taocrypt/src/rsa.cpp
@@ -0,0 +1,215 @@
+/* rsa.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's rsa.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include "rsa.hpp"
+#include "asn.hpp"
+#include "modarith.hpp"
+#include "stdexcept.hpp"
+
+#include "algebra.cpp" // for GCC 3.2 on aix ?
+
+
+namespace TaoCrypt {
+
+
+Integer RSA_PublicKey::ApplyFunction(const Integer& x) const
+{
+ return a_exp_b_mod_c(x, e_, n_);
+}
+
+
+RSA_PublicKey::RSA_PublicKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void RSA_PublicKey::Initialize(Source& source)
+{
+ RSA_Public_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+Integer RSA_PrivateKey::CalculateInverse(RandomNumberGenerator& rng,
+ const Integer& x) const
+{
+ ModularArithmetic modn(n_);
+
+ Integer r(rng, Integer::One(), n_ - Integer::One());
+ Integer re = modn.Exponentiate(r, e_);
+ re = modn.Multiply(re, x); // blind
+
+ // here we follow the notation of PKCS #1 and let u=q inverse mod p
+ // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q
+
+ Integer y = ModularRoot(re, dq_, dp_, q_, p_, u_);
+ y = modn.Divide(y, r); // unblind
+ assert(modn.Exponentiate(y, e_) == x); // check
+
+ return y;
+}
+
+
+RSA_PrivateKey::RSA_PrivateKey(Source& source)
+{
+ Initialize(source);
+}
+
+
+void RSA_PrivateKey::Initialize(Source& source)
+{
+ RSA_Private_Decoder decoder(source);
+ decoder.Decode(*this);
+}
+
+
+void RSA_BlockType2::Pad(const byte *input, word32 inputLen, byte *pkcsBlock,
+ word32 pkcsBlockLen, RandomNumberGenerator& rng) const
+{
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ pkcsBlock[0] = 0;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ pkcsBlock[0] = 2; // block type 2
+
+ // pad with non-zero random bytes
+ word32 padLen = pkcsBlockLen - inputLen - 1;
+ rng.GenerateBlock(&pkcsBlock[1], padLen);
+ for (word32 i = 1; i < padLen; i++)
+ if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
+ memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+}
+
+word32 RSA_BlockType2::UnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
+ byte *output) const
+{
+ bool invalid = false;
+ unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U);
+
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ invalid = (pkcsBlock[0] != 0) || invalid;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ // Require block type 2.
+ invalid = (pkcsBlock[0] != 2) || invalid;
+
+ // skip past the padding until we find the separator
+ unsigned i=1;
+ while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
+ }
+ assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
+
+ unsigned int outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid)
+ return 0;
+
+ memcpy (output, pkcsBlock+i, outputLen);
+ return outputLen;
+}
+
+
+void RSA_BlockType1::Pad(const byte* input, word32 inputLen, byte* pkcsBlock,
+ word32 pkcsBlockLen, RandomNumberGenerator&) const
+{
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ pkcsBlock[0] = 0;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ pkcsBlock[0] = 1; // block type 1 for SSL
+
+ // pad with 0xff bytes
+ memset(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
+
+ pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
+ memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
+}
+
+
+word32 RSA_BlockType1::UnPad(const byte* pkcsBlock, word32 pkcsBlockLen,
+ byte* output) const
+{
+ bool invalid = false;
+ unsigned int maxOutputLen = SaturatingSubtract(pkcsBlockLen / 8, 10U);
+
+ // convert from bit length to byte length
+ if (pkcsBlockLen % 8 != 0)
+ {
+ invalid = (pkcsBlock[0] != 0) || invalid;
+ pkcsBlock++;
+ }
+ pkcsBlockLen /= 8;
+
+ // Require block type 1 for SSL.
+ invalid = (pkcsBlock[0] != 1) || invalid;
+
+ // skip past the padding until we find the separator
+ unsigned i=1;
+ while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
+ }
+ assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
+
+ unsigned int outputLen = pkcsBlockLen - i;
+ invalid = (outputLen > maxOutputLen) || invalid;
+
+ if (invalid)
+ return 0;
+
+ memcpy(output, pkcsBlock+i, outputLen);
+ return outputLen;
+}
+
+
+word32 SSL_Decrypt(const RSA_PublicKey& key, const byte* sig, byte* plain)
+{
+ PK_Lengths lengths(key.GetModulus());
+
+ ByteBlock paddedBlock(BitsToBytes(lengths.PaddedBlockBitLength()));
+ Integer x = key.ApplyFunction(Integer(sig,
+ lengths.FixedCiphertextLength()));
+ if (x.ByteCount() > paddedBlock.size())
+ x = Integer::Zero();
+ x.Encode(paddedBlock.get_buffer(), paddedBlock.size());
+ return RSA_BlockType1().UnPad(paddedBlock.get_buffer(),
+ lengths.PaddedBlockBitLength(), plain);
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp
new file mode 100644
index 00000000000..4dfd2c3f3db
--- /dev/null
+++ b/extra/yassl/taocrypt/src/sha.cpp
@@ -0,0 +1,144 @@
+/* sha.cpp
+ *
+ * Copyright (C) 2003 Sawtooth Consulting Ltd.
+ *
+ * This file is part of yaSSL.
+ *
+ * yaSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * yaSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* based on Wei Dai's sha.cpp from CryptoPP */
+
+#include "runtime.hpp"
+#include <string.h>
+#include "algorithm.hpp" // mySTL::swap
+#include "sha.hpp"
+
+
+namespace TaoCrypt {
+
+#define blk0(i) (W[i] = (*reinterpret_cast<word32*>(&buffer_[i*4])))
+#define blk1(i) (W[i&15] = \
+ rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
+
+#define f1(x,y,z) (z^(x &(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+
+// (R0+R1), R2, R3, R4 are the different operations used in SHA1
+#define R0(v,w,x,y,z,i) z+= f1(w,x,y) + blk0(i) + 0x5A827999+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R1(v,w,x,y,z,i) z+= f1(w,x,y) + blk1(i) + 0x5A827999+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R2(v,w,x,y,z,i) z+= f2(w,x,y) + blk1(i) + 0x6ED9EBA1+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R3(v,w,x,y,z,i) z+= f3(w,x,y) + blk1(i) + 0x8F1BBCDC+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+#define R4(v,w,x,y,z,i) z+= f4(w,x,y) + blk1(i) + 0xCA62C1D6+ \
+ rotlFixed(v,5); w = rotlFixed(w,30);
+
+
+void SHA::Init()
+{
+ digest_[0] = 0x67452301L;
+ digest_[1] = 0xEFCDAB89L;
+ digest_[2] = 0x98BADCFEL;
+ digest_[3] = 0x10325476L;
+ digest_[4] = 0xC3D2E1F0L;
+
+ buffLen_ = 0;
+ length_ = 0;
+}
+
+
+SHA::SHA(const SHA& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
+ BLOCK_SIZE)
+{
+ buffLen_ = that.buffLen_;
+ length_ = that.length_;
+
+ memcpy(digest_, that.digest_, DIGEST_SIZE);
+ memcpy(buffer_, that.buffer_, BLOCK_SIZE);
+}
+
+SHA& SHA::operator= (const SHA& that)
+{
+ SHA tmp(that);
+ Swap(tmp);
+
+ return *this;
+}
+
+
+void SHA::Swap(SHA& other)
+{
+ mySTL::swap(buffer_, other.buffer_);
+ mySTL::swap(buffLen_, other.buffLen_);
+ mySTL::swap(digest_, other.digest_);
+ mySTL::swap(length_, other.length_);
+}
+
+
+void SHA::Transform()
+{
+ word32 W[BLOCK_SIZE / sizeof(word32)];
+
+ // Copy context->state[] to working vars
+ word32 a = digest_[0];
+ word32 b = digest_[1];
+ word32 c = digest_[2];
+ word32 d = digest_[3];
+ word32 e = digest_[4];
+
+ // 4 rounds of 20 operations each. Loop unrolled.
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ // Add the working vars back into digest state[]
+ digest_[0] += a;
+ digest_[1] += b;
+ digest_[2] += c;
+ digest_[3] += d;
+ digest_[4] += e;
+
+ // Wipe variables
+ a = b = c = d = e = 0;
+ memset(W, 0, sizeof(W));
+
+ buffLen_ = 0;
+ length_ += 512;
+}
+
+
+} // namespace
diff --git a/extra/yassl/taocrypt/taocrypt.dsp b/extra/yassl/taocrypt/taocrypt.dsp
new file mode 100644
index 00000000000..115ad0cb272
--- /dev/null
+++ b/extra/yassl/taocrypt/taocrypt.dsp
@@ -0,0 +1,260 @@
+# Microsoft Developer Studio Project File - Name="taocrypt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=taocrypt - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "taocrypt.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "taocrypt.mak" CFG="taocrypt - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "taocrypt - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "taocrypt - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "taocrypt - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "taocrypt___Win32_Release"
+# PROP BASE Intermediate_Dir "taocrypt___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX- /O2 /I "include" /I "..\mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "taocrypt - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "taocrypt___Win32_Debug"
+# PROP BASE Intermediate_Dir "taocrypt___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX- /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "taocrypt - Win32 Release"
+# Name "taocrypt - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\aes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\aestables.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\algebra.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\arc4.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\asn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\coding.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\des.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\dh.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\dsa.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\file.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\hash.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\integer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\md2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\md5.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\misc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\random.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ripemd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\rsa.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\sha.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\include\aes.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\algebra.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\arc4.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\asn.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\block.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\coding.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\des.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\dh.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\dsa.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\error.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\file.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\hash.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\hmac.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\integer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\md2.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\md5.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\misc.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\modarith.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\modes.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\random.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\ripemd.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\rsa.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\sha.hpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extra/yassl/taocrypt/taocrypt.dsw b/extra/yassl/taocrypt/taocrypt.dsw
new file mode 100644
index 00000000000..d10d7534c3d
--- /dev/null
+++ b/extra/yassl/taocrypt/taocrypt.dsw
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "taocrypt"=.\taocrypt.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "test"=.\test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/extra/yassl/yassl.dsp b/extra/yassl/yassl.dsp
new file mode 100644
index 00000000000..f51c19eebbf
--- /dev/null
+++ b/extra/yassl/yassl.dsp
@@ -0,0 +1,192 @@
+# Microsoft Developer Studio Project File - Name="yassl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=yassl - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "yassl.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "yassl.mak" CFG="yassl - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "yassl - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "yassl - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "yassl - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX- /O2 /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "yassl - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX- /ZI /Od /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "yassl - Win32 Release"
+# Name "yassl - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\buffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\cert_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\crypto_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\handshake.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\lock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\log.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\socket_wrapper.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ssl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\timer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_imp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\yassl_int.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\include\buffer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\cert_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\crypto_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\factory.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\handshake.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\lock.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\log.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\socket_wrapper.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\timer.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_error.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_imp.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_int.hpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\yassl_types.hpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/extra/yassl/yassl.dsw b/extra/yassl/yassl.dsw
new file mode 100644
index 00000000000..c0bba9acdce
--- /dev/null
+++ b/extra/yassl/yassl.dsw
@@ -0,0 +1,137 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "client"=.\examples\client\client.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "echoclient"=.\examples\echoclient\echoclient.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "echoserver"=.\examples\echoserver\echoserver.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "server"=.\examples\server\server.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "taocrypt"=.\taocrypt\taocrypt.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "test"=.\taocrypt\test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "testsuite"=.\testsuite\testsuite.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name yassl
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "yassl"=.\yassl.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name taocrypt
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+