summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README18
-rw-r--r--axTLS/axTLS.vcproj291
-rw-r--r--axTLS/configured/config.h126
-rw-r--r--axTLS/src/README3
-rw-r--r--axTLS/src/crypto/aes.c457
-rw-r--r--axTLS/src/crypto/bigint.c1512
-rw-r--r--axTLS/src/crypto/bigint.h99
-rw-r--r--axTLS/src/crypto/bigint_impl.h131
-rw-r--r--axTLS/src/crypto/crypto.h229
-rw-r--r--axTLS/src/crypto/crypto_misc.c370
-rw-r--r--axTLS/src/crypto/hmac.c105
-rw-r--r--axTLS/src/crypto/md2.c162
-rw-r--r--axTLS/src/crypto/md5.c294
-rw-r--r--axTLS/src/crypto/rc4.c92
-rw-r--r--axTLS/src/crypto/rsa.c269
-rw-r--r--axTLS/src/crypto/sha1.c249
-rw-r--r--axTLS/src/ssl/asn1.c565
-rw-r--r--axTLS/src/ssl/cert.h43
-rw-r--r--axTLS/src/ssl/crypto_misc.h173
-rw-r--r--axTLS/src/ssl/gen_cert.c364
-rw-r--r--axTLS/src/ssl/loader.c478
-rw-r--r--axTLS/src/ssl/openssl.c323
-rw-r--r--axTLS/src/ssl/os_port.c158
-rw-r--r--axTLS/src/ssl/os_port.h208
-rw-r--r--axTLS/src/ssl/p12.c483
-rw-r--r--axTLS/src/ssl/private_key.h54
-rw-r--r--axTLS/src/ssl/ssl.h499
-rw-r--r--axTLS/src/ssl/tls1.c2195
-rw-r--r--axTLS/src/ssl/tls1.h295
-rw-r--r--axTLS/src/ssl/tls1_clnt.c395
-rw-r--r--axTLS/src/ssl/tls1_svr.c478
-rw-r--r--axTLS/src/ssl/version.h1
-rw-r--r--axTLS/src/ssl/x509.c564
-rw-r--r--axTLS/src/www/index.html7106
-rw-r--r--json-c/json-c.vcproj4
-rw-r--r--pianobar.sln14
-rw-r--r--pianobar/pianobar.vcproj4
m---------pianobar/src0
-rw-r--r--polarssl/polarssl.vcproj494
-rw-r--r--polarssl/src/LICENSE339
-rw-r--r--polarssl/src/include/polarssl/aes.h176
-rw-r--r--polarssl/src/include/polarssl/arc4.h80
-rw-r--r--polarssl/src/include/polarssl/asn1.h246
-rw-r--r--polarssl/src/include/polarssl/asn1write.h46
-rw-r--r--polarssl/src/include/polarssl/base64.h87
-rw-r--r--polarssl/src/include/polarssl/bignum.h632
-rw-r--r--polarssl/src/include/polarssl/bn_mul.h742
-rw-r--r--polarssl/src/include/polarssl/camellia.h182
-rw-r--r--polarssl/src/include/polarssl/certs.h47
-rw-r--r--polarssl/src/include/polarssl/cipher.h459
-rw-r--r--polarssl/src/include/polarssl/cipher_wrap.h95
-rw-r--r--polarssl/src/include/polarssl/config.h744
-rw-r--r--polarssl/src/include/polarssl/ctr_drbg.h228
-rw-r--r--polarssl/src/include/polarssl/debug.h89
-rw-r--r--polarssl/src/include/polarssl/des.h227
-rw-r--r--polarssl/src/include/polarssl/dhm.h153
-rw-r--r--polarssl/src/include/polarssl/entropy.h150
-rw-r--r--polarssl/src/include/polarssl/entropy_poll.h75
-rw-r--r--polarssl/src/include/polarssl/error.h102
-rw-r--r--polarssl/src/include/polarssl/gcm.h142
-rw-r--r--polarssl/src/include/polarssl/havege.h71
-rw-r--r--polarssl/src/include/polarssl/md.h354
-rw-r--r--polarssl/src/include/polarssl/md2.h153
-rw-r--r--polarssl/src/include/polarssl/md4.h152
-rw-r--r--polarssl/src/include/polarssl/md5.h154
-rw-r--r--polarssl/src/include/polarssl/md_wrap.h64
-rw-r--r--polarssl/src/include/polarssl/net.h159
-rw-r--r--polarssl/src/include/polarssl/openssl.h136
-rw-r--r--polarssl/src/include/polarssl/padlock.h100
-rw-r--r--polarssl/src/include/polarssl/pem.h100
-rw-r--r--polarssl/src/include/polarssl/pkcs11.h126
-rw-r--r--polarssl/src/include/polarssl/rsa.h379
-rw-r--r--polarssl/src/include/polarssl/sha1.h152
-rw-r--r--polarssl/src/include/polarssl/sha2.h160
-rw-r--r--polarssl/src/include/polarssl/sha4.h168
-rw-r--r--polarssl/src/include/polarssl/ssl.h766
-rw-r--r--polarssl/src/include/polarssl/timing.h75
-rw-r--r--polarssl/src/include/polarssl/version.h81
-rw-r--r--polarssl/src/include/polarssl/x509.h733
-rw-r--r--polarssl/src/include/polarssl/x509write.h46
-rw-r--r--polarssl/src/include/polarssl/xtea.h111
-rw-r--r--polarssl/src/library/aes.c1346
-rw-r--r--polarssl/src/library/arc4.c169
-rw-r--r--polarssl/src/library/asn1parse.c260
-rw-r--r--polarssl/src/library/asn1write.c241
-rw-r--r--polarssl/src/library/base64.c254
-rw-r--r--polarssl/src/library/bignum.c2111
-rw-r--r--polarssl/src/library/camellia.c1032
-rw-r--r--polarssl/src/library/certs.c196
-rw-r--r--polarssl/src/library/cipher.c557
-rw-r--r--polarssl/src/library/cipher_wrap.c595
-rw-r--r--polarssl/src/library/ctr_drbg.c562
-rw-r--r--polarssl/src/library/debug.c238
-rw-r--r--polarssl/src/library/des.c993
-rw-r--r--polarssl/src/library/dhm.c296
-rw-r--r--polarssl/src/library/entropy.c204
-rw-r--r--polarssl/src/library/entropy_poll.c136
-rw-r--r--polarssl/src/library/error.c525
-rw-r--r--polarssl/src/library/gcm.c653
-rw-r--r--polarssl/src/library/havege.c231
-rw-r--r--polarssl/src/library/md.c297
-rw-r--r--polarssl/src/library/md2.c364
-rw-r--r--polarssl/src/library/md4.c460
-rw-r--r--polarssl/src/library/md5.c583
-rw-r--r--polarssl/src/library/md_wrap.c733
-rw-r--r--polarssl/src/library/net.c358
-rw-r--r--polarssl/src/library/padlock.c162
-rw-r--r--polarssl/src/library/pem.c352
-rw-r--r--polarssl/src/library/pkcs11.c238
-rw-r--r--polarssl/src/library/rsa.c1219
-rw-r--r--polarssl/src/library/sha1.c624
-rw-r--r--polarssl/src/library/sha2.c705
-rw-r--r--polarssl/src/library/sha4.c760
-rw-r--r--polarssl/src/library/ssl_cli.c1130
-rw-r--r--polarssl/src/library/ssl_srv.c1080
-rw-r--r--polarssl/src/library/ssl_tls.c3166
-rw-r--r--polarssl/src/library/timing.c271
-rw-r--r--polarssl/src/library/version.c50
-rw-r--r--polarssl/src/library/x509parse.c3425
-rw-r--r--polarssl/src/library/x509write.c287
-rw-r--r--polarssl/src/library/xtea.c248
121 files changed, 36907 insertions, 18790 deletions
diff --git a/README b/README
index b26c169..c4ca393 100644
--- a/README
+++ b/README
@@ -1,6 +1,9 @@
pianobar for Windows - build environment
========
+*Binaries* in the form of *standalone* executable ara available at:
+https://github.com/thedmd/pianobar-windows-binaries
+
pianobar is a console client for the personalized web radio pandora
(http://www.pandora.com). Source code of the original project can be found at
at http://github.com/PromyLOPh/pianobar/ or http://6xq.net/projects/pianobar/
@@ -12,12 +15,11 @@ found at https://github.com/thedmd/pianobar-windows/
Solution files for Microsoft Visual Studio 2008 are available and allow building
pianobar in clean environment.
-Source code of four libraries is included:
- - axTLS - modified version, which generate SHA-1 fingerprint for certificates
- - libao - unmodified, but stripped from unnecessary files
- - libmad - unmodified, but stripped from unnecessary files
- - pthreads-win32 - unmodified, but stripped from unnecessary files
-
+Source code of included libraries:
+ - PolarSSL
+ - libao
+ - libmad
+ - pthreads-win32
+ - json-c
+ - blowfish - modified Paul Kocher sources, available at http://www.schneier.com/blowfish-download.html
-Binaries of this project can be found at:
-https://github.com/thedmd/pianobar-windows-binaries \ No newline at end of file
diff --git a/axTLS/axTLS.vcproj b/axTLS/axTLS.vcproj
deleted file mode 100644
index 5c8b94b..0000000
--- a/axTLS/axTLS.vcproj
+++ /dev/null
@@ -1,291 +0,0 @@
-<?xml version="1.0" encoding="windows-1250"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9,00"
- Name="axTLS"
- ProjectGUID="{3A871221-4317-4839-80D9-C2F03DED1AF8}"
- RootNamespace="axTLS"
- Keyword="Win32Proj"
- TargetFrameworkVersion="131072"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(SolutionDir)build\temp\lib\"
- IntermediateDirectory="$(SolutionDir)build\temp\obj\$(ProjectName)\$(ConfigurationName)"
- ConfigurationType="4"
- CharacterSet="0"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="&quot;$(ProjectDir)configured\&quot;;&quot;$(ProjectDir)src\crypto\&quot;;&quot;$(ProjectDir)src\ssl\&quot;"
- PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
- MinimalRebuild="false"
- ExceptionHandling="0"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- UsePrecompiledHeader="0"
- ProgramDataBaseFileName="$(IntDir)\vc90.pdb"
- WarningLevel="3"
- DebugInformationFormat="1"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- OutputFile="$(OutDir)\$(ProjectName)-mt-debug.lib"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- CommandLine="xcopy &quot;$(ProjectDir)src\ssl\ssl.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\ssl\tls1.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\ssl\version.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\ssl\crypto_misc.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\crypto\crypto.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\crypto\bigint.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\crypto\bigint_impl.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)configured\config.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;&#x0D;&#x0A;&#x0D;&#x0A;"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(SolutionDir)build\temp\lib\"
- IntermediateDirectory="$(SolutionDir)build\temp\obj\$(ProjectName)\$(ConfigurationName)"
- ConfigurationType="4"
- CharacterSet="0"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="&quot;$(ProjectDir)configured\&quot;;&quot;$(ProjectDir)src\crypto\&quot;;&quot;$(ProjectDir)src\ssl\&quot;"
- PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
- ExceptionHandling="0"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- UsePrecompiledHeader="0"
- ProgramDataBaseFileName="$(IntDir)\vc90.pdb"
- WarningLevel="3"
- DebugInformationFormat="0"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- OutputFile="$(OutDir)\$(ProjectName)-mt.lib"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- CommandLine="xcopy &quot;$(ProjectDir)src\ssl\ssl.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\ssl\tls1.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\ssl\version.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\ssl\crypto_misc.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\crypto\crypto.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\crypto\bigint.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\crypto\bigint_impl.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)configured\config.h&quot; &quot;$(SolutionDir)build\temp\include\axTLS\&quot; /I /Y /D&#x0D;&#x0A;&#x0D;&#x0A;&#x0D;&#x0A;"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="ssl"
- >
- <File
- RelativePath=".\src\ssl\asn1.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\cert.h"
- >
- </File>
- <File
- RelativePath=".\src\ssl\crypto_misc.h"
- >
- </File>
- <File
- RelativePath=".\src\ssl\gen_cert.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\loader.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\openssl.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\os_port.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\os_port.h"
- >
- </File>
- <File
- RelativePath=".\src\ssl\p12.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\private_key.h"
- >
- </File>
- <File
- RelativePath=".\src\ssl\ssl.h"
- >
- </File>
- <File
- RelativePath=".\src\ssl\tls1.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\tls1.h"
- >
- </File>
- <File
- RelativePath=".\src\ssl\tls1_clnt.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\tls1_svr.c"
- >
- </File>
- <File
- RelativePath=".\src\ssl\version.h"
- >
- </File>
- <File
- RelativePath=".\src\ssl\x509.c"
- >
- </File>
- </Filter>
- <Filter
- Name="crypto"
- >
- <File
- RelativePath=".\src\crypto\aes.c"
- >
- </File>
- <File
- RelativePath=".\src\crypto\bigint.c"
- >
- </File>
- <File
- RelativePath=".\src\crypto\bigint.h"
- >
- </File>
- <File
- RelativePath=".\src\crypto\bigint_impl.h"
- >
- </File>
- <File
- RelativePath=".\src\crypto\crypto.h"
- >
- </File>
- <File
- RelativePath=".\src\crypto\crypto_misc.c"
- >
- </File>
- <File
- RelativePath=".\src\crypto\hmac.c"
- >
- </File>
- <File
- RelativePath=".\src\crypto\md2.c"
- >
- </File>
- <File
- RelativePath=".\src\crypto\md5.c"
- >
- </File>
- <File
- RelativePath=".\src\crypto\rc4.c"
- >
- </File>
- <File
- RelativePath=".\src\crypto\rsa.c"
- >
- </File>
- <File
- RelativePath=".\src\crypto\sha1.c"
- >
- </File>
- </Filter>
- <Filter
- Name="configured"
- >
- <File
- RelativePath=".\configured\config.h"
- >
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/axTLS/configured/config.h b/axTLS/configured/config.h
deleted file mode 100644
index a64d3cd..0000000
--- a/axTLS/configured/config.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Automatically generated header file: don't edit
- */
-
-#define HAVE_DOT_CONFIG 1
-#undef CONFIG_PLATFORM_LINUX
-#undef CONFIG_PLATFORM_CYGWIN
-#define CONFIG_PLATFORM_WIN32 1
-
-/*
- * General Configuration
- */
-#define PREFIX ""
-#undef CONFIG_DEBUG
-#undef CONFIG_STRIP_UNWANTED_SECTIONS
-
-/*
- * Microsoft Compiler Options
- */
-/*
-#undef CONFIG_VISUAL_STUDIO_7_0
-#undef CONFIG_VISUAL_STUDIO_8_0
-#define CONFIG_VISUAL_STUDIO_9_0 1
-#define CONFIG_VISUAL_STUDIO_7_0_BASE ""
-#define CONFIG_VISUAL_STUDIO_8_0_BASE ""
-#define CONFIG_VISUAL_STUDIO_9_0_BASE "c:\\Program Files\\Microsoft Visual Studio 9.0"
-#define CONFIG_EXTRA_CFLAGS_OPTIONS ""
-#define CONFIG_EXTRA_LDFLAGS_OPTIONS ""
-*/
-
-/*
- * SSL Library
- */
-#undef CONFIG_SSL_SERVER_ONLY
-#undef CONFIG_SSL_CERT_VERIFICATION
-#define CONFIG_SSL_ENABLE_CLIENT
-#define CONFIG_SSL_FULL_MODE 1
-#undef CONFIG_SSL_SKELETON_MODE
-#undef CONFIG_SSL_PROT_LOW
-#define CONFIG_SSL_PROT_MEDIUM 1
-#undef CONFIG_SSL_PROT_HIGH
-#define CONFIG_SSL_USE_DEFAULT_KEY 1
-#define CONFIG_SSL_PRIVATE_KEY_LOCATION ""
-#define CONFIG_SSL_PRIVATE_KEY_PASSWORD ""
-#define CONFIG_SSL_X509_CERT_LOCATION ""
-#undef CONFIG_SSL_GENERATE_X509_CERT
-#define CONFIG_SSL_X509_COMMON_NAME ""
-#define CONFIG_SSL_X509_ORGANIZATION_NAME ""
-#define CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME ""
-#define CONFIG_SSL_ENABLE_V23_HANDSHAKE 1
-#define CONFIG_SSL_HAS_PEM 1
-#define CONFIG_SSL_USE_PKCS12 1
-#define CONFIG_SSL_EXPIRY_TIME 24
-#define CONFIG_X509_MAX_CA_CERTS 150
-#define CONFIG_SSL_MAX_CERTS 3
-#undef CONFIG_SSL_CTX_MUTEXING
-#undef CONFIG_USE_DEV_URANDOM
-//#define CONFIG_WIN32_USE_CRYPTO_LIB 1
-#undef CONFIG_WIN32_USE_CRYPTO_LIB
-#undef CONFIG_OPENSSL_COMPATIBLE
-#undef CONFIG_PERFORMANCE_TESTING
-#undef CONFIG_SSL_TEST
-#undef CONFIG_AXTLSWRAP
-#undef CONFIG_AXHTTPD
-#undef CONFIG_HTTP_STATIC_BUILD
-#define CONFIG_HTTP_PORT
-#define CONFIG_HTTP_HTTPS_PORT
-#define CONFIG_HTTP_SESSION_CACHE_SIZE
-#define CONFIG_HTTP_WEBROOT ""
-#define CONFIG_HTTP_TIMEOUT
-#undef CONFIG_HTTP_HAS_CGI
-#define CONFIG_HTTP_CGI_EXTENSIONS ""
-#undef CONFIG_HTTP_ENABLE_LUA
-#define CONFIG_HTTP_LUA_PREFIX ""
-#undef CONFIG_HTTP_BUILD_LUA
-#define CONFIG_HTTP_CGI_LAUNCHER ""
-#undef CONFIG_HTTP_DIRECTORIES
-#undef CONFIG_HTTP_HAS_AUTHORIZATION
-#undef CONFIG_HTTP_HAS_IPV6
-#undef CONFIG_HTTP_ENABLE_DIFFERENT_USER
-#define CONFIG_HTTP_USER ""
-#undef CONFIG_HTTP_VERBOSE
-#undef CONFIG_HTTP_IS_DAEMON
-
-/*
- * Language Bindings
- */
-#undef CONFIG_BINDINGS
-#undef CONFIG_CSHARP_BINDINGS
-#undef CONFIG_VBNET_BINDINGS
-#define CONFIG_DOT_NET_FRAMEWORK_BASE ""
-#undef CONFIG_JAVA_BINDINGS
-#define CONFIG_JAVA_HOME ""
-#undef CONFIG_PERL_BINDINGS
-#define CONFIG_PERL_CORE ""
-#define CONFIG_PERL_LIB ""
-#undef CONFIG_LUA_BINDINGS
-#define CONFIG_LUA_CORE ""
-
-/*
- * Samples
- */
-#undef CONFIG_SAMPLES
-#undef CONFIG_C_SAMPLES
-#undef CONFIG_CSHARP_SAMPLES
-#undef CONFIG_VBNET_SAMPLES
-#undef CONFIG_JAVA_SAMPLES
-#undef CONFIG_PERL_SAMPLES
-#undef CONFIG_LUA_SAMPLES
-
-/*
- * BigInt Options
- */
-#undef CONFIG_BIGINT_CLASSICAL
-#undef CONFIG_BIGINT_MONTGOMERY
-#define CONFIG_BIGINT_BARRETT 1
-#define CONFIG_BIGINT_CRT 1
-#undef CONFIG_BIGINT_KARATSUBA
-#define MUL_KARATSUBA_THRESH
-#define SQU_KARATSUBA_THRESH
-#define CONFIG_BIGINT_SLIDING_WINDOW 1
-#define CONFIG_BIGINT_SQUARE 1
-#undef CONFIG_BIGINT_CHECK_ON
-#define CONFIG_INTEGER_32BIT 1
-#undef CONFIG_INTEGER_16BIT
-#undef CONFIG_INTEGER_8BIT
diff --git a/axTLS/src/README b/axTLS/src/README
deleted file mode 100644
index c8926d9..0000000
--- a/axTLS/src/README
+++ /dev/null
@@ -1,3 +0,0 @@
-
-See www/index.html for the README, CHANGELOG, LICENSE and other notes.
-
diff --git a/axTLS/src/crypto/aes.c b/axTLS/src/crypto/aes.c
deleted file mode 100644
index 9b07e27..0000000
--- a/axTLS/src/crypto/aes.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * AES implementation - this is a small code version. There are much faster
- * versions around but they are much larger in size (i.e. they use large
- * submix tables).
- */
-
-#include <string.h>
-#include "os_port.h"
-#include "crypto.h"
-
-/* all commented out in skeleton mode */
-#ifndef CONFIG_SSL_SKELETON_MODE
-
-#define rot1(x) (((x) << 24) | ((x) >> 8))
-#define rot2(x) (((x) << 16) | ((x) >> 16))
-#define rot3(x) (((x) << 8) | ((x) >> 24))
-
-/*
- * This cute trick does 4 'mul by two' at once. Stolen from
- * Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
- * a standard graphics trick
- * The key to this is that we need to xor with 0x1b if the top bit is set.
- * a 1xxx xxxx 0xxx 0xxx First we mask the 7bit,
- * b 1000 0000 0000 0000 then we shift right by 7 putting the 7bit in 0bit,
- * c 0000 0001 0000 0000 we then subtract (c) from (b)
- * d 0111 1111 0000 0000 and now we and with our mask
- * e 0001 1011 0000 0000
- */
-#define mt 0x80808080
-#define ml 0x7f7f7f7f
-#define mh 0xfefefefe
-#define mm 0x1b1b1b1b
-#define mul2(x,t) ((t)=((x)&mt), \
- ((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
-
-#define inv_mix_col(x,f2,f4,f8,f9) (\
- (f2)=mul2(x,f2), \
- (f4)=mul2(f2,f4), \
- (f8)=mul2(f4,f8), \
- (f9)=(x)^(f8), \
- (f8)=((f2)^(f4)^(f8)), \
- (f2)^=(f9), \
- (f4)^=(f9), \
- (f8)^=rot3(f2), \
- (f8)^=rot2(f4), \
- (f8)^rot1(f9))
-
-/*
- * AES S-box
- */
-static const uint8_t aes_sbox[256] =
-{
- 0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
- 0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
- 0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
- 0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
- 0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
- 0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
- 0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
- 0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
- 0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
- 0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
- 0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
- 0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
- 0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
- 0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
- 0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
- 0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
- 0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
- 0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
- 0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
- 0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
- 0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
- 0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
- 0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
- 0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
- 0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
- 0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
- 0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
- 0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
- 0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
- 0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
- 0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
- 0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
-};
-
-/*
- * AES is-box
- */
-static const uint8_t aes_isbox[256] =
-{
- 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
- 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
- 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
- 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
- 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
- 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
- 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
- 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
- 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
- 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
- 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
- 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
- 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
- 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
- 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
- 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
- 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
- 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
- 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
- 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
- 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
- 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
- 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
- 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
- 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
- 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
- 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
- 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
- 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
- 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
- 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
- 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
-};
-
-static const unsigned char Rcon[30]=
-{
- 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
- 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
- 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
- 0xb3,0x7d,0xfa,0xef,0xc5,0x91,
-};
-
-/* ----- static functions ----- */
-static void AES_encrypt(const AES_CTX *ctx, uint32_t *data);
-static void AES_decrypt(const AES_CTX *ctx, uint32_t *data);
-
-/* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
- x^8+x^4+x^3+x+1 */
-static unsigned char AES_xtime(uint32_t x)
-{
- return (x&0x80) ? (x<<1)^0x1b : x<<1;
-}
-
-/**
- * Set up AES with the key/iv and cipher size.
- */
-void AES_set_key(AES_CTX *ctx, const uint8_t *key,
- const uint8_t *iv, AES_MODE mode)
-{
- int i, ii;
- uint32_t *W, tmp, tmp2;
- const unsigned char *ip;
- int words;
-
- switch (mode)
- {
- case AES_MODE_128:
- i = 10;
- words = 4;
- break;
-
- case AES_MODE_256:
- i = 14;
- words = 8;
- break;
-
- default: /* fail silently */
- return;
- }
-
- ctx->rounds = i;
- ctx->key_size = words;
- W = ctx->ks;
- for (i = 0; i < words; i+=2)
- {
- W[i+0]= ((uint32_t)key[ 0]<<24)|
- ((uint32_t)key[ 1]<<16)|
- ((uint32_t)key[ 2]<< 8)|
- ((uint32_t)key[ 3] );
- W[i+1]= ((uint32_t)key[ 4]<<24)|
- ((uint32_t)key[ 5]<<16)|
- ((uint32_t)key[ 6]<< 8)|
- ((uint32_t)key[ 7] );
- key += 8;
- }
-
- ip = Rcon;
- ii = 4 * (ctx->rounds+1);
- for (i = words; i<ii; i++)
- {
- tmp = W[i-1];
-
- if ((i % words) == 0)
- {
- tmp2 =(uint32_t)aes_sbox[(tmp )&0xff]<< 8;
- tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
- tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
- tmp2|=(uint32_t)aes_sbox[(tmp>>24) ];
- tmp=tmp2^(((unsigned int)*ip)<<24);
- ip++;
- }
-
- if ((words == 8) && ((i % words) == 4))
- {
- tmp2 =(uint32_t)aes_sbox[(tmp )&0xff] ;
- tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
- tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
- tmp2|=(uint32_t)aes_sbox[(tmp>>24) ]<<24;
- tmp=tmp2;
- }
-
- W[i]=W[i-words]^tmp;
- }
-
- /* copy the iv across */
- memcpy(ctx->iv, iv, 16);
-}
-
-/**
- * Change a key for decryption.
- */
-void AES_convert_key(AES_CTX *ctx)
-{
- int i;
- uint32_t *k,w,t1,t2,t3,t4;
-
- k = ctx->ks;
- k += 4;
-
- for (i= ctx->rounds*4; i > 4; i--)
- {
- w= *k;
- w = inv_mix_col(w,t1,t2,t3,t4);
- *k++ =w;
- }
-}
-
-/**
- * Encrypt a byte sequence (with a block size 16) using the AES cipher.
- */
-void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
-{
- int i;
- uint32_t tin[4], tout[4], iv[4];
-
- memcpy(iv, ctx->iv, AES_IV_SIZE);
- for (i = 0; i < 4; i++)
- tout[i] = ntohl(iv[i]);
-
- for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE)
- {
- uint32_t msg_32[4];
- uint32_t out_32[4];
- memcpy(msg_32, msg, AES_BLOCKSIZE);
- msg += AES_BLOCKSIZE;
-
- for (i = 0; i < 4; i++)
- tin[i] = ntohl(msg_32[i])^tout[i];
-
- AES_encrypt(ctx, tin);
-
- for (i = 0; i < 4; i++)
- {
- tout[i] = tin[i];
- out_32[i] = htonl(tout[i]);
- }
-
- memcpy(out, out_32, AES_BLOCKSIZE);
- out += AES_BLOCKSIZE;
- }
-
- for (i = 0; i < 4; i++)
- iv[i] = htonl(tout[i]);
- memcpy(ctx->iv, iv, AES_IV_SIZE);
-}
-
-/**
- * Decrypt a byte sequence (with a block size 16) using the AES cipher.
- */
-void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
-{
- int i;
- uint32_t tin[4], xor[4], tout[4], data[4], iv[4];
-
- memcpy(iv, ctx->iv, AES_IV_SIZE);
- for (i = 0; i < 4; i++)
- xor[i] = ntohl(iv[i]);
-
- for (length -= 16; length >= 0; length -= 16)
- {
- uint32_t msg_32[4];
- uint32_t out_32[4];
- memcpy(msg_32, msg, AES_BLOCKSIZE);
- msg += AES_BLOCKSIZE;
-
- for (i = 0; i < 4; i++)
- {
- tin[i] = ntohl(msg_32[i]);
- data[i] = tin[i];
- }
-
- AES_decrypt(ctx, data);
-
- for (i = 0; i < 4; i++)
- {
- tout[i] = data[i]^xor[i];
- xor[i] = tin[i];
- out_32[i] = htonl(tout[i]);
- }
-
- memcpy(out, out_32, AES_BLOCKSIZE);
- out += AES_BLOCKSIZE;
- }
-
- for (i = 0; i < 4; i++)
- iv[i] = htonl(xor[i]);
- memcpy(ctx->iv, iv, AES_IV_SIZE);
-}
-
-/**
- * Encrypt a single block (16 bytes) of data
- */
-static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
-{
- /* To make this code smaller, generate the sbox entries on the fly.
- * This will have a really heavy effect upon performance.
- */
- uint32_t tmp[4];
- uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
- int curr_rnd;
- int rounds = ctx->rounds;
- const uint32_t *k = ctx->ks;
-
- /* Pre-round key addition */
- for (row = 0; row < 4; row++)
- data[row] ^= *(k++);
-
- /* Encrypt one block. */
- for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
- {
- /* Perform ByteSub and ShiftRow operations together */
- for (row = 0; row < 4; row++)
- {
- a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
- a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
- a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF];
- a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
-
- /* Perform MixColumn iff not last round */
- if (curr_rnd < (rounds - 1))
- {
- tmp1 = a0 ^ a1 ^ a2 ^ a3;
- old_a0 = a0;
- a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
- a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
- a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
- a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
- }
-
- tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
- }
-
- /* KeyAddition - note that it is vital that this loop is separate from
- the MixColumn operation, which must be atomic...*/
- for (row = 0; row < 4; row++)
- data[row] = tmp[row] ^ *(k++);
- }
-}
-
-/**
- * Decrypt a single block (16 bytes) of data
- */
-static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
-{
- uint32_t tmp[4];
- uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;
- uint32_t a0, a1, a2, a3, row;
- int curr_rnd;
- int rounds = ctx->rounds;
- const uint32_t *k = ctx->ks + ((rounds+1)*4);
-
- /* pre-round key addition */
- for (row=4; row > 0;row--)
- data[row-1] ^= *(--k);
-
- /* Decrypt one block */
- for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
- {
- /* Perform ByteSub and ShiftRow operations together */
- for (row = 4; row > 0; row--)
- {
- a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
- a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
- a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
- a3 = aes_isbox[(data[row%4])&0xFF];
-
- /* Perform MixColumn iff not last round */
- if (curr_rnd<(rounds-1))
- {
- /* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
- are quite large compared to encryption; this
- operation slows decryption down noticeably. */
- xt0 = AES_xtime(a0^a1);
- xt1 = AES_xtime(a1^a2);
- xt2 = AES_xtime(a2^a3);
- xt3 = AES_xtime(a3^a0);
- xt4 = AES_xtime(xt0^xt1);
- xt5 = AES_xtime(xt1^xt2);
- xt6 = AES_xtime(xt4^xt5);
-
- xt0 ^= a1^a2^a3^xt4^xt6;
- xt1 ^= a0^a2^a3^xt5^xt6;
- xt2 ^= a0^a1^a3^xt4^xt6;
- xt3 ^= a0^a1^a2^xt5^xt6;
- tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
- }
- else
- tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
- }
-
- for (row = 4; row > 0; row--)
- data[row-1] = tmp[row-1] ^ *(--k);
- }
-}
-
-#endif
diff --git a/axTLS/src/crypto/bigint.c b/axTLS/src/crypto/bigint.c
deleted file mode 100644
index e9ca04c..0000000
--- a/axTLS/src/crypto/bigint.c
+++ /dev/null
@@ -1,1512 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @defgroup bigint_api Big Integer API
- * @brief The bigint implementation as used by the axTLS project.
- *
- * The bigint library is for RSA encryption/decryption as well as signing.
- * This code tries to minimise use of malloc/free by maintaining a small
- * cache. A bigint context may maintain state by being made "permanent".
- * It be be later released with a bi_depermanent() and bi_free() call.
- *
- * It supports the following reduction techniques:
- * - Classical
- * - Barrett
- * - Montgomery
- *
- * It also implements the following:
- * - Karatsuba multiplication
- * - Squaring
- * - Sliding window exponentiation
- * - Chinese Remainder Theorem (implemented in rsa.c).
- *
- * All the algorithms used are pretty standard, and designed for different
- * data bus sizes. Negative numbers are not dealt with at all, so a subtraction
- * may need to be tested for negativity.
- *
- * This library steals some ideas from Jef Poskanzer
- * <http://cs.marlboro.edu/term/cs-fall02/algorithms/crypto/RSA/bigint>
- * and GMP <http://www.swox.com/gmp>. It gets most of its implementation
- * detail from "The Handbook of Applied Cryptography"
- * <http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf>
- * @{
- */
-
-#include <stdlib.h>
-#include <limits.h>
-#include <string.h>
-#include <stdio.h>
-#include <time.h>
-#include "os_port.h"
-#include "bigint.h"
-
-#define V1 v->comps[v->size-1] /**< v1 for division */
-#define V2 v->comps[v->size-2] /**< v2 for division */
-#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */
-#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */
-
-static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i);
-static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom);
-static bigint *alloc(BI_CTX *ctx, int size);
-static bigint *trim(bigint *bi);
-static void more_comps(bigint *bi, int n);
-#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
- defined(CONFIG_BIGINT_MONTGOMERY)
-static bigint *comp_right_shift(bigint *biR, int num_shifts);
-static bigint *comp_left_shift(bigint *biR, int num_shifts);
-#endif
-
-#ifdef CONFIG_BIGINT_CHECK_ON
-static void check(const bigint *bi);
-#else
-#define check(A) /**< disappears in normal production mode */
-#endif
-
-
-/**
- * @brief Start a new bigint context.
- * @return A bigint context.
- */
-BI_CTX *bi_initialize(void)
-{
- /* calloc() sets everything to zero */
- BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX));
-
- /* the radix */
- ctx->bi_radix = alloc(ctx, 2);
- ctx->bi_radix->comps[0] = 0;
- ctx->bi_radix->comps[1] = 1;
- bi_permanent(ctx->bi_radix);
- return ctx;
-}
-
-/**
- * @brief Close the bigint context and free any resources.
- *
- * Free up any used memory - a check is done if all objects were not
- * properly freed.
- * @param ctx [in] The bigint session context.
- */
-void bi_terminate(BI_CTX *ctx)
-{
- bi_depermanent(ctx->bi_radix);
- bi_free(ctx, ctx->bi_radix);
-
- if (ctx->active_count != 0)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("bi_terminate: there were %d un-freed bigints\n",
- ctx->active_count);
-#endif
- abort();
- }
-
- bi_clear_cache(ctx);
- free(ctx);
-}
-
-/**
- *@brief Clear the memory cache.
- */
-void bi_clear_cache(BI_CTX *ctx)
-{
- bigint *p, *pn;
-
- if (ctx->free_list == NULL)
- return;
-
- for (p = ctx->free_list; p != NULL; p = pn)
- {
- pn = p->next;
- free(p->comps);
- free(p);
- }
-
- ctx->free_count = 0;
- ctx->free_list = NULL;
-}
-
-/**
- * @brief Increment the number of references to this object.
- * It does not do a full copy.
- * @param bi [in] The bigint to copy.
- * @return A reference to the same bigint.
- */
-bigint *bi_copy(bigint *bi)
-{
- check(bi);
- if (bi->refs != PERMANENT)
- bi->refs++;
- return bi;
-}
-
-/**
- * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it.
- *
- * For this object to be freed, bi_depermanent() must be called.
- * @param bi [in] The bigint to be made permanent.
- */
-void bi_permanent(bigint *bi)
-{
- check(bi);
- if (bi->refs != 1)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("bi_permanent: refs was not 1\n");
-#endif
- abort();
- }
-
- bi->refs = PERMANENT;
-}
-
-/**
- * @brief Take a permanent object and make it eligible for freedom.
- * @param bi [in] The bigint to be made back to temporary.
- */
-void bi_depermanent(bigint *bi)
-{
- check(bi);
- if (bi->refs != PERMANENT)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("bi_depermanent: bigint was not permanent\n");
-#endif
- abort();
- }
-
- bi->refs = 1;
-}
-
-/**
- * @brief Free a bigint object so it can be used again.
- *
- * The memory itself it not actually freed, just tagged as being available
- * @param ctx [in] The bigint session context.
- * @param bi [in] The bigint to be freed.
- */
-void bi_free(BI_CTX *ctx, bigint *bi)
-{
- check(bi);
- if (bi->refs == PERMANENT)
- {
- return;
- }
-
- if (--bi->refs > 0)
- {
- return;
- }
-
- bi->next = ctx->free_list;
- ctx->free_list = bi;
- ctx->free_count++;
-
- if (--ctx->active_count < 0)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("bi_free: active_count went negative "
- "- double-freed bigint?\n");
-#endif
- abort();
- }
-}
-
-/**
- * @brief Convert an (unsigned) integer into a bigint.
- * @param ctx [in] The bigint session context.
- * @param i [in] The (unsigned) integer to be converted.
- *
- */
-bigint *int_to_bi(BI_CTX *ctx, comp i)
-{
- bigint *biR = alloc(ctx, 1);
- biR->comps[0] = i;
- return biR;
-}
-
-/**
- * @brief Do a full copy of the bigint object.
- * @param ctx [in] The bigint session context.
- * @param bi [in] The bigint object to be copied.
- */
-bigint *bi_clone(BI_CTX *ctx, const bigint *bi)
-{
- bigint *biR = alloc(ctx, bi->size);
- check(bi);
- memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE);
- return biR;
-}
-
-/**
- * @brief Perform an addition operation between two bigints.
- * @param ctx [in] The bigint session context.
- * @param bia [in] A bigint.
- * @param bib [in] Another bigint.
- * @return The result of the addition.
- */
-bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib)
-{
- int n;
- comp carry = 0;
- comp *pa, *pb;
-
- check(bia);
- check(bib);
-
- n = max(bia->size, bib->size);
- more_comps(bia, n+1);
- more_comps(bib, n);
- pa = bia->comps;
- pb = bib->comps;
-
- do
- {
- comp sl, rl, cy1;
- sl = *pa + *pb++;
- rl = sl + carry;
- cy1 = sl < *pa;
- carry = cy1 | (rl < sl);
- *pa++ = rl;
- } while (--n != 0);
-
- *pa = carry; /* do overflow */
- bi_free(ctx, bib);
- return trim(bia);
-}
-
-/**
- * @brief Perform a subtraction operation between two bigints.
- * @param ctx [in] The bigint session context.
- * @param bia [in] A bigint.
- * @param bib [in] Another bigint.
- * @param is_negative [out] If defined, indicates that the result was negative.
- * is_negative may be null.
- * @return The result of the subtraction. The result is always positive.
- */
-bigint *bi_subtract(BI_CTX *ctx,
- bigint *bia, bigint *bib, int *is_negative)
-{
- int n = bia->size;
- comp *pa, *pb, carry = 0;
-
- check(bia);
- check(bib);
-
- more_comps(bib, n);
- pa = bia->comps;
- pb = bib->comps;
-
- do
- {
- comp sl, rl, cy1;
- sl = *pa - *pb++;
- rl = sl - carry;
- cy1 = sl > *pa;
- carry = cy1 | (rl > sl);
- *pa++ = rl;
- } while (--n != 0);
-
- if (is_negative) /* indicate a negative result */
- {
- *is_negative = carry;
- }
-
- bi_free(ctx, trim(bib)); /* put bib back to the way it was */
- return trim(bia);
-}
-
-/**
- * Perform a multiply between a bigint an an (unsigned) integer
- */
-static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b)
-{
- int j = 0, n = bia->size;
- bigint *biR = alloc(ctx, n + 1);
- comp carry = 0;
- comp *r = biR->comps;
- comp *a = bia->comps;
-
- check(bia);
-
- /* clear things to start with */
- memset(r, 0, ((n+1)*COMP_BYTE_SIZE));
-
- do
- {
- long_comp tmp = *r + (long_comp)a[j]*b + carry;
- *r++ = (comp)tmp; /* downsize */
- carry = (comp)(tmp >> COMP_BIT_SIZE);
- } while (++j < n);
-
- *r = carry;
- bi_free(ctx, bia);
- return trim(biR);
-}
-
-/**
- * @brief Does both division and modulo calculations.
- *
- * Used extensively when doing classical reduction.
- * @param ctx [in] The bigint session context.
- * @param u [in] A bigint which is the numerator.
- * @param v [in] Either the denominator or the modulus depending on the mode.
- * @param is_mod [n] Determines if this is a normal division (0) or a reduction
- * (1).
- * @return The result of the division/reduction.
- */
-bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod)
-{
- int n = v->size, m = u->size-n;
- int j = 0, orig_u_size = u->size;
- uint8_t mod_offset = ctx->mod_offset;
- comp d;
- bigint *quotient, *tmp_u;
- comp q_dash;
-
- check(u);
- check(v);
-
- /* if doing reduction and we are < mod, then return mod */
- if (is_mod && bi_compare(v, u) > 0)
- {
- bi_free(ctx, v);
- return u;
- }
-
- quotient = alloc(ctx, m+1);
- tmp_u = alloc(ctx, n+1);
- v = trim(v); /* make sure we have no leading 0's */
- d = (comp)((long_comp)COMP_RADIX/(V1+1));
-
- /* clear things to start with */
- memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE));
-
- /* normalise */
- if (d > 1)
- {
- u = bi_int_multiply(ctx, u, d);
-
- if (is_mod)
- {
- v = ctx->bi_normalised_mod[mod_offset];
- }
- else
- {
- v = bi_int_multiply(ctx, v, d);
- }
- }
-
- if (orig_u_size == u->size) /* new digit position u0 */
- {
- more_comps(u, orig_u_size + 1);
- }
-
- do
- {
- /* get a temporary short version of u */
- memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE);
-
- /* calculate q' */
- if (U(0) == V1)
- {
- q_dash = COMP_RADIX-1;
- }
- else
- {
- q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1);
-
- if (v->size > 1 && V2)
- {
- /* we are implementing the following:
- if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) -
- q_dash*V1)*COMP_RADIX) + U(2))) ... */
- comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) -
- (long_comp)q_dash*V1);
- if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2))
- {
- q_dash--;
- }
- }
- }
-
- /* multiply and subtract */
- if (q_dash)
- {
- int is_negative;
- tmp_u = bi_subtract(ctx, tmp_u,
- bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative);
- more_comps(tmp_u, n+1);
-
- Q(j) = q_dash;
-
- /* add back */
- if (is_negative)
- {
- Q(j)--;
- tmp_u = bi_add(ctx, tmp_u, bi_copy(v));
-
- /* lop off the carry */
- tmp_u->size--;
- v->size--;
- }
- }
- else
- {
- Q(j) = 0;
- }
-
- /* copy back to u */
- memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE);
- } while (++j <= m);
-
- bi_free(ctx, tmp_u);
- bi_free(ctx, v);
-
- if (is_mod) /* get the remainder */
- {
- bi_free(ctx, quotient);
- return bi_int_divide(ctx, trim(u), d);
- }
- else /* get the quotient */
- {
- bi_free(ctx, u);
- return trim(quotient);
- }
-}
-
-/*
- * Perform an integer divide on a bigint.
- */
-static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom)
-{
- int i = biR->size - 1;
- long_comp r = 0;
-
- check(biR);
-
- do
- {
- r = (r<<COMP_BIT_SIZE) + biR->comps[i];
- biR->comps[i] = (comp)(r / denom);
- r %= denom;
- } while (--i >= 0);
-
- return trim(biR);
-}
-
-#ifdef CONFIG_BIGINT_MONTGOMERY
-/**
- * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1,
- * where B^-1(B-1) mod N=1. Actually, only the least significant part of
- * N' is needed, hence the definition N0'=N' mod b. We reproduce below the
- * simple algorithm from an article by Dusse and Kaliski to efficiently
- * find N0' from N0 and b */
-static comp modular_inverse(bigint *bim)
-{
- int i;
- comp t = 1;
- comp two_2_i_minus_1 = 2; /* 2^(i-1) */
- long_comp two_2_i = 4; /* 2^i */
- comp N = bim->comps[0];
-
- for (i = 2; i <= COMP_BIT_SIZE; i++)
- {
- if ((long_comp)N*t%two_2_i >= two_2_i_minus_1)
- {
- t += two_2_i_minus_1;
- }
-
- two_2_i_minus_1 <<= 1;
- two_2_i <<= 1;
- }
-
- return (comp)(COMP_RADIX-t);
-}
-#endif
-
-#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
- defined(CONFIG_BIGINT_MONTGOMERY)
-/**
- * Take each component and shift down (in terms of components)
- */
-static bigint *comp_right_shift(bigint *biR, int num_shifts)
-{
- int i = biR->size-num_shifts;
- comp *x = biR->comps;
- comp *y = &biR->comps[num_shifts];
-
- check(biR);
-
- if (i <= 0) /* have we completely right shifted? */
- {
- biR->comps[0] = 0; /* return 0 */
- biR->size = 1;
- return biR;
- }
-
- do
- {
- *x++ = *y++;
- } while (--i > 0);
-
- biR->size -= num_shifts;
- return biR;
-}
-
-/**
- * Take each component and shift it up (in terms of components)
- */
-static bigint *comp_left_shift(bigint *biR, int num_shifts)
-{
- int i = biR->size-1;
- comp *x, *y;
-
- check(biR);
-
- if (num_shifts <= 0)
- {
- return biR;
- }
-
- more_comps(biR, biR->size + num_shifts);
-
- x = &biR->comps[i+num_shifts];
- y = &biR->comps[i];
-
- do
- {
- *x-- = *y--;
- } while (i--);
-
- memset(biR->comps, 0, num_shifts*COMP_BYTE_SIZE); /* zero LS comps */
- return biR;
-}
-#endif
-
-/**
- * @brief Allow a binary sequence to be imported as a bigint.
- * @param ctx [in] The bigint session context.
- * @param data [in] The data to be converted.
- * @param size [in] The number of bytes of data.
- * @return A bigint representing this data.
- */
-bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size)
-{
- bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE);
- int i, j = 0, offset = 0;
-
- memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
-
- for (i = size-1; i >= 0; i--)
- {
- biR->comps[offset] += data[i] << (j*8);
-
- if (++j == COMP_BYTE_SIZE)
- {
- j = 0;
- offset ++;
- }
- }
-
- return trim(biR);
-}
-
-#ifdef CONFIG_SSL_FULL_MODE
-/**
- * @brief The testharness uses this code to import text hex-streams and
- * convert them into bigints.
- * @param ctx [in] The bigint session context.
- * @param data [in] A string consisting of hex characters. The characters must
- * be in upper case.
- * @return A bigint representing this data.
- */
-bigint *bi_str_import(BI_CTX *ctx, const char *data)
-{
- int size = strlen(data);
- bigint *biR = alloc(ctx, (size+COMP_NUM_NIBBLES-1)/COMP_NUM_NIBBLES);
- int i, j = 0, offset = 0;
- memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
-
- for (i = size-1; i >= 0; i--)
- {
- int num = (data[i] <= '9') ? (data[i] - '0') : (data[i] - 'A' + 10);
- biR->comps[offset] += num << (j*4);
-
- if (++j == COMP_NUM_NIBBLES)
- {
- j = 0;
- offset ++;
- }
- }
-
- return biR;
-}
-
-void bi_print(const char *label, bigint *x)
-{
- int i, j;
-
- if (x == NULL)
- {
- printf("%s: (null)\n", label);
- return;
- }
-
- printf("%s: (size %d)\n", label, x->size);
- for (i = x->size-1; i >= 0; i--)
- {
- for (j = COMP_NUM_NIBBLES-1; j >= 0; j--)
- {
- comp mask = 0x0f << (j*4);
- comp num = (x->comps[i] & mask) >> (j*4);
- putc((num <= 9) ? (num + '0') : (num + 'A' - 10), stdout);
- }
- }
-
- printf("\n");
-}
-#endif
-
-/**
- * @brief Take a bigint and convert it into a byte sequence.
- *
- * This is useful after a decrypt operation.
- * @param ctx [in] The bigint session context.
- * @param x [in] The bigint to be converted.
- * @param data [out] The converted data as a byte stream.
- * @param size [in] The maximum size of the byte stream. Unused bytes will be
- * zeroed.
- */
-void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size)
-{
- int i, j, k = size-1;
-
- check(x);
- memset(data, 0, size); /* ensure all leading 0's are cleared */
-
- for (i = 0; i < x->size; i++)
- {
- for (j = 0; j < COMP_BYTE_SIZE; j++)
- {
- comp mask = 0xff << (j*8);
- int num = (x->comps[i] & mask) >> (j*8);
- data[k--] = num;
-
- if (k < 0)
- {
- goto buf_done;
- }
- }
- }
-buf_done:
-
- bi_free(ctx, x);
-}
-
-/**
- * @brief Pre-calculate some of the expensive steps in reduction.
- *
- * This function should only be called once (normally when a session starts).
- * When the session is over, bi_free_mod() should be called. bi_mod_power()
- * relies on this function being called.
- * @param ctx [in] The bigint session context.
- * @param bim [in] The bigint modulus that will be used.
- * @param mod_offset [in] There are three moduluii that can be stored - the
- * standard modulus, and its two primes p and q. This offset refers to which
- * modulus we are referring to.
- * @see bi_free_mod(), bi_mod_power().
- */
-void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset)
-{
- int k = bim->size;
- comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1));
-#ifdef CONFIG_BIGINT_MONTGOMERY
- bigint *R, *R2;
-#endif
-
- ctx->bi_mod[mod_offset] = bim;
- bi_permanent(ctx->bi_mod[mod_offset]);
- ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d);
- bi_permanent(ctx->bi_normalised_mod[mod_offset]);
-
-#if defined(CONFIG_BIGINT_MONTGOMERY)
- /* set montgomery variables */
- R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1); /* R */
- R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1); /* R^2 */
- ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2); /* R^2 mod m */
- ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R); /* R mod m */
-
- bi_permanent(ctx->bi_RR_mod_m[mod_offset]);
- bi_permanent(ctx->bi_R_mod_m[mod_offset]);
-
- ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]);
-
-#elif defined (CONFIG_BIGINT_BARRETT)
- ctx->bi_mu[mod_offset] =
- bi_divide(ctx, comp_left_shift(
- bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0);
- bi_permanent(ctx->bi_mu[mod_offset]);
-#endif
-}
-
-/**
- * @brief Used when cleaning various bigints at the end of a session.
- * @param ctx [in] The bigint session context.
- * @param mod_offset [in] The offset to use.
- * @see bi_set_mod().
- */
-void bi_free_mod(BI_CTX *ctx, int mod_offset)
-{
- bi_depermanent(ctx->bi_mod[mod_offset]);
- bi_free(ctx, ctx->bi_mod[mod_offset]);
-#if defined (CONFIG_BIGINT_MONTGOMERY)
- bi_depermanent(ctx->bi_RR_mod_m[mod_offset]);
- bi_depermanent(ctx->bi_R_mod_m[mod_offset]);
- bi_free(ctx, ctx->bi_RR_mod_m[mod_offset]);
- bi_free(ctx, ctx->bi_R_mod_m[mod_offset]);
-#elif defined(CONFIG_BIGINT_BARRETT)
- bi_depermanent(ctx->bi_mu[mod_offset]);
- bi_free(ctx, ctx->bi_mu[mod_offset]);
-#endif
- bi_depermanent(ctx->bi_normalised_mod[mod_offset]);
- bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);
-}
-
-/**
- * Perform a standard multiplication between two bigints.
- *
- * Barrett reduction has no need for some parts of the product, so ignore bits
- * of the multiply. This routine gives Barrett its big performance
- * improvements over Classical/Montgomery reduction methods.
- */
-static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib,
- int inner_partial, int outer_partial)
-{
- int i = 0, j;
- int n = bia->size;
- int t = bib->size;
- bigint *biR = alloc(ctx, n + t);
- comp *sr = biR->comps;
- comp *sa = bia->comps;
- comp *sb = bib->comps;
-
- check(bia);
- check(bib);
-
- /* clear things to start with */
- memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE));
-
- do
- {
- long_comp tmp;
- comp carry = 0;
- int r_index = i;
- j = 0;
-
- if (outer_partial && outer_partial-i > 0 && outer_partial < n)
- {
- r_index = outer_partial-1;
- j = outer_partial-i-1;
- }
-
- do
- {
- if (inner_partial && r_index >= inner_partial)
- {
- break;
- }
-
- tmp = sr[r_index] + ((long_comp)sa[j])*sb[i] + carry;
- sr[r_index++] = (comp)tmp; /* downsize */
- carry = tmp >> COMP_BIT_SIZE;
- } while (++j < n);
-
- sr[r_index] = carry;
- } while (++i < t);
-
- bi_free(ctx, bia);
- bi_free(ctx, bib);
- return trim(biR);
-}
-
-#ifdef CONFIG_BIGINT_KARATSUBA
-/*
- * Karatsuba improves on regular multiplication due to only 3 multiplications
- * being done instead of 4. The additional additions/subtractions are O(N)
- * rather than O(N^2) and so for big numbers it saves on a few operations
- */
-static bigint *karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square)
-{
- bigint *x0, *x1;
- bigint *p0, *p1, *p2;
- int m;
-
- if (is_square)
- {
- m = (bia->size + 1)/2;
- }
- else
- {
- m = (max(bia->size, bib->size) + 1)/2;
- }
-
- x0 = bi_clone(ctx, bia);
- x0->size = m;
- x1 = bi_clone(ctx, bia);
- comp_right_shift(x1, m);
- bi_free(ctx, bia);
-
- /* work out the 3 partial products */
- if (is_square)
- {
- p0 = bi_square(ctx, bi_copy(x0));
- p2 = bi_square(ctx, bi_copy(x1));
- p1 = bi_square(ctx, bi_add(ctx, x0, x1));
- }
- else /* normal multiply */
- {
- bigint *y0, *y1;
- y0 = bi_clone(ctx, bib);
- y0->size = m;
- y1 = bi_clone(ctx, bib);
- comp_right_shift(y1, m);
- bi_free(ctx, bib);
-
- p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0));
- p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1));
- p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1));
- }
-
- p1 = bi_subtract(ctx,
- bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0), NULL);
-
- comp_left_shift(p1, m);
- comp_left_shift(p2, 2*m);
- return bi_add(ctx, p1, bi_add(ctx, p0, p2));
-}
-#endif
-
-/**
- * @brief Perform a multiplication operation between two bigints.
- * @param ctx [in] The bigint session context.
- * @param bia [in] A bigint.
- * @param bib [in] Another bigint.
- * @return The result of the multiplication.
- */
-bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)
-{
- check(bia);
- check(bib);
-
-#ifdef CONFIG_BIGINT_KARATSUBA
- if (min(bia->size, bib->size) < MUL_KARATSUBA_THRESH)
- {
- return regular_multiply(ctx, bia, bib, 0, 0);
- }
-
- return karatsuba(ctx, bia, bib, 0);
-#else
- return regular_multiply(ctx, bia, bib, 0, 0);
-#endif
-}
-
-#ifdef CONFIG_BIGINT_SQUARE
-/*
- * Perform the actual square operion. It takes into account overflow.
- */
-static bigint *regular_square(BI_CTX *ctx, bigint *bi)
-{
- int t = bi->size;
- int i = 0, j;
- bigint *biR = alloc(ctx, t*2+1);
- comp *w = biR->comps;
- comp *x = bi->comps;
- long_comp carry;
- memset(w, 0, biR->size*COMP_BYTE_SIZE);
-
- do
- {
- long_comp tmp = w[2*i] + (long_comp)x[i]*x[i];
- w[2*i] = (comp)tmp;
- carry = tmp >> COMP_BIT_SIZE;
-
- for (j = i+1; j < t; j++)
- {
- uint8_t c = 0;
- long_comp xx = (long_comp)x[i]*x[j];
- if ((COMP_MAX-xx) < xx)
- c = 1;
-
- tmp = (xx<<1);
-
- if ((COMP_MAX-tmp) < w[i+j])
- c = 1;
-
- tmp += w[i+j];
-
- if ((COMP_MAX-tmp) < carry)
- c = 1;
-
- tmp += carry;
- w[i+j] = (comp)tmp;
- carry = tmp >> COMP_BIT_SIZE;
-
- if (c)
- carry += COMP_RADIX;
- }
-
- tmp = w[i+t] + carry;
- w[i+t] = (comp)tmp;
- w[i+t+1] = tmp >> COMP_BIT_SIZE;
- } while (++i < t);
-
- bi_free(ctx, bi);
- return trim(biR);
-}
-
-/**
- * @brief Perform a square operation on a bigint.
- * @param ctx [in] The bigint session context.
- * @param bia [in] A bigint.
- * @return The result of the multiplication.
- */
-bigint *bi_square(BI_CTX *ctx, bigint *bia)
-{
- check(bia);
-
-#ifdef CONFIG_BIGINT_KARATSUBA
- if (bia->size < SQU_KARATSUBA_THRESH)
- {
- return regular_square(ctx, bia);
- }
-
- return karatsuba(ctx, bia, NULL, 1);
-#else
- return regular_square(ctx, bia);
-#endif
-}
-#endif
-
-/**
- * @brief Compare two bigints.
- * @param bia [in] A bigint.
- * @param bib [in] Another bigint.
- * @return -1 if smaller, 1 if larger and 0 if equal.
- */
-int bi_compare(bigint *bia, bigint *bib)
-{
- int r, i;
-
- check(bia);
- check(bib);
-
- if (bia->size > bib->size)
- r = 1;
- else if (bia->size < bib->size)
- r = -1;
- else
- {
- comp *a = bia->comps;
- comp *b = bib->comps;
-
- /* Same number of components. Compare starting from the high end
- * and working down. */
- r = 0;
- i = bia->size - 1;
-
- do
- {
- if (a[i] > b[i])
- {
- r = 1;
- break;
- }
- else if (a[i] < b[i])
- {
- r = -1;
- break;
- }
- } while (--i >= 0);
- }
-
- return r;
-}
-
-/*
- * Allocate and zero more components. Does not consume bi.
- */
-static void more_comps(bigint *bi, int n)
-{
- if (n > bi->max_comps)
- {
- bi->max_comps = max(bi->max_comps * 2, n);
- bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE);
- }
-
- if (n > bi->size)
- {
- memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE);
- }
-
- bi->size = n;
-}
-
-/*
- * Make a new empty bigint. It may just use an old one if one is available.
- * Otherwise get one off the heap.
- */
-static bigint *alloc(BI_CTX *ctx, int size)
-{
- bigint *biR;
-
- /* Can we recycle an old bigint? */
- if (ctx->free_list != NULL)
- {
- biR = ctx->free_list;
- ctx->free_list = biR->next;
- ctx->free_count--;
-
- if (biR->refs != 0)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("alloc: refs was not 0\n");
-#endif
- abort(); /* create a stack trace from a core dump */
- }
-
- more_comps(biR, size);
- }
- else
- {
- /* No free bigints available - create a new one. */
- biR = (bigint *)malloc(sizeof(bigint));
- biR->comps = (comp*)malloc(size * COMP_BYTE_SIZE);
- biR->max_comps = size; /* give some space to spare */
- }
-
- biR->size = size;
- biR->refs = 1;
- biR->next = NULL;
- ctx->active_count++;
- return biR;
-}
-
-/*
- * Work out the highest '1' bit in an exponent. Used when doing sliding-window
- * exponentiation.
- */
-static int find_max_exp_index(bigint *biexp)
-{
- int i = COMP_BIT_SIZE-1;
- comp shift = COMP_RADIX/2;
- comp test = biexp->comps[biexp->size-1]; /* assume no leading zeroes */
-
- check(biexp);
-
- do
- {
- if (test & shift)
- {
- return i+(biexp->size-1)*COMP_BIT_SIZE;
- }
-
- shift >>= 1;
- } while (i-- != 0);
-
- return -1; /* error - must have been a leading 0 */
-}
-
-/*
- * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window
- * exponentiation.
- */
-static int exp_bit_is_one(bigint *biexp, int offset)
-{
- comp test = biexp->comps[offset / COMP_BIT_SIZE];
- int num_shifts = offset % COMP_BIT_SIZE;
- comp shift = 1;
- int i;
-
- check(biexp);
-
- for (i = 0; i < num_shifts; i++)
- {
- shift <<= 1;
- }
-
- return (test & shift) != 0;
-}
-
-#ifdef CONFIG_BIGINT_CHECK_ON
-/*
- * Perform a sanity check on bi.
- */
-static void check(const bigint *bi)
-{
- if (bi->refs <= 0)
- {
- printf("check: zero or negative refs in bigint\n");
- abort();
- }
-
- if (bi->next != NULL)
- {
- printf("check: attempt to use a bigint from "
- "the free list\n");
- abort();
- }
-}
-#endif
-
-/*
- * Delete any leading 0's (and allow for 0).
- */
-static bigint *trim(bigint *bi)
-{
- check(bi);
-
- while (bi->comps[bi->size-1] == 0 && bi->size > 1)
- {
- bi->size--;
- }
-
- return bi;
-}
-
-#if defined(CONFIG_BIGINT_MONTGOMERY)
-/**
- * @brief Perform a single montgomery reduction.
- * @param ctx [in] The bigint session context.
- * @param bixy [in] A bigint.
- * @return The result of the montgomery reduction.
- */
-bigint *bi_mont(BI_CTX *ctx, bigint *bixy)
-{
- int i = 0, n;
- uint8_t mod_offset = ctx->mod_offset;
- bigint *bim = ctx->bi_mod[mod_offset];
- comp mod_inv = ctx->N0_dash[mod_offset];
-
- check(bixy);
-
- if (ctx->use_classical) /* just use classical instead */
- {
- return bi_mod(ctx, bixy);
- }
-
- n = bim->size;
-
- do
- {
- bixy = bi_add(ctx, bixy, comp_left_shift(
- bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i));
- } while (++i < n);
-
- comp_right_shift(bixy, n);
-
- if (bi_compare(bixy, bim) >= 0)
- {
- bixy = bi_subtract(ctx, bixy, bim, NULL);
- }
-
- return bixy;
-}
-
-#elif defined(CONFIG_BIGINT_BARRETT)
-/*
- * Stomp on the most significant components to give the illusion of a "mod base
- * radix" operation
- */
-static bigint *comp_mod(bigint *bi, int mod)
-{
- check(bi);
-
- if (bi->size > mod)
- {
- bi->size = mod;
- }
-
- return bi;
-}
-
-/**
- * @brief Perform a single Barrett reduction.
- * @param ctx [in] The bigint session context.
- * @param bi [in] A bigint.
- * @return The result of the Barrett reduction.
- */
-bigint *bi_barrett(BI_CTX *ctx, bigint *bi)
-{
- bigint *q1, *q2, *q3, *r1, *r2, *r;
- uint8_t mod_offset = ctx->mod_offset;
- bigint *bim = ctx->bi_mod[mod_offset];
- int k = bim->size;
-
- check(bi);
- check(bim);
-
- /* use Classical method instead - Barrett cannot help here */
- if (bi->size > k*2)
- {
- return bi_mod(ctx, bi);
- }
-
- q1 = comp_right_shift(bi_clone(ctx, bi), k-1);
-
- /* do outer partial multiply */
- q2 = regular_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1);
- q3 = comp_right_shift(q2, k+1);
- r1 = comp_mod(bi, k+1);
-
- /* do inner partial multiply */
- r2 = comp_mod(regular_multiply(ctx, q3, bim, k+1, 0), k+1);
- r = bi_subtract(ctx, r1, r2, NULL);
-
- /* if (r >= m) r = r - m; */
- if (bi_compare(r, bim) >= 0)
- {
- r = bi_subtract(ctx, r, bim, NULL);
- }
-
- return r;
-}
-#endif /* CONFIG_BIGINT_BARRETT */
-
-#ifdef CONFIG_BIGINT_SLIDING_WINDOW
-/*
- * Work out g1, g3, g5, g7... etc for the sliding-window algorithm
- */
-static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1)
-{
- int k = 1, i;
- bigint *g2;
-
- for (i = 0; i < window-1; i++) /* compute 2^(window-1) */
- {
- k <<= 1;
- }
-
- ctx->g = (bigint **)malloc(k*sizeof(bigint *));
- ctx->g[0] = bi_clone(ctx, g1);
- bi_permanent(ctx->g[0]);
- g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */
-
- for (i = 1; i < k; i++)
- {
- ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i-1], bi_copy(g2)));
- bi_permanent(ctx->g[i]);
- }
-
- bi_free(ctx, g2);
- ctx->window = k;
-}
-#endif
-
-/**
- * @brief Perform a modular exponentiation.
- *
- * This function requires bi_set_mod() to have been called previously. This is
- * one of the optimisations used for performance.
- * @param ctx [in] The bigint session context.
- * @param bi [in] The bigint on which to perform the mod power operation.
- * @param biexp [in] The bigint exponent.
- * @return The result of the mod exponentiation operation
- * @see bi_set_mod().
- */
-bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp)
-{
- int i = find_max_exp_index(biexp), j, window_size = 1;
- bigint *biR = int_to_bi(ctx, 1);
-
-#if defined(CONFIG_BIGINT_MONTGOMERY)
- uint8_t mod_offset = ctx->mod_offset;
- if (!ctx->use_classical)
- {
- /* preconvert */
- bi = bi_mont(ctx,
- bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset])); /* x' */
- bi_free(ctx, biR);
- biR = ctx->bi_R_mod_m[mod_offset]; /* A */
- }
-#endif
-
- check(bi);
- check(biexp);
-
-#ifdef CONFIG_BIGINT_SLIDING_WINDOW
- for (j = i; j > 32; j /= 5) /* work out an optimum size */
- window_size++;
-
- /* work out the slide constants */
- precompute_slide_window(ctx, window_size, bi);
-#else /* just one constant */
- ctx->g = (bigint **)malloc(sizeof(bigint *));
- ctx->g[0] = bi_clone(ctx, bi);
- ctx->window = 1;
- bi_permanent(ctx->g[0]);
-#endif
-
- /* if sliding-window is off, then only one bit will be done at a time and
- * will reduce to standard left-to-right exponentiation */
- do
- {
- if (exp_bit_is_one(biexp, i))
- {
- int l = i-window_size+1;
- int part_exp = 0;
-
- if (l < 0) /* LSB of exponent will always be 1 */
- l = 0;
- else
- {
- while (exp_bit_is_one(biexp, l) == 0)
- l++; /* go back up */
- }
-
- /* build up the section of the exponent */
- for (j = i; j >= l; j--)
- {
- biR = bi_residue(ctx, bi_square(ctx, biR));
- if (exp_bit_is_one(biexp, j))
- part_exp++;
-
- if (j != l)
- part_exp <<= 1;
- }
-
- part_exp = (part_exp-1)/2; /* adjust for array */
- biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp]));
- i = l-1;
- }
- else /* square it */
- {
- biR = bi_residue(ctx, bi_square(ctx, biR));
- i--;
- }
- } while (i >= 0);
-
- /* cleanup */
- for (i = 0; i < ctx->window; i++)
- {
- bi_depermanent(ctx->g[i]);
- bi_free(ctx, ctx->g[i]);
- }
-
- free(ctx->g);
- bi_free(ctx, bi);
- bi_free(ctx, biexp);
-#if defined CONFIG_BIGINT_MONTGOMERY
- return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */
-#else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */
- return biR;
-#endif
-}
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-/**
- * @brief Perform a modular exponentiation using a temporary modulus.
- *
- * We need this function to check the signatures of certificates. The modulus
- * of this function is temporary as it's just used for authentication.
- * @param ctx [in] The bigint session context.
- * @param bi [in] The bigint to perform the exp/mod.
- * @param bim [in] The temporary modulus.
- * @param biexp [in] The bigint exponent.
- * @return The result of the mod exponentiation operation
- * @see bi_set_mod().
- */
-bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp)
-{
- bigint *biR, *tmp_biR;
-
- /* Set up a temporary bigint context and transfer what we need between
- * them. We need to do this since we want to keep the original modulus
- * which is already in this context. This operation is only called when
- * doing peer verification, and so is not expensive :-) */
- BI_CTX *tmp_ctx = bi_initialize();
- bi_set_mod(tmp_ctx, bi_clone(tmp_ctx, bim), BIGINT_M_OFFSET);
- tmp_biR = bi_mod_power(tmp_ctx,
- bi_clone(tmp_ctx, bi),
- bi_clone(tmp_ctx, biexp));
- biR = bi_clone(ctx, tmp_biR);
- bi_free(tmp_ctx, tmp_biR);
- bi_free_mod(tmp_ctx, BIGINT_M_OFFSET);
- bi_terminate(tmp_ctx);
-
- bi_free(ctx, bi);
- bi_free(ctx, bim);
- bi_free(ctx, biexp);
- return biR;
-}
-#endif
-
-#ifdef CONFIG_BIGINT_CRT
-/**
- * @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts.
- *
- * @param ctx [in] The bigint session context.
- * @param bi [in] The bigint to perform the exp/mod.
- * @param dP [in] CRT's dP bigint
- * @param dQ [in] CRT's dQ bigint
- * @param p [in] CRT's p bigint
- * @param q [in] CRT's q bigint
- * @param qInv [in] CRT's qInv bigint
- * @return The result of the CRT operation
- */
-bigint *bi_crt(BI_CTX *ctx, bigint *bi,
- bigint *dP, bigint *dQ,
- bigint *p, bigint *q, bigint *qInv)
-{
- bigint *m1, *m2, *h;
-
- /* Montgomery has a condition the 0 < x, y < m and these products violate
- * that condition. So disable Montgomery when using CRT */
-#if defined(CONFIG_BIGINT_MONTGOMERY)
- ctx->use_classical = 1;
-#endif
- ctx->mod_offset = BIGINT_P_OFFSET;
- m1 = bi_mod_power(ctx, bi_copy(bi), dP);
-
- ctx->mod_offset = BIGINT_Q_OFFSET;
- m2 = bi_mod_power(ctx, bi, dQ);
-
- h = bi_subtract(ctx, bi_add(ctx, m1, p), bi_copy(m2), NULL);
- h = bi_multiply(ctx, h, qInv);
- ctx->mod_offset = BIGINT_P_OFFSET;
- h = bi_residue(ctx, h);
-#if defined(CONFIG_BIGINT_MONTGOMERY)
- ctx->use_classical = 0; /* reset for any further operation */
-#endif
- return bi_add(ctx, m2, bi_multiply(ctx, q, h));
-}
-#endif
-/** @} */
diff --git a/axTLS/src/crypto/bigint.h b/axTLS/src/crypto/bigint.h
deleted file mode 100644
index 2966a3e..0000000
--- a/axTLS/src/crypto/bigint.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BIGINT_HEADER
-#define BIGINT_HEADER
-
-#include "crypto.h"
-
-BI_CTX *bi_initialize(void);
-void bi_terminate(BI_CTX *ctx);
-void bi_permanent(bigint *bi);
-void bi_depermanent(bigint *bi);
-void bi_clear_cache(BI_CTX *ctx);
-void bi_free(BI_CTX *ctx, bigint *bi);
-bigint *bi_copy(bigint *bi);
-bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
-void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);
-bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);
-bigint *int_to_bi(BI_CTX *ctx, comp i);
-
-/* the functions that actually do something interesting */
-bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);
-bigint *bi_subtract(BI_CTX *ctx, bigint *bia,
- bigint *bib, int *is_negative);
-bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod);
-bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);
-bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);
-bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp);
-int bi_compare(bigint *bia, bigint *bib);
-void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
-void bi_free_mod(BI_CTX *ctx, int mod_offset);
-
-#ifdef CONFIG_SSL_FULL_MODE
-void bi_print(const char *label, bigint *bi);
-bigint *bi_str_import(BI_CTX *ctx, const char *data);
-#endif
-
-/**
- * @def bi_mod
- * Find the residue of B. bi_set_mod() must be called before hand.
- */
-#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)
-
-/**
- * bi_residue() is technically the same as bi_mod(), but it uses the
- * appropriate reduction technique (which is bi_mod() when doing classical
- * reduction).
- */
-#if defined(CONFIG_BIGINT_MONTGOMERY)
-#define bi_residue(A, B) bi_mont(A, B)
-bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
-#elif defined(CONFIG_BIGINT_BARRETT)
-#define bi_residue(A, B) bi_barrett(A, B)
-bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
-#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
-#define bi_residue(A, B) bi_mod(A, B)
-#endif
-
-#ifdef CONFIG_BIGINT_SQUARE
-bigint *bi_square(BI_CTX *ctx, bigint *bi);
-#else
-#define bi_square(A, B) bi_multiply(A, bi_copy(B), B)
-#endif
-
-#ifdef CONFIG_BIGINT_CRT
-bigint *bi_crt(BI_CTX *ctx, bigint *bi,
- bigint *dP, bigint *dQ,
- bigint *p, bigint *q,
- bigint *qInv);
-#endif
-
-#endif
diff --git a/axTLS/src/crypto/bigint_impl.h b/axTLS/src/crypto/bigint_impl.h
deleted file mode 100644
index d6e70d2..0000000
--- a/axTLS/src/crypto/bigint_impl.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BIGINT_IMPL_HEADER
-#define BIGINT_IMPL_HEADER
-
-/* Maintain a number of precomputed variables when doing reduction */
-#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */
-#ifdef CONFIG_BIGINT_CRT
-#define BIGINT_P_OFFSET 1 /**< p modulo offset. */
-#define BIGINT_Q_OFFSET 2 /**< q module offset. */
-#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */
-#else
-#define BIGINT_NUM_MODS 1
-#endif
-
-/* Architecture specific functions for big ints */
-#if defined(CONFIG_INTEGER_8BIT)
-#define COMP_RADIX 256U /**< Max component + 1 */
-#define COMP_MAX 0xFFFFU/**< (Max dbl comp -1) */
-#define COMP_BIT_SIZE 8 /**< Number of bits in a component. */
-#define COMP_BYTE_SIZE 1 /**< Number of bytes in a component. */
-#define COMP_NUM_NIBBLES 2 /**< Used For diagnostics only. */
-typedef uint8_t comp; /**< A single precision component. */
-typedef uint16_t long_comp; /**< A double precision component. */
-typedef int16_t slong_comp; /**< A signed double precision component. */
-#elif defined(CONFIG_INTEGER_16BIT)
-#define COMP_RADIX 65536U /**< Max component + 1 */
-#define COMP_MAX 0xFFFFFFFFU/**< (Max dbl comp -1) */
-#define COMP_BIT_SIZE 16 /**< Number of bits in a component. */
-#define COMP_BYTE_SIZE 2 /**< Number of bytes in a component. */
-#define COMP_NUM_NIBBLES 4 /**< Used For diagnostics only. */
-typedef uint16_t comp; /**< A single precision component. */
-typedef uint32_t long_comp; /**< A double precision component. */
-typedef int32_t slong_comp; /**< A signed double precision component. */
-#else /* regular 32 bit */
-#ifdef _MSC_VER
-#define COMP_RADIX 4294967296i64
-#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64
-#else
-#define COMP_RADIX 4294967296ULL /**< Max component + 1 */
-#define COMP_MAX 0xFFFFFFFFFFFFFFFFULL/**< (Max dbl comp -1) */
-#endif
-#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */
-#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */
-#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */
-typedef uint32_t comp; /**< A single precision component. */
-typedef uint64_t long_comp; /**< A double precision component. */
-typedef int64_t slong_comp; /**< A signed double precision component. */
-#endif
-
-/**
- * @struct _bigint
- * @brief A big integer basic object
- */
-struct _bigint
-{
- struct _bigint* next; /**< The next bigint in the cache. */
- short size; /**< The number of components in this bigint. */
- short max_comps; /**< The heapsize allocated for this bigint */
- int refs; /**< An internal reference count. */
- comp* comps; /**< A ptr to the actual component data */
-};
-
-typedef struct _bigint bigint; /**< An alias for _bigint */
-
-/**
- * Maintains the state of the cache, and a number of variables used in
- * reduction.
- */
-typedef struct /**< A big integer "session" context. */
-{
- bigint *active_list; /**< Bigints currently used. */
- bigint *free_list; /**< Bigints not used. */
- bigint *bi_radix; /**< The radix used. */
- bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */
-
-#if defined(CONFIG_BIGINT_MONTGOMERY)
- bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */
- bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */
- comp N0_dash[BIGINT_NUM_MODS];
-#elif defined(CONFIG_BIGINT_BARRETT)
- bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */
-#endif
- bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */
- bigint **g; /**< Used by sliding-window. */
- int window; /**< The size of the sliding window */
- int active_count; /**< Number of active bigints. */
- int free_count; /**< Number of free bigints. */
-
-#ifdef CONFIG_BIGINT_MONTGOMERY
- uint8_t use_classical; /**< Use classical reduction. */
-#endif
- uint8_t mod_offset; /**< The mod offset we are using */
-} BI_CTX;
-
-#ifndef WIN32
-#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */
-#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */
-#endif
-
-#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */
-
-#endif
diff --git a/axTLS/src/crypto/crypto.h b/axTLS/src/crypto/crypto.h
deleted file mode 100644
index c6f186c..0000000
--- a/axTLS/src/crypto/crypto.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file crypto.h
- */
-
-#ifndef HEADER_CRYPTO_H
-#define HEADER_CRYPTO_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-#include "bigint_impl.h"
-#include "bigint.h"
-
-#ifndef STDCALL
-#define STDCALL
-#endif
-#ifndef EXP_FUNC
-#define EXP_FUNC
-#endif
-
-
-/* enable features based on a 'super-set' capbaility. */
-#if defined(CONFIG_SSL_FULL_MODE)
-#define CONFIG_SSL_ENABLE_CLIENT
-#define CONFIG_SSL_CERT_VERIFICATION
-#elif defined(CONFIG_SSL_ENABLE_CLIENT)
-#define CONFIG_SSL_CERT_VERIFICATION
-#endif
-
-/**************************************************************************
- * AES declarations
- **************************************************************************/
-
-#define AES_MAXROUNDS 14
-#define AES_BLOCKSIZE 16
-#define AES_IV_SIZE 16
-
-typedef struct aes_key_st
-{
- uint16_t rounds;
- uint16_t key_size;
- uint32_t ks[(AES_MAXROUNDS+1)*8];
- uint8_t iv[AES_IV_SIZE];
-} AES_CTX;
-
-typedef enum
-{
- AES_MODE_128,
- AES_MODE_256
-} AES_MODE;
-
-void AES_set_key(AES_CTX *ctx, const uint8_t *key,
- const uint8_t *iv, AES_MODE mode);
-void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg,
- uint8_t *out, int length);
-void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length);
-void AES_convert_key(AES_CTX *ctx);
-
-/**************************************************************************
- * RC4 declarations
- **************************************************************************/
-
-typedef struct
-{
- uint8_t x, y, m[256];
-} RC4_CTX;
-
-void RC4_setup(RC4_CTX *s, const uint8_t *key, int length);
-void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length);
-
-/**************************************************************************
- * SHA1 declarations
- **************************************************************************/
-
-#define SHA1_SIZE 20
-
-/*
- * This structure will hold context information for the SHA-1
- * hashing operation
- */
-typedef struct
-{
- uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */
- uint32_t Length_Low; /* Message length in bits */
- uint32_t Length_High; /* Message length in bits */
- uint16_t Message_Block_Index; /* Index into message block array */
- uint8_t Message_Block[64]; /* 512-bit message blocks */
-} SHA1_CTX;
-
-void SHA1_Init(SHA1_CTX *);
-void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len);
-void SHA1_Final(uint8_t *digest, SHA1_CTX *);
-
-/**************************************************************************
- * MD2 declarations
- **************************************************************************/
-
-#define MD2_SIZE 16
-
-typedef struct
-{
- unsigned char cksum[16]; /* checksum of the data block */
- unsigned char state[48]; /* intermediate digest state */
- unsigned char buffer[16]; /* data block being processed */
- int left; /* amount of data in buffer */
-} MD2_CTX;
-
-EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx);
-EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen);
-EXP_FUNC void STDCALL MD2_Final(uint8_t *digest, MD2_CTX *ctx);
-
-/**************************************************************************
- * MD5 declarations
- **************************************************************************/
-
-#define MD5_SIZE 16
-
-typedef struct
-{
- uint32_t state[4]; /* state (ABCD) */
- uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
- uint8_t buffer[64]; /* input buffer */
-} MD5_CTX;
-
-EXP_FUNC void STDCALL MD5_Init(MD5_CTX *);
-EXP_FUNC void STDCALL MD5_Update(MD5_CTX *, const uint8_t *msg, int len);
-EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *);
-
-/**************************************************************************
- * HMAC declarations
- **************************************************************************/
-void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
- int key_len, uint8_t *digest);
-void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
- int key_len, uint8_t *digest);
-
-/**************************************************************************
- * RSA declarations
- **************************************************************************/
-
-typedef struct
-{
- bigint *m; /* modulus */
- bigint *e; /* public exponent */
- bigint *d; /* private exponent */
-#ifdef CONFIG_BIGINT_CRT
- bigint *p; /* p as in m = pq */
- bigint *q; /* q as in m = pq */
- bigint *dP; /* d mod (p-1) */
- bigint *dQ; /* d mod (q-1) */
- bigint *qInv; /* q^-1 mod p */
-#endif
- int num_octets;
- BI_CTX *bi_ctx;
-} RSA_CTX;
-
-void RSA_priv_key_new(RSA_CTX **rsa_ctx,
- const uint8_t *modulus, int mod_len,
- const uint8_t *pub_exp, int pub_len,
- const uint8_t *priv_exp, int priv_len
-#ifdef CONFIG_BIGINT_CRT
- , const uint8_t *p, int p_len,
- const uint8_t *q, int q_len,
- const uint8_t *dP, int dP_len,
- const uint8_t *dQ, int dQ_len,
- const uint8_t *qInv, int qInv_len
-#endif
- );
-void RSA_pub_key_new(RSA_CTX **rsa_ctx,
- const uint8_t *modulus, int mod_len,
- const uint8_t *pub_exp, int pub_len);
-void RSA_free(RSA_CTX *ctx);
-int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
- int is_decryption);
-bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg);
-#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
-bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
- bigint *modulus, bigint *pub_exp);
-bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg);
-int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
- uint8_t *out_data, int is_signing);
-void RSA_print(const RSA_CTX *ctx);
-#endif
-
-/**************************************************************************
- * RNG declarations
- **************************************************************************/
-EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size);
-EXP_FUNC void STDCALL RNG_terminate(void);
-EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data);
-void get_random_NZ(int num_rand_bytes, uint8_t *rand_data);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/axTLS/src/crypto/crypto_misc.c b/axTLS/src/crypto/crypto_misc.c
deleted file mode 100644
index 8e7cbf9..0000000
--- a/axTLS/src/crypto/crypto_misc.c
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Some misc. routines to help things out
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include "os_port.h"
-#include "crypto_misc.h"
-#ifdef CONFIG_WIN32_USE_CRYPTO_LIB
-#include "wincrypt.h"
-#endif
-
-#ifndef WIN32
-static int rng_fd = -1;
-#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
-static HCRYPTPROV gCryptProv;
-#endif
-
-#if (!defined(CONFIG_USE_DEV_URANDOM) && !defined(CONFIG_WIN32_USE_CRYPTO_LIB))
-/* change to processor registers as appropriate */
-#define ENTROPY_POOL_SIZE 32
-#define ENTROPY_COUNTER1 ((((uint64_t)tv.tv_sec)<<32) | tv.tv_usec)
-#define ENTROPY_COUNTER2 rand()
-static uint8_t entropy_pool[ENTROPY_POOL_SIZE];
-#endif
-
-static int rng_ref_count;
-const char * const unsupported_str = "Error: Feature not supported\n";
-
-#ifndef CONFIG_SSL_SKELETON_MODE
-/**
- * Retrieve a file and put it into memory
- * @return The size of the file, or -1 on failure.
- */
-int get_file(const char *filename, uint8_t **buf)
-{
- int total_bytes = 0;
- int bytes_read = 0;
- int filesize;
- FILE *stream = fopen(filename, "rb");
-
- if (stream == NULL)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("file '%s' does not exist\n", filename); TTY_FLUSH();
-#endif
- return -1;
- }
-
- /* Win CE doesn't support stat() */
- fseek(stream, 0, SEEK_END);
- filesize = ftell(stream);
- *buf = (uint8_t *)malloc(filesize);
- fseek(stream, 0, SEEK_SET);
-
- do
- {
- bytes_read = fread(*buf+total_bytes, 1, filesize-total_bytes, stream);
- total_bytes += bytes_read;
- } while (total_bytes < filesize && bytes_read > 0);
-
- fclose(stream);
- return filesize;
-}
-#endif
-
-/**
- * Initialise the Random Number Generator engine.
- * - On Win32 use the platform SDK's crypto engine.
- * - On Linux use /dev/urandom
- * - If none of these work then use a custom RNG.
- */
-EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size)
-{
- if (rng_ref_count == 0)
- {
-#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
- rng_fd = ax_open("/dev/urandom", O_RDONLY);
-#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
- if (!CryptAcquireContext(&gCryptProv,
- NULL, NULL, PROV_RSA_FULL, 0))
- {
- if (GetLastError() == NTE_BAD_KEYSET &&
- !CryptAcquireContext(&gCryptProv,
- NULL,
- NULL,
- PROV_RSA_FULL,
- CRYPT_NEWKEYSET))
- {
- printf("CryptoLib: %x\n", unsupported_str, GetLastError());
- exit(1);
- }
- }
-#else
- int i;
- uint32_t seed_addr_val = (uint32_t)&seed_buf;
- uint32_t *ep = (uint32_t *)entropy_pool;
-
- /* help start the entropy with the user's private key - this is
- a number that should be hard to find, due to the fact that it
- relies on knowing the private key */
- memcpy(entropy_pool, seed_buf, ENTROPY_POOL_SIZE);
- srand((long)entropy_pool);
-
- /* mix it up a little with a stack address */
- for (i = 0; i < ENTROPY_POOL_SIZE/4; i++)
- ep[i] ^= seed_addr_val;
-
-#endif
- }
-
- rng_ref_count++;
-}
-
-/**
- * Terminate the RNG engine.
- */
-EXP_FUNC void STDCALL RNG_terminate(void)
-{
- if (--rng_ref_count == 0)
- {
-#ifndef WIN32
- close(rng_fd);
-#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
- CryptReleaseContext(gCryptProv, 0);
-#endif
- }
-}
-
-/**
- * Set a series of bytes with a random number. Individual bytes can be 0
- */
-EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
-{
-#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
- /* use the Linux default */
- read(rng_fd, rand_data, num_rand_bytes); /* read from /dev/urandom */
-#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
- /* use Microsoft Crypto Libraries */
- CryptGenRandom(gCryptProv, num_rand_bytes, rand_data);
-#else /* nothing else to use, so use a custom RNG */
- /* The method we use when we've got nothing better. Use RC4, time
- and a couple of random seeds to generate a random sequence */
- RC4_CTX rng_ctx;
- struct timeval tv;
- MD5_CTX rng_digest_ctx;
- uint8_t digest[MD5_SIZE];
- uint64_t *ep;
- int i;
-
- /* A proper implementation would use counters etc for entropy */
- gettimeofday(&tv, NULL);
- ep = (uint64_t *)entropy_pool;
- ep[0] ^= ENTROPY_COUNTER1;
- ep[1] ^= ENTROPY_COUNTER2;
-
- /* use a digested version of the entropy pool as a key */
- MD5_Init(&rng_digest_ctx);
- MD5_Update(&rng_digest_ctx, entropy_pool, ENTROPY_POOL_SIZE);
- MD5_Final(digest, &rng_digest_ctx);
-
- /* come up with the random sequence */
- RC4_setup(&rng_ctx, digest, MD5_SIZE); /* use as a key */
- memcpy(rand_data, entropy_pool, num_rand_bytes < ENTROPY_POOL_SIZE ?
- num_rand_bytes : ENTROPY_POOL_SIZE);
- RC4_crypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
-
- /* move things along */
- for (i = ENTROPY_POOL_SIZE-1; i >= MD5_SIZE ; i--)
- entropy_pool[i] = entropy_pool[i-MD5_SIZE];
-
- /* insert the digest at the start of the entropy pool */
- memcpy(entropy_pool, digest, MD5_SIZE);
-#endif
-}
-
-/**
- * Set a series of bytes with a random number. Individual bytes are not zero.
- */
-void get_random_NZ(int num_rand_bytes, uint8_t *rand_data)
-{
- int i;
- get_random(num_rand_bytes, rand_data);
-
- for (i = 0; i < num_rand_bytes; i++)
- {
- while (rand_data[i] == 0) /* can't be 0 */
- rand_data[i] = (uint8_t)(rand());
- }
-}
-
-/**
- * Some useful diagnostic routines
- */
-#if defined(CONFIG_SSL_FULL_MODE) || defined(CONFIG_DEBUG)
-int hex_finish;
-int hex_index;
-
-static void print_hex_init(int finish)
-{
- hex_finish = finish;
- hex_index = 0;
-}
-
-static void print_hex(uint8_t hex)
-{
- static int column;
-
- if (hex_index == 0)
- {
- column = 0;
- }
-
- printf("%02x ", hex);
- if (++column == 8)
- {
- printf(": ");
- }
- else if (column >= 16)
- {
- printf("\n");
- column = 0;
- }
-
- if (++hex_index >= hex_finish && column > 0)
- {
- printf("\n");
- }
-}
-
-/**
- * Spit out a blob of data for diagnostics. The data is is a nice column format
- * for easy reading.
- *
- * @param format [in] The string (with possible embedded format characters)
- * @param size [in] The number of numbers to print
- * @param data [in] The start of data to use
- * @param ... [in] Any additional arguments
- */
-EXP_FUNC void STDCALL print_blob(const char *format,
- const uint8_t *data, int size, ...)
-{
- int i;
- char tmp[80];
- va_list(ap);
-
- va_start(ap, size);
- sprintf(tmp, "%s\n", format);
- vprintf(tmp, ap);
- print_hex_init(size);
- for (i = 0; i < size; i++)
- {
- print_hex(data[i]);
- }
-
- va_end(ap);
- TTY_FLUSH();
-}
-#elif defined(WIN32)
-/* VC6.0 doesn't handle variadic macros */
-EXP_FUNC void STDCALL print_blob(const char *format, const unsigned char *data,
- int size, ...) {}
-#endif
-
-#if defined(CONFIG_SSL_HAS_PEM) || defined(CONFIG_HTTP_HAS_AUTHORIZATION)
-/* base64 to binary lookup table */
-static const uint8_t map[128] =
-{
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
- 255, 254, 255, 255, 255, 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, 255, 255, 255, 255, 255,
- 255, 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, 255, 255, 255, 255, 255
-};
-
-EXP_FUNC int STDCALL base64_decode(const char *in, int len,
- uint8_t *out, int *outlen)
-{
- int g, t, x, y, z;
- uint8_t c;
- int ret = -1;
-
- g = 3;
- for (x = y = z = t = 0; x < len; x++)
- {
- if ((c = map[in[x]&0x7F]) == 0xff)
- continue;
-
- if (c == 254) /* this is the end... */
- {
- c = 0;
-
- if (--g < 0)
- goto error;
- }
- else if (g != 3) /* only allow = at end */
- goto error;
-
- t = (t<<6) | c;
-
- if (++y == 4)
- {
- out[z++] = (uint8_t)((t>>16)&255);
-
- if (g > 1)
- out[z++] = (uint8_t)((t>>8)&255);
-
- if (g > 2)
- out[z++] = (uint8_t)(t&255);
-
- y = t = 0;
- }
- }
-
- if (y != 0)
- goto error;
-
- if (outlen)
- *outlen = z;
- ret = 0;
-
-error:
-#ifdef CONFIG_SSL_FULL_MODE
- if (ret < 0)
- printf("Error: Invalid base64\n"); TTY_FLUSH();
-#endif
- TTY_FLUSH();
- return ret;
-
-}
-#endif
-
diff --git a/axTLS/src/crypto/hmac.c b/axTLS/src/crypto/hmac.c
deleted file mode 100644
index 24a04d7..0000000
--- a/axTLS/src/crypto/hmac.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * HMAC implementation - This code was originally taken from RFC2104
- * See http://www.ietf.org/rfc/rfc2104.txt and
- * http://www.faqs.org/rfcs/rfc2202.html
- */
-
-#include <string.h>
-#include "os_port.h"
-#include "crypto.h"
-
-/**
- * Perform HMAC-MD5
- * NOTE: does not handle keys larger than the block size.
- */
-void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
- int key_len, uint8_t *digest)
-{
- MD5_CTX context;
- uint8_t k_ipad[64];
- uint8_t k_opad[64];
- int i;
-
- memset(k_ipad, 0, sizeof k_ipad);
- memset(k_opad, 0, sizeof k_opad);
- memcpy(k_ipad, key, key_len);
- memcpy(k_opad, key, key_len);
-
- for (i = 0; i < 64; i++)
- {
- k_ipad[i] ^= 0x36;
- k_opad[i] ^= 0x5c;
- }
-
- MD5_Init(&context);
- MD5_Update(&context, k_ipad, 64);
- MD5_Update(&context, msg, length);
- MD5_Final(digest, &context);
- MD5_Init(&context);
- MD5_Update(&context, k_opad, 64);
- MD5_Update(&context, digest, MD5_SIZE);
- MD5_Final(digest, &context);
-}
-
-/**
- * Perform HMAC-SHA1
- * NOTE: does not handle keys larger than the block size.
- */
-void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
- int key_len, uint8_t *digest)
-{
- SHA1_CTX context;
- uint8_t k_ipad[64];
- uint8_t k_opad[64];
- int i;
-
- memset(k_ipad, 0, sizeof k_ipad);
- memset(k_opad, 0, sizeof k_opad);
- memcpy(k_ipad, key, key_len);
- memcpy(k_opad, key, key_len);
-
- for (i = 0; i < 64; i++)
- {
- k_ipad[i] ^= 0x36;
- k_opad[i] ^= 0x5c;
- }
-
- SHA1_Init(&context);
- SHA1_Update(&context, k_ipad, 64);
- SHA1_Update(&context, msg, length);
- SHA1_Final(digest, &context);
- SHA1_Init(&context);
- SHA1_Update(&context, k_opad, 64);
- SHA1_Update(&context, digest, SHA1_SIZE);
- SHA1_Final(digest, &context);
-}
diff --git a/axTLS/src/crypto/md2.c b/axTLS/src/crypto/md2.c
deleted file mode 100644
index dee909a..0000000
--- a/axTLS/src/crypto/md2.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * RFC 1115/1319 compliant MD2 implementation
- * The MD2 algorithm was designed by Ron Rivest in 1989.
- *
- * http://www.ietf.org/rfc/rfc1115.txt
- * http://www.ietf.org/rfc/rfc1319.txt
- */
-
-#include <string.h>
-#include <stdio.h>
-#include "os_port.h"
-#include "crypto.h"
-
-/**
- * This code is only here to enable the verification of Verisign root
- * certificates. So only enable it for verification mode.
- */
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-
-static const uint8_t PI_SUBST[256] =
-{
- 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
- 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
- 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
- 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
- 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
- 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
- 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
- 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
- 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
- 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
- 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
- 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
- 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
- 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
- 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
- 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
- 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
- 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
- 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
- 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
- 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
- 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
- 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
- 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
- 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
- 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
-};
-
-/*
- * MD2 context setup
- */
-EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx)
-{
- memset(ctx, 0, sizeof *ctx);
-}
-
-static void md2_process(MD2_CTX *ctx)
-{
- int i, j;
- uint8_t t = 0;
-
- for (i = 0; i < 16; i++)
- {
- ctx->state[i + 16] = ctx->buffer[i];
- ctx->state[i + 32] = ctx->buffer[i] ^ ctx->state[i];
- }
-
- for (i = 0; i < 18; i++)
- {
- for (j = 0; j < 48; j++)
- t = (ctx->state[j] ^= PI_SUBST[t]);
-
- t = (t + i) & 0xFF;
- }
-
- t = ctx->cksum[15];
-
- for (i = 0; i < 16; i++)
- t = (ctx->cksum[i] ^= PI_SUBST[ctx->buffer[i] ^ t]);
-}
-
-/*
- * MD2 process buffer
- */
-EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen)
-{
- int fill;
-
- while (ilen > 0)
- {
- if (ctx->left + ilen > 16)
- fill = 16 - ctx->left;
- else
- fill = ilen;
-
- memcpy(ctx->buffer + ctx->left, input, fill);
-
- ctx->left += fill;
- input += fill;
- ilen -= fill;
-
- if (ctx->left == 16)
- {
- ctx->left = 0;
- md2_process(ctx);
- }
- }
-}
-
-/*
- * MD2 final digest
- */
-EXP_FUNC void STDCALL MD2_Final(uint8_t *output, MD2_CTX *ctx)
-{
- int i;
- uint8_t x;
-
- x = (uint8_t)(16 - ctx->left);
-
- for (i = ctx->left; i < 16; i++)
- ctx->buffer[i] = x;
-
- md2_process(ctx);
-
- memcpy(ctx->buffer, ctx->cksum, 16);
- md2_process(ctx);
-
- memcpy(output, ctx->state, 16);
-}
-
-#endif
diff --git a/axTLS/src/crypto/md5.c b/axTLS/src/crypto/md5.c
deleted file mode 100644
index 7f50713..0000000
--- a/axTLS/src/crypto/md5.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * This file implements the MD5 algorithm as defined in RFC1321
- */
-
-#include <string.h>
-#include "os_port.h"
-#include "crypto.h"
-
-/* Constants for MD5Transform routine.
- */
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-/* ----- static functions ----- */
-static void MD5Transform(uint32_t state[4], const uint8_t block[64]);
-static void Encode(uint8_t *output, uint32_t *input, uint32_t len);
-static void Decode(uint32_t *output, const uint8_t *input, uint32_t len);
-
-static const uint8_t PADDING[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits. */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
- Rotation is separate from addition to prevent recomputation. */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-
-/**
- * MD5 initialization - begins an MD5 operation, writing a new ctx.
- */
-EXP_FUNC void STDCALL MD5_Init(MD5_CTX *ctx)
-{
- ctx->count[0] = ctx->count[1] = 0;
-
- /* Load magic initialization constants.
- */
- ctx->state[0] = 0x67452301;
- ctx->state[1] = 0xefcdab89;
- ctx->state[2] = 0x98badcfe;
- ctx->state[3] = 0x10325476;
-}
-
-/**
- * Accepts an array of octets as the next portion of the message.
- */
-EXP_FUNC void STDCALL MD5_Update(MD5_CTX *ctx, const uint8_t * msg, int len)
-{
- uint32_t x;
- int i, partLen;
-
- /* Compute number of bytes mod 64 */
- x = (uint32_t)((ctx->count[0] >> 3) & 0x3F);
-
- /* Update number of bits */
- if ((ctx->count[0] += ((uint32_t)len << 3)) < ((uint32_t)len << 3))
- ctx->count[1]++;
- ctx->count[1] += ((uint32_t)len >> 29);
-
- partLen = 64 - x;
-
- /* Transform as many times as possible. */
- if (len >= partLen)
- {
- memcpy(&ctx->buffer[x], msg, partLen);
- MD5Transform(ctx->state, ctx->buffer);
-
- for (i = partLen; i + 63 < len; i += 64)
- MD5Transform(ctx->state, &msg[i]);
-
- x = 0;
- }
- else
- i = 0;
-
- /* Buffer remaining input */
- memcpy(&ctx->buffer[x], &msg[i], len-i);
-}
-
-/**
- * Return the 128-bit message digest into the user's array
- */
-EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *ctx)
-{
- uint8_t bits[8];
- uint32_t x, padLen;
-
- /* Save number of bits */
- Encode(bits, ctx->count, 8);
-
- /* Pad out to 56 mod 64.
- */
- x = (uint32_t)((ctx->count[0] >> 3) & 0x3f);
- padLen = (x < 56) ? (56 - x) : (120 - x);
- MD5_Update(ctx, PADDING, padLen);
-
- /* Append length (before padding) */
- MD5_Update(ctx, bits, 8);
-
- /* Store state in digest */
- Encode(digest, ctx->state, MD5_SIZE);
-}
-
-/**
- * MD5 basic transformation. Transforms state based on block.
- */
-static void MD5Transform(uint32_t state[4], const uint8_t block[64])
-{
- uint32_t a = state[0], b = state[1], c = state[2],
- d = state[3], x[MD5_SIZE];
-
- Decode(x, block, 64);
-
- /* Round 1 */
- FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
- FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
- FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
- FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
- FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
- FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
- FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
- FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
- FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
- FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
- FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
- FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
- FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
- FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
- FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
- FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
- GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
- GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
- GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
- GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
- GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
- GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
- GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
- GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
- GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
- GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
- GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
- GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
- GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
- GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
- GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
- GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
- HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
- HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
- HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
- HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
- HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
- HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
- HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
- HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
- HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
- HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
- HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
- HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
- HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
- HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
- HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
- HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
- II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
- II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
- II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
- II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
- II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
- II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
- II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
- II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
- II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
- II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
- II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
- II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
- II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
- II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
- II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
- II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
-}
-
-/**
- * Encodes input (uint32_t) into output (uint8_t). Assumes len is
- * a multiple of 4.
- */
-static void Encode(uint8_t *output, uint32_t *input, uint32_t len)
-{
- uint32_t i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- {
- output[j] = (uint8_t)(input[i] & 0xff);
- output[j+1] = (uint8_t)((input[i] >> 8) & 0xff);
- output[j+2] = (uint8_t)((input[i] >> 16) & 0xff);
- output[j+3] = (uint8_t)((input[i] >> 24) & 0xff);
- }
-}
-
-/**
- * Decodes input (uint8_t) into output (uint32_t). Assumes len is
- * a multiple of 4.
- */
-static void Decode(uint32_t *output, const uint8_t *input, uint32_t len)
-{
- uint32_t i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
- (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
-}
diff --git a/axTLS/src/crypto/rc4.c b/axTLS/src/crypto/rc4.c
deleted file mode 100644
index 12a1211..0000000
--- a/axTLS/src/crypto/rc4.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * An implementation of the RC4/ARC4 algorithm.
- * Originally written by Christophe Devine.
- */
-
-#include <string.h>
-#include "os_port.h"
-#include "crypto.h"
-
-/**
- * Get ready for an encrypt/decrypt operation
- */
-void RC4_setup(RC4_CTX *ctx, const uint8_t *key, int length)
-{
- int i, j = 0, k = 0, a;
- uint8_t *m;
-
- ctx->x = 0;
- ctx->y = 0;
- m = ctx->m;
-
- for (i = 0; i < 256; i++)
- m[i] = i;
-
- for (i = 0; i < 256; i++)
- {
- a = m[i];
- j = (uint8_t)(j + a + key[k]);
- m[i] = m[j];
- m[j] = a;
-
- if (++k >= length)
- k = 0;
- }
-}
-
-/**
- * Perform the encrypt/decrypt operation (can use it for either since
- * this is a stream cipher).
- * NOTE: *msg and *out must be the same pointer (performance tweak)
- */
-void RC4_crypt(RC4_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
-{
- int i;
- uint8_t *m, x, y, a, b;
-
- x = ctx->x;
- y = ctx->y;
- m = ctx->m;
-
- for (i = 0; i < length; i++)
- {
- a = m[++x];
- y += a;
- m[x] = b = m[y];
- m[y] = a;
- out[i] ^= m[(uint8_t)(a + b)];
- }
-
- ctx->x = x;
- ctx->y = y;
-}
diff --git a/axTLS/src/crypto/rsa.c b/axTLS/src/crypto/rsa.c
deleted file mode 100644
index 143e66a..0000000
--- a/axTLS/src/crypto/rsa.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Implements the RSA public encryption algorithm. Uses the bigint library to
- * perform its calculations.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <stdlib.h>
-#include "os_port.h"
-#include "crypto.h"
-
-void RSA_priv_key_new(RSA_CTX **ctx,
- const uint8_t *modulus, int mod_len,
- const uint8_t *pub_exp, int pub_len,
- const uint8_t *priv_exp, int priv_len
-#if CONFIG_BIGINT_CRT
- , const uint8_t *p, int p_len,
- const uint8_t *q, int q_len,
- const uint8_t *dP, int dP_len,
- const uint8_t *dQ, int dQ_len,
- const uint8_t *qInv, int qInv_len
-#endif
- )
-{
- RSA_CTX *rsa_ctx;
- BI_CTX *bi_ctx;
- RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len);
- rsa_ctx = *ctx;
- bi_ctx = rsa_ctx->bi_ctx;
- rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len);
- bi_permanent(rsa_ctx->d);
-
-#ifdef CONFIG_BIGINT_CRT
- rsa_ctx->p = bi_import(bi_ctx, p, p_len);
- rsa_ctx->q = bi_import(bi_ctx, q, q_len);
- rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len);
- rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len);
- rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len);
- bi_permanent(rsa_ctx->dP);
- bi_permanent(rsa_ctx->dQ);
- bi_permanent(rsa_ctx->qInv);
- bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET);
- bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET);
-#endif
-}
-
-void RSA_pub_key_new(RSA_CTX **ctx,
- const uint8_t *modulus, int mod_len,
- const uint8_t *pub_exp, int pub_len)
-{
- RSA_CTX *rsa_ctx;
- BI_CTX *bi_ctx;
-
- if (*ctx) /* if we load multiple certs, dump the old one */
- RSA_free(*ctx);
-
- bi_ctx = bi_initialize();
- *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX));
- rsa_ctx = *ctx;
- rsa_ctx->bi_ctx = bi_ctx;
- rsa_ctx->num_octets = mod_len;
- rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len);
- bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET);
- rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len);
- bi_permanent(rsa_ctx->e);
-}
-
-/**
- * Free up any RSA context resources.
- */
-void RSA_free(RSA_CTX *rsa_ctx)
-{
- BI_CTX *bi_ctx;
- if (rsa_ctx == NULL) /* deal with ptrs that are null */
- return;
-
- bi_ctx = rsa_ctx->bi_ctx;
-
- bi_depermanent(rsa_ctx->e);
- bi_free(bi_ctx, rsa_ctx->e);
- bi_free_mod(rsa_ctx->bi_ctx, BIGINT_M_OFFSET);
-
- if (rsa_ctx->d)
- {
- bi_depermanent(rsa_ctx->d);
- bi_free(bi_ctx, rsa_ctx->d);
-#ifdef CONFIG_BIGINT_CRT
- bi_depermanent(rsa_ctx->dP);
- bi_depermanent(rsa_ctx->dQ);
- bi_depermanent(rsa_ctx->qInv);
- bi_free(bi_ctx, rsa_ctx->dP);
- bi_free(bi_ctx, rsa_ctx->dQ);
- bi_free(bi_ctx, rsa_ctx->qInv);
- bi_free_mod(rsa_ctx->bi_ctx, BIGINT_P_OFFSET);
- bi_free_mod(rsa_ctx->bi_ctx, BIGINT_Q_OFFSET);
-#endif
- }
-
- bi_terminate(bi_ctx);
- free(rsa_ctx);
-}
-
-/**
- * @brief Use PKCS1.5 for decryption/verification.
- * @param ctx [in] The context
- * @param in_data [in] The data to encrypt (must be < modulus size-11)
- * @param out_data [out] The encrypted data.
- * @param is_decryption [in] Decryption or verify operation.
- * @return The number of bytes that were originally encrypted. -1 on error.
- * @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
- */
-int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data,
- uint8_t *out_data, int is_decryption)
-{
- const int byte_size = ctx->num_octets;
- int i, size;
- bigint *decrypted_bi, *dat_bi;
- uint8_t *block = (uint8_t *)alloca(byte_size);
-
- memset(out_data, 0, byte_size); /* initialise */
-
- /* decrypt */
- dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size);
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- decrypted_bi = is_decryption ? /* decrypt or verify? */
- RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi);
-#else /* always a decryption */
- decrypted_bi = RSA_private(ctx, dat_bi);
-#endif
-
- /* convert to a normal block */
- bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size);
-
- i = 10; /* start at the first possible non-padded byte */
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */
- {
- while (block[i++] == 0xff && i < byte_size);
-
- if (block[i-2] != 0xff)
- i = byte_size; /*ensure size is 0 */
- }
- else /* PKCS1.5 encryption padding is random */
-#endif
- {
- while (block[i++] && i < byte_size);
- }
- size = byte_size - i;
-
- /* get only the bit we want */
- if (size > 0)
- memcpy(out_data, &block[i], size);
-
- return size ? size : -1;
-}
-
-/**
- * Performs m = c^d mod n
- */
-bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg)
-{
-#ifdef CONFIG_BIGINT_CRT
- return bi_crt(c->bi_ctx, bi_msg, c->dP, c->dQ, c->p, c->q, c->qInv);
-#else
- BI_CTX *ctx = c->bi_ctx;
- ctx->mod_offset = BIGINT_M_OFFSET;
- return bi_mod_power(ctx, bi_msg, c->d);
-#endif
-}
-
-#ifdef CONFIG_SSL_FULL_MODE
-/**
- * Used for diagnostics.
- */
-void RSA_print(const RSA_CTX *rsa_ctx)
-{
- if (rsa_ctx == NULL)
- return;
-
- printf("----------------- RSA DEBUG ----------------\n");
- printf("Size:\t%d\n", rsa_ctx->num_octets);
- bi_print("Modulus", rsa_ctx->m);
- bi_print("Public Key", rsa_ctx->e);
- bi_print("Private Key", rsa_ctx->d);
-}
-#endif
-
-#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
-/**
- * Performs c = m^e mod n
- */
-bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg)
-{
- c->bi_ctx->mod_offset = BIGINT_M_OFFSET;
- return bi_mod_power(c->bi_ctx, bi_msg, c->e);
-}
-
-/**
- * Use PKCS1.5 for encryption/signing.
- * see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
- */
-int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
- uint8_t *out_data, int is_signing)
-{
- int byte_size = ctx->num_octets;
- int num_pads_needed = byte_size-in_len-3;
- bigint *dat_bi, *encrypt_bi;
-
- /* note: in_len+11 must be > byte_size */
- out_data[0] = 0; /* ensure encryption block is < modulus */
-
- if (is_signing)
- {
- out_data[1] = 1; /* PKCS1.5 signing pads with "0xff"'s */
- memset(&out_data[2], 0xff, num_pads_needed);
- }
- else /* randomize the encryption padding with non-zero bytes */
- {
- out_data[1] = 2;
- get_random_NZ(num_pads_needed, &out_data[2]);
- }
-
- out_data[2+num_pads_needed] = 0;
- memcpy(&out_data[3+num_pads_needed], in_data, in_len);
-
- /* now encrypt it */
- dat_bi = bi_import(ctx->bi_ctx, out_data, byte_size);
- encrypt_bi = is_signing ? RSA_private(ctx, dat_bi) :
- RSA_public(ctx, dat_bi);
- bi_export(ctx->bi_ctx, encrypt_bi, out_data, byte_size);
-
- /* save a few bytes of memory */
- bi_clear_cache(ctx->bi_ctx);
- return byte_size;
-}
-
-#endif /* CONFIG_SSL_CERT_VERIFICATION */
diff --git a/axTLS/src/crypto/sha1.c b/axTLS/src/crypto/sha1.c
deleted file mode 100644
index 1082733..0000000
--- a/axTLS/src/crypto/sha1.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * SHA1 implementation - as defined in FIPS PUB 180-1 published April 17, 1995.
- * This code was originally taken from RFC3174
- */
-
-#include <string.h>
-#include "os_port.h"
-#include "crypto.h"
-
-/*
- * Define the SHA1 circular left shift macro
- */
-#define SHA1CircularShift(bits,word) \
- (((word) << (bits)) | ((word) >> (32-(bits))))
-
-/* ----- static functions ----- */
-static void SHA1PadMessage(SHA1_CTX *ctx);
-static void SHA1ProcessMessageBlock(SHA1_CTX *ctx);
-
-/**
- * Initialize the SHA1 context
- */
-void SHA1_Init(SHA1_CTX *ctx)
-{
- ctx->Length_Low = 0;
- ctx->Length_High = 0;
- ctx->Message_Block_Index = 0;
- ctx->Intermediate_Hash[0] = 0x67452301;
- ctx->Intermediate_Hash[1] = 0xEFCDAB89;
- ctx->Intermediate_Hash[2] = 0x98BADCFE;
- ctx->Intermediate_Hash[3] = 0x10325476;
- ctx->Intermediate_Hash[4] = 0xC3D2E1F0;
-}
-
-/**
- * Accepts an array of octets as the next portion of the message.
- */
-void SHA1_Update(SHA1_CTX *ctx, const uint8_t *msg, int len)
-{
- while (len--)
- {
- ctx->Message_Block[ctx->Message_Block_Index++] = (*msg & 0xFF);
- ctx->Length_Low += 8;
-
- if (ctx->Length_Low == 0)
- ctx->Length_High++;
-
- if (ctx->Message_Block_Index == 64)
- SHA1ProcessMessageBlock(ctx);
-
- msg++;
- }
-}
-
-/**
- * Return the 160-bit message digest into the user's array
- */
-void SHA1_Final(uint8_t *digest, SHA1_CTX *ctx)
-{
- int i;
-
- SHA1PadMessage(ctx);
- memset(ctx->Message_Block, 0, 64);
- ctx->Length_Low = 0; /* and clear length */
- ctx->Length_High = 0;
-
- for (i = 0; i < SHA1_SIZE; i++)
- {
- digest[i] = ctx->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) );
- }
-}
-
-/**
- * Process the next 512 bits of the message stored in the array.
- */
-static void SHA1ProcessMessageBlock(SHA1_CTX *ctx)
-{
- const uint32_t K[] = { /* Constants defined in SHA-1 */
- 0x5A827999,
- 0x6ED9EBA1,
- 0x8F1BBCDC,
- 0xCA62C1D6
- };
- int t; /* Loop counter */
- uint32_t temp; /* Temporary word value */
- uint32_t W[80]; /* Word sequence */
- uint32_t A, B, C, D, E; /* Word buffers */
-
- /*
- * Initialize the first 16 words in the array W
- */
- for (t = 0; t < 16; t++)
- {
- W[t] = ctx->Message_Block[t * 4] << 24;
- W[t] |= ctx->Message_Block[t * 4 + 1] << 16;
- W[t] |= ctx->Message_Block[t * 4 + 2] << 8;
- W[t] |= ctx->Message_Block[t * 4 + 3];
- }
-
- for (t = 16; t < 80; t++)
- {
- W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
- }
-
- A = ctx->Intermediate_Hash[0];
- B = ctx->Intermediate_Hash[1];
- C = ctx->Intermediate_Hash[2];
- D = ctx->Intermediate_Hash[3];
- E = ctx->Intermediate_Hash[4];
-
- for (t = 0; t < 20; t++)
- {
- temp = SHA1CircularShift(5,A) +
- ((B & C) | ((~B) & D)) + E + W[t] + K[0];
- E = D;
- D = C;
- C = SHA1CircularShift(30,B);
-
- B = A;
- A = temp;
- }
-
- for (t = 20; t < 40; t++)
- {
- temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
- E = D;
- D = C;
- C = SHA1CircularShift(30,B);
- B = A;
- A = temp;
- }
-
- for (t = 40; t < 60; t++)
- {
- temp = SHA1CircularShift(5,A) +
- ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
- E = D;
- D = C;
- C = SHA1CircularShift(30,B);
- B = A;
- A = temp;
- }
-
- for (t = 60; t < 80; t++)
- {
- temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
- E = D;
- D = C;
- C = SHA1CircularShift(30,B);
- B = A;
- A = temp;
- }
-
- ctx->Intermediate_Hash[0] += A;
- ctx->Intermediate_Hash[1] += B;
- ctx->Intermediate_Hash[2] += C;
- ctx->Intermediate_Hash[3] += D;
- ctx->Intermediate_Hash[4] += E;
- ctx->Message_Block_Index = 0;
-}
-
-/*
- * According to the standard, the message must be padded to an even
- * 512 bits. The first padding bit must be a '1'. The last 64
- * bits represent the length of the original message. All bits in
- * between should be 0. This function will pad the message
- * according to those rules by filling the Message_Block array
- * accordingly. It will also call the ProcessMessageBlock function
- * provided appropriately. When it returns, it can be assumed that
- * the message digest has been computed.
- *
- * @param ctx [in, out] The SHA1 context
- */
-static void SHA1PadMessage(SHA1_CTX *ctx)
-{
- /*
- * Check to see if the current message block is too small to hold
- * the initial padding bits and length. If so, we will pad the
- * block, process it, and then continue padding into a second
- * block.
- */
- if (ctx->Message_Block_Index > 55)
- {
- ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
- while(ctx->Message_Block_Index < 64)
- {
- ctx->Message_Block[ctx->Message_Block_Index++] = 0;
- }
-
- SHA1ProcessMessageBlock(ctx);
-
- while (ctx->Message_Block_Index < 56)
- {
- ctx->Message_Block[ctx->Message_Block_Index++] = 0;
- }
- }
- else
- {
- ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
- while(ctx->Message_Block_Index < 56)
- {
-
- ctx->Message_Block[ctx->Message_Block_Index++] = 0;
- }
- }
-
- /*
- * Store the message length as the last 8 octets
- */
- ctx->Message_Block[56] = ctx->Length_High >> 24;
- ctx->Message_Block[57] = ctx->Length_High >> 16;
- ctx->Message_Block[58] = ctx->Length_High >> 8;
- ctx->Message_Block[59] = ctx->Length_High;
- ctx->Message_Block[60] = ctx->Length_Low >> 24;
- ctx->Message_Block[61] = ctx->Length_Low >> 16;
- ctx->Message_Block[62] = ctx->Length_Low >> 8;
- ctx->Message_Block[63] = ctx->Length_Low;
- SHA1ProcessMessageBlock(ctx);
-}
diff --git a/axTLS/src/ssl/asn1.c b/axTLS/src/ssl/asn1.c
deleted file mode 100644
index cf8d5be..0000000
--- a/axTLS/src/ssl/asn1.c
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Some primitive asn methods for extraction ASN.1 data.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "os_port.h"
-#include "crypto.h"
-#include "crypto_misc.h"
-
-#define SIG_OID_PREFIX_SIZE 8
-#define SIG_IIS6_OID_SIZE 5
-#define SIG_SUBJECT_ALT_NAME_SIZE 3
-
-/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
-static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] =
-{
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
-};
-
-static const uint8_t sig_sha1WithRSAEncrypt[SIG_IIS6_OID_SIZE] =
-{
- 0x2b, 0x0e, 0x03, 0x02, 0x1d
-};
-
-static const uint8_t sig_subject_alt_name[SIG_SUBJECT_ALT_NAME_SIZE] =
-{
- 0x55, 0x1d, 0x11
-};
-
-/* CN, O, OU */
-static const uint8_t g_dn_types[] = { 3, 10, 11 };
-
-int get_asn1_length(const uint8_t *buf, int *offset)
-{
- int len, i;
-
- if (!(buf[*offset] & 0x80)) /* short form */
- {
- len = buf[(*offset)++];
- }
- else /* long form */
- {
- int length_bytes = buf[(*offset)++]&0x7f;
- len = 0;
- for (i = 0; i < length_bytes; i++)
- {
- len <<= 8;
- len += buf[(*offset)++];
- }
- }
-
- return len;
-}
-
-/**
- * Skip the ASN1.1 object type and its length. Get ready to read the object's
- * data.
- */
-int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
-{
- if (buf[*offset] != obj_type)
- return X509_NOT_OK;
- (*offset)++;
- return get_asn1_length(buf, offset);
-}
-
-/**
- * Skip over an ASN.1 object type completely. Get ready to read the next
- * object.
- */
-int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
-{
- int len;
-
- if (buf[*offset] != obj_type)
- return X509_NOT_OK;
- (*offset)++;
- len = get_asn1_length(buf, offset);
- *offset += len;
- return 0;
-}
-
-/**
- * Read an integer value for ASN.1 data
- * Note: This function allocates memory which must be freed by the user.
- */
-int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
-{
- int len;
-
- if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
- goto end_int_array;
-
- if (len > 1 && buf[*offset] == 0x00) /* ignore the negative byte */
- {
- len--;
- (*offset)++;
- }
-
- *object = (uint8_t *)malloc(len);
- memcpy(*object, &buf[*offset], len);
- *offset += len;
-
-end_int_array:
- return len;
-}
-
-/**
- * Get all the RSA private key specifics from an ASN.1 encoded file
- */
-int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
-{
- int offset = 7;
- uint8_t *modulus = NULL, *priv_exp = NULL, *pub_exp = NULL;
- int mod_len, priv_len, pub_len;
-#ifdef CONFIG_BIGINT_CRT
- uint8_t *p = NULL, *q = NULL, *dP = NULL, *dQ = NULL, *qInv = NULL;
- int p_len, q_len, dP_len, dQ_len, qInv_len;
-#endif
-
- /* not in der format */
- if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: This is not a valid ASN.1 file\n");
-#endif
- return X509_INVALID_PRIV_KEY;
- }
-
- /* initialise the RNG */
- RNG_initialize(buf, len);
-
- mod_len = asn1_get_int(buf, &offset, &modulus);
- pub_len = asn1_get_int(buf, &offset, &pub_exp);
- priv_len = asn1_get_int(buf, &offset, &priv_exp);
-
- if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
- return X509_INVALID_PRIV_KEY;
-
-#ifdef CONFIG_BIGINT_CRT
- p_len = asn1_get_int(buf, &offset, &p);
- q_len = asn1_get_int(buf, &offset, &q);
- dP_len = asn1_get_int(buf, &offset, &dP);
- dQ_len = asn1_get_int(buf, &offset, &dQ);
- qInv_len = asn1_get_int(buf, &offset, &qInv);
-
- if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
- return X509_INVALID_PRIV_KEY;
-
- RSA_priv_key_new(rsa_ctx,
- modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
- p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
-
- free(p);
- free(q);
- free(dP);
- free(dQ);
- free(qInv);
-#else
- RSA_priv_key_new(rsa_ctx,
- modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
-#endif
-
- free(modulus);
- free(priv_exp);
- free(pub_exp);
- return X509_OK;
-}
-
-/**
- * Get the time of a certificate. Ignore hours/minutes/seconds.
- */
-static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
-{
- int ret = X509_NOT_OK, len, t_offset;
- struct tm tm;
-
- if (buf[(*offset)++] != ASN1_UTC_TIME)
- goto end_utc_time;
-
- len = get_asn1_length(buf, offset);
- t_offset = *offset;
-
- memset(&tm, 0, sizeof(struct tm));
- tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
-
- if (tm.tm_year <= 50) /* 1951-2050 thing */
- {
- tm.tm_year += 100;
- }
-
- tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
- tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
- *t = mktime(&tm);
- *offset += len;
- ret = X509_OK;
-
-end_utc_time:
- return ret;
-}
-
-/**
- * Get the version type of a certificate (which we don't actually care about)
- */
-int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
-{
- int ret = X509_NOT_OK;
-
- (*offset) += 2; /* get past explicit tag */
- if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
- goto end_version;
-
- ret = X509_OK;
-end_version:
- return ret;
-}
-
-/**
- * Retrieve the notbefore and notafter certificate times.
- */
-int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
-{
- return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
- asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
- asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
-}
-
-/**
- * Get the components of a distinguished name
- */
-static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
-{
- int dn_type = 0;
- int len;
-
- if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
- goto end_oid;
-
- /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name
- components we are interested in. */
- if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
- dn_type = buf[(*offset)++];
- else
- {
- *offset += len; /* skip over it */
- }
-
-end_oid:
- return dn_type;
-}
-
-/**
- * Obtain an ASN.1 printable string type.
- */
-static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
-{
- int len = X509_NOT_OK;
-
- /* some certs have this awful crud in them for some reason */
- if (buf[*offset] != ASN1_PRINTABLE_STR &&
- buf[*offset] != ASN1_PRINTABLE_STR2 &&
- buf[*offset] != ASN1_TELETEX_STR &&
- buf[*offset] != ASN1_IA5_STR &&
- buf[*offset] != ASN1_UNICODE_STR)
- goto end_pnt_str;
-
- (*offset)++;
- len = get_asn1_length(buf, offset);
-
- if (buf[*offset - 1] == ASN1_UNICODE_STR)
- {
- int i;
- *str = (char *)malloc(len/2+1); /* allow for null */
-
- for (i = 0; i < len; i += 2)
- (*str)[i/2] = buf[*offset + i + 1];
-
- (*str)[len/2] = 0; /* null terminate */
- }
- else
- {
- *str = (char *)malloc(len+1); /* allow for null */
- memcpy(*str, &buf[*offset], len);
- (*str)[len] = 0; /* null terminate */
- }
-
- *offset += len;
-
-end_pnt_str:
- return len;
-}
-
-/**
- * Get the subject name (or the issuer) of a certificate.
- */
-int asn1_name(const uint8_t *cert, int *offset, char *dn[])
-{
- int ret = X509_NOT_OK;
- int dn_type;
- char *tmp;
-
- if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
- goto end_name;
-
- while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
- {
- int i, found = 0;
-
- if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
- (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
- goto end_name;
-
- tmp = NULL;
-
- if (asn1_get_printable_str(cert, offset, &tmp) < 0)
- {
- free(tmp);
- goto end_name;
- }
-
- /* find the distinguished named type */
- for (i = 0; i < X509_NUM_DN_TYPES; i++)
- {
- if (dn_type == g_dn_types[i])
- {
- if (dn[i] == NULL)
- {
- dn[i] = tmp;
- found = 1;
- break;
- }
- }
- }
-
- if (found == 0) /* not found so get rid of it */
- {
- free(tmp);
- }
- }
-
- ret = X509_OK;
-end_name:
- return ret;
-}
-
-/**
- * Read the modulus and public exponent of a certificate.
- */
-int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
-{
- int ret = X509_NOT_OK, mod_len, pub_len;
- uint8_t *modulus = NULL, *pub_exp = NULL;
-
- if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
- asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
- goto end_pub_key;
-
- (*offset)++; /* ignore the padding bit field */
-
- if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
- goto end_pub_key;
-
- mod_len = asn1_get_int(cert, offset, &modulus);
- pub_len = asn1_get_int(cert, offset, &pub_exp);
-
- RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
-
- free(modulus);
- free(pub_exp);
- ret = X509_OK;
-
-end_pub_key:
- return ret;
-}
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-/**
- * Read the signature of the certificate.
- */
-int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
-{
- int ret = X509_NOT_OK;
-
- if (cert[(*offset)++] != ASN1_BIT_STRING)
- goto end_sig;
-
- x509_ctx->sig_len = get_asn1_length(cert, offset)-1;
- (*offset)++; /* ignore bit string padding bits */
- x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
- memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
- *offset += x509_ctx->sig_len;
- ret = X509_OK;
-
-end_sig:
- return ret;
-}
-
-/*
- * Compare 2 distinguished name components for equality
- * @return 0 if a match
- */
-static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
-{
- int ret;
-
- if (dn1 == NULL && dn2 == NULL)
- ret = 0;
- else
- ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 1;
-
- return ret;
-}
-
-/**
- * Clean up all of the CA certificates.
- */
-void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
-{
- int i = 0;
-
- if (ca_cert_ctx == NULL)
- return;
-
- while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
- {
- x509_free(ca_cert_ctx->cert[i]);
- ca_cert_ctx->cert[i++] = NULL;
- }
-
- free(ca_cert_ctx);
-}
-
-/*
- * Compare 2 distinguished names for equality
- * @return 0 if a match
- */
-int asn1_compare_dn(char * const dn1[], char * const dn2[])
-{
- int i;
-
- for (i = 0; i < X509_NUM_DN_TYPES; i++)
- {
- if (asn1_compare_dn_comp(dn1[i], dn2[i]))
- return 1;
- }
-
- return 0; /* all good */
-}
-
-int asn1_find_oid(const uint8_t* cert, int* offset,
- const uint8_t* oid, int oid_length)
-{
- int seqlen;
- if ((seqlen = asn1_next_obj(cert, offset, ASN1_SEQUENCE))> 0)
- {
- int end = *offset + seqlen;
-
- while (*offset < end)
- {
- int type = cert[(*offset)++];
- int length = get_asn1_length(cert, offset);
- int noffset = *offset + length;
-
- if (type == ASN1_SEQUENCE)
- {
- type = cert[(*offset)++];
- length = get_asn1_length(cert, offset);
-
- if (type == ASN1_OID && length == oid_length &&
- memcmp(cert + *offset, oid, oid_length) == 0)
- {
- *offset += oid_length;
- return 1;
- }
- }
-
- *offset = noffset;
- }
- }
-
- return 0;
-}
-
-int asn1_find_subjectaltname(const uint8_t* cert, int offset)
-{
- if (asn1_find_oid(cert, &offset, sig_subject_alt_name,
- SIG_SUBJECT_ALT_NAME_SIZE))
- {
- return offset;
- }
-
- return 0;
-}
-
-#endif /* CONFIG_SSL_CERT_VERIFICATION */
-
-/**
- * Read the signature type of the certificate. We only support RSA-MD5 and
- * RSA-SHA1 signature types.
- */
-int asn1_signature_type(const uint8_t *cert,
- int *offset, X509_CTX *x509_ctx)
-{
- int ret = X509_NOT_OK, len;
-
- if (cert[(*offset)++] != ASN1_OID)
- goto end_check_sig;
-
- len = get_asn1_length(cert, offset);
-
- if (len == 5 && memcmp(sig_sha1WithRSAEncrypt, &cert[*offset],
- SIG_IIS6_OID_SIZE) == 0)
- {
- x509_ctx->sig_type = SIG_TYPE_SHA1;
- }
- else
- {
- if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
- goto end_check_sig; /* unrecognised cert type */
-
- x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
- }
-
- *offset += len;
- asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
- ret = X509_OK;
-
-end_check_sig:
- return ret;
-}
-
diff --git a/axTLS/src/ssl/cert.h b/axTLS/src/ssl/cert.h
deleted file mode 100644
index 30c7b65..0000000
--- a/axTLS/src/ssl/cert.h
+++ /dev/null
@@ -1,43 +0,0 @@
-unsigned char default_certificate[] = {
- 0x30, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0x40, 0x02, 0x09, 0x00, 0xab,
- 0x08, 0x18, 0xa7, 0x03, 0x07, 0x27, 0xfd, 0x30, 0x0d, 0x06, 0x09, 0x2a,
- 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x34,
- 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x29, 0x61,
- 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
- 0x20, 0x44, 0x6f, 0x64, 0x67, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
- 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
- 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x31, 0x32,
- 0x32, 0x36, 0x32, 0x32, 0x33, 0x33, 0x33, 0x39, 0x5a, 0x17, 0x0d, 0x32,
- 0x34, 0x30, 0x39, 0x30, 0x33, 0x32, 0x32, 0x33, 0x33, 0x33, 0x39, 0x5a,
- 0x30, 0x2c, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
- 0x0d, 0x61, 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65,
- 0x63, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
- 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81,
- 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
- 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
- 0x81, 0x81, 0x00, 0xcd, 0xfd, 0x89, 0x48, 0xbe, 0x36, 0xb9, 0x95, 0x76,
- 0xd4, 0x13, 0x30, 0x0e, 0xbf, 0xb2, 0xed, 0x67, 0x0a, 0xc0, 0x16, 0x3f,
- 0x51, 0x09, 0x9d, 0x29, 0x2f, 0xb2, 0x6d, 0x3f, 0x3e, 0x6c, 0x2f, 0x90,
- 0x80, 0xa1, 0x71, 0xdf, 0xbe, 0x38, 0xc5, 0xcb, 0xa9, 0x9a, 0x40, 0x14,
- 0x90, 0x0a, 0xf9, 0xb7, 0x07, 0x0b, 0xe1, 0xda, 0xe7, 0x09, 0xbf, 0x0d,
- 0x57, 0x41, 0x86, 0x60, 0xa1, 0xc1, 0x27, 0x91, 0x5b, 0x0a, 0x98, 0x46,
- 0x1b, 0xf6, 0xa2, 0x84, 0xf8, 0x65, 0xc7, 0xce, 0x2d, 0x96, 0x17, 0xaa,
- 0x91, 0xf8, 0x61, 0x04, 0x50, 0x70, 0xeb, 0xb4, 0x43, 0xb7, 0xdc, 0x9a,
- 0xcc, 0x31, 0x01, 0x14, 0xd4, 0xcd, 0xcc, 0xc2, 0x37, 0x6d, 0x69, 0x82,
- 0xd6, 0xc6, 0xc4, 0xbe, 0xf2, 0x34, 0xa5, 0xc9, 0xa6, 0x19, 0x53, 0x32,
- 0x7a, 0x86, 0x0e, 0x91, 0x82, 0x0f, 0xa1, 0x42, 0x54, 0xaa, 0x01, 0x02,
- 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
- 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x40,
- 0xb4, 0x94, 0x9a, 0xa8, 0x89, 0x72, 0x1d, 0x07, 0xe5, 0xb3, 0x6b, 0x88,
- 0x21, 0xc2, 0x38, 0x36, 0x9e, 0x7a, 0x8c, 0x49, 0x48, 0x68, 0x0c, 0x06,
- 0xe8, 0xdb, 0x1f, 0x4e, 0x05, 0xe6, 0x31, 0xe3, 0xfd, 0xe6, 0x0d, 0x6b,
- 0xd8, 0x13, 0x17, 0xe0, 0x2d, 0x0d, 0xb8, 0x7e, 0xcb, 0x20, 0x6c, 0xa8,
- 0x73, 0xa7, 0xfd, 0xe3, 0xa7, 0xfa, 0xf3, 0x02, 0x60, 0x78, 0x1f, 0x13,
- 0x40, 0x45, 0xee, 0x75, 0xf5, 0x10, 0xfd, 0x8f, 0x68, 0x74, 0xd4, 0xac,
- 0xae, 0x04, 0x09, 0x55, 0x2c, 0xdb, 0xd8, 0x07, 0x07, 0x65, 0x69, 0x27,
- 0x6e, 0xbf, 0x5e, 0x61, 0x40, 0x56, 0x8b, 0xd7, 0x33, 0x3b, 0xff, 0x6e,
- 0x53, 0x7e, 0x9d, 0x3f, 0xc0, 0x40, 0x3a, 0xab, 0xa0, 0x50, 0x4e, 0x80,
- 0x47, 0x46, 0x0d, 0x1e, 0xdb, 0x4c, 0xf1, 0x1b, 0x5d, 0x3c, 0x2a, 0x54,
- 0xa7, 0x4d, 0xfa, 0x7b, 0x72, 0x66, 0xc5
-};
-unsigned int default_certificate_len = 475;
diff --git a/axTLS/src/ssl/crypto_misc.h b/axTLS/src/ssl/crypto_misc.h
deleted file mode 100644
index 9c9e2aa..0000000
--- a/axTLS/src/ssl/crypto_misc.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/**
- * @file crypto_misc.h
- */
-
-#ifndef HEADER_CRYPTO_MISC_H
-#define HEADER_CRYPTO_MISC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "crypto.h"
-#include "bigint.h"
-
-/**************************************************************************
- * X509 declarations
- **************************************************************************/
-#define X509_OK 0
-#define X509_NOT_OK -1
-#define X509_VFY_ERROR_NO_TRUSTED_CERT -2
-#define X509_VFY_ERROR_BAD_SIGNATURE -3
-#define X509_VFY_ERROR_NOT_YET_VALID -4
-#define X509_VFY_ERROR_EXPIRED -5
-#define X509_VFY_ERROR_SELF_SIGNED -6
-#define X509_VFY_ERROR_INVALID_CHAIN -7
-#define X509_VFY_ERROR_UNSUPPORTED_DIGEST -8
-#define X509_INVALID_PRIV_KEY -9
-
-/*
- * The Distinguished Name
- */
-#define X509_NUM_DN_TYPES 3
-#define X509_COMMON_NAME 0
-#define X509_ORGANIZATION 1
-#define X509_ORGANIZATIONAL_UNIT 2
-
-struct _x509_ctx
-{
- char *ca_cert_dn[X509_NUM_DN_TYPES];
- char *cert_dn[X509_NUM_DN_TYPES];
- char **subject_alt_dnsnames;
- time_t not_before;
- time_t not_after;
- uint8_t *signature;
- uint16_t sig_len;
- uint8_t sig_type;
- RSA_CTX *rsa_ctx;
- bigint *digest;
- uint8_t sha1_fingerprint[SHA1_SIZE];
- struct _x509_ctx *next;
-};
-
-typedef struct _x509_ctx X509_CTX;
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-typedef struct
-{
- X509_CTX *cert[CONFIG_X509_MAX_CA_CERTS];
-} CA_CERT_CTX;
-#endif
-
-int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx);
-void x509_free(X509_CTX *x509_ctx);
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert);
-#endif
-#ifdef CONFIG_SSL_FULL_MODE
-void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx);
-const char * x509_display_error(int error);
-#endif
-
-/**************************************************************************
- * ASN1 declarations
- **************************************************************************/
-#define ASN1_INTEGER 0x02
-#define ASN1_BIT_STRING 0x03
-#define ASN1_OCTET_STRING 0x04
-#define ASN1_NULL 0x05
-#define ASN1_PRINTABLE_STR2 0x0C
-#define ASN1_OID 0x06
-#define ASN1_PRINTABLE_STR2 0x0C
-#define ASN1_PRINTABLE_STR 0x13
-#define ASN1_TELETEX_STR 0x14
-#define ASN1_IA5_STR 0x16
-#define ASN1_UTC_TIME 0x17
-#define ASN1_UNICODE_STR 0x1e
-#define ASN1_SEQUENCE 0x30
-#define ASN1_CONTEXT_DNSNAME 0x82
-#define ASN1_SET 0x31
-#define ASN1_V3_DATA 0xa3
-#define ASN1_IMPLICIT_TAG 0x80
-#define ASN1_CONTEXT_DNSNAME 0x82
-#define ASN1_EXPLICIT_TAG 0xa0
-#define ASN1_V3_DATA 0xa3
-
-#define SIG_TYPE_MD2 0x02
-#define SIG_TYPE_MD5 0x04
-#define SIG_TYPE_SHA1 0x05
-
-int get_asn1_length(const uint8_t *buf, int *offset);
-int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx);
-int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type);
-int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type);
-int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object);
-int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
-int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
-int asn1_name(const uint8_t *cert, int *offset, char *dn[]);
-int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
-int asn1_find_subjectaltname(const uint8_t* cert, int offset);
-int asn1_compare_dn(char * const dn1[], char * const dn2[]);
-#endif /* CONFIG_SSL_CERT_VERIFICATION */
-int asn1_signature_type(const uint8_t *cert,
- int *offset, X509_CTX *x509_ctx);
-
-/**************************************************************************
- * MISC declarations
- **************************************************************************/
-#define SALT_SIZE 8
-
-extern const char * const unsupported_str;
-
-typedef void (*crypt_func)(void *, const uint8_t *, uint8_t *, int);
-typedef void (*hmac_func)(const uint8_t *msg, int length, const uint8_t *key,
- int key_len, uint8_t *digest);
-
-int get_file(const char *filename, uint8_t **buf);
-
-#if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG)
-EXP_FUNC void STDCALL print_blob(const char *format, const uint8_t *data, int size, ...);
-#else
- #define print_blob(...)
-#endif
-
-EXP_FUNC int STDCALL base64_decode(const char *in, int len,
- uint8_t *out, int *outlen);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/axTLS/src/ssl/gen_cert.c b/axTLS/src/ssl/gen_cert.c
deleted file mode 100644
index c2fe381..0000000
--- a/axTLS/src/ssl/gen_cert.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#ifdef CONFIG_SSL_GENERATE_X509_CERT
-#include <string.h>
-#include <stdlib.h>
-#include "os_port.h"
-#include "ssl.h"
-
-/**
- * Generate a basic X.509 certificate
- */
-
-static uint8_t set_gen_length(int len, uint8_t *buf, int *offset)
-{
- if (len < 0x80) /* short form */
- {
- buf[(*offset)++] = len;
- return 1;
- }
- else /* long form */
- {
- int i, length_bytes = 0;
-
- if (len & 0x00FF0000)
- length_bytes = 3;
- else if (len & 0x0000FF00)
- length_bytes = 2;
- else if (len & 0x000000FF)
- length_bytes = 1;
-
- buf[(*offset)++] = 0x80 + length_bytes;
-
- for (i = length_bytes-1; i >= 0; i--)
- {
- buf[*offset+i] = len & 0xFF;
- len >>= 8;
- }
-
- *offset += length_bytes;
- return length_bytes+1;
- }
-}
-
-static int pre_adjust_with_size(uint8_t type,
- int *seq_offset, uint8_t *buf, int *offset)
-{
- buf[(*offset)++] = type;
- *seq_offset = *offset;
- *offset += 4; /* fill in later */
- return *offset;
-}
-
-static void adjust_with_size(int seq_size, int seq_start,
- uint8_t *buf, int *offset)
-{
- uint8_t seq_byte_size;
- int orig_seq_size = seq_size;
- int orig_seq_start = seq_start;
-
- seq_size = *offset-seq_size;
- seq_byte_size = set_gen_length(seq_size, buf, &seq_start);
-
- if (seq_byte_size != 4)
- {
- memmove(&buf[orig_seq_start+seq_byte_size],
- &buf[orig_seq_size], seq_size);
- *offset -= 4-seq_byte_size;
- }
-}
-
-static void gen_serial_number(uint8_t *buf, int *offset)
-{
- static const uint8_t ser_oid[] = { ASN1_INTEGER, 1, 0x7F };
- memcpy(&buf[*offset], ser_oid , sizeof(ser_oid));
- *offset += sizeof(ser_oid);
-}
-
-static void gen_signature_alg(uint8_t *buf, int *offset)
-{
- /* OBJECT IDENTIFIER sha1withRSAEncryption (1 2 840 113549 1 1 5) */
- static const uint8_t sig_oid[] =
- {
- ASN1_SEQUENCE, 0x0d, ASN1_OID, 0x09,
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
- ASN1_NULL, 0x00
- };
-
- memcpy(&buf[*offset], sig_oid, sizeof(sig_oid));
- *offset += sizeof(sig_oid);
-}
-
-static int gen_dn(const char *name, uint8_t dn_type,
- uint8_t *buf, int *offset)
-{
- int ret = X509_OK;
- int name_size = strlen(name);
-
- if (name_size > 0x70) /* just too big */
- {
- ret = X509_NOT_OK;
- goto error;
- }
-
- buf[(*offset)++] = ASN1_SET;
- set_gen_length(9+name_size, buf, offset);
- buf[(*offset)++] = ASN1_SEQUENCE;
- set_gen_length(7+name_size, buf, offset);
- buf[(*offset)++] = ASN1_OID;
- buf[(*offset)++] = 3;
- buf[(*offset)++] = 0x55;
- buf[(*offset)++] = 0x04;
- buf[(*offset)++] = dn_type;
- buf[(*offset)++] = ASN1_PRINTABLE_STR;
- buf[(*offset)++] = name_size;
- strcpy(&buf[*offset], name);
- *offset += name_size;
-
-error:
- return ret;
-}
-
-static int gen_issuer(const char * dn[], uint8_t *buf, int *offset)
-{
- int ret = X509_OK;
- int seq_offset;
- int seq_size = pre_adjust_with_size(
- ASN1_SEQUENCE, &seq_offset, buf, offset);
- char fqdn[128];
-
- /* we need the common name, so if not configured, work out the fully
- * qualified domain name */
- if (dn[X509_COMMON_NAME] == NULL || strlen(dn[X509_COMMON_NAME]) == 0)
- {
- int fqdn_len;
- gethostname(fqdn, sizeof(fqdn));
- fqdn_len = strlen(fqdn);
- fqdn[fqdn_len++] = '.';
- getdomainname(&fqdn[fqdn_len], sizeof(fqdn)-fqdn_len);
- fqdn_len = strlen(fqdn);
-
- if (fqdn[fqdn_len-1] == '.') /* ensure '.' is not last char */
- fqdn[fqdn_len-1] = 0;
-
- dn[X509_COMMON_NAME] = fqdn;
- }
-
- if ((ret = gen_dn(dn[X509_COMMON_NAME], 3, buf, offset)))
- goto error;
-
- if (dn[X509_ORGANIZATION] != NULL && strlen(dn[X509_ORGANIZATION]) > 0)
- {
- if ((ret = gen_dn(dn[X509_ORGANIZATION], 10, buf, offset)))
- goto error;
- }
-
- if (dn[X509_ORGANIZATIONAL_UNIT] != NULL &&
- strlen(dn[X509_ORGANIZATIONAL_UNIT]) > 0)
- {
- if ((ret = gen_dn(dn[X509_ORGANIZATIONAL_UNIT], 11, buf, offset)))
- goto error;
- }
-
- adjust_with_size(seq_size, seq_offset, buf, offset);
-
-error:
- return ret;
-}
-
-static void gen_utc_time(uint8_t *buf, int *offset)
-{
- static const uint8_t time_seq[] =
- {
- ASN1_SEQUENCE, 30,
- ASN1_UTC_TIME, 13,
- '0', '7', '0', '1', '0', '1', '0', '0', '0', '0', '0', '0', 'Z',
- ASN1_UTC_TIME, 13, /* make it good for 30 or so years */
- '3', '8', '0', '1', '0', '1', '0', '0', '0', '0', '0', '0', 'Z'
- };
-
- /* fixed time */
- memcpy(&buf[*offset], time_seq, sizeof(time_seq));
- *offset += sizeof(time_seq);
-}
-
-static void gen_pub_key2(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
-{
- static const uint8_t pub_key_seq[] =
- {
- ASN1_INTEGER, 0x03, 0x01, 0x00, 0x01 /* INTEGER 65537 */
- };
-
- int seq_offset;
- int pub_key_size = rsa_ctx->num_octets;
- uint8_t *block = (uint8_t *)alloca(pub_key_size);
- int seq_size = pre_adjust_with_size(
- ASN1_SEQUENCE, &seq_offset, buf, offset);
- buf[(*offset)++] = ASN1_INTEGER;
- bi_export(rsa_ctx->bi_ctx, rsa_ctx->m, block, pub_key_size);
-
- if (*block & 0x80) /* make integer positive */
- {
- set_gen_length(pub_key_size+1, buf, offset);
- buf[(*offset)++] = 0;
- }
- else
- set_gen_length(pub_key_size, buf, offset);
-
- memcpy(&buf[*offset], block, pub_key_size);
- *offset += pub_key_size;
- memcpy(&buf[*offset], pub_key_seq, sizeof(pub_key_seq));
- *offset += sizeof(pub_key_seq);
- adjust_with_size(seq_size, seq_offset, buf, offset);
-}
-
-static void gen_pub_key1(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
-{
- int seq_offset;
- int seq_size = pre_adjust_with_size(
- ASN1_BIT_STRING, &seq_offset, buf, offset);
- buf[(*offset)++] = 0; /* bit string is multiple of 8 */
- gen_pub_key2(rsa_ctx, buf, offset);
- adjust_with_size(seq_size, seq_offset, buf, offset);
-}
-
-static void gen_pub_key(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
-{
- /* OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) */
- static const uint8_t rsa_enc_oid[] =
- {
- ASN1_SEQUENCE, 0x0d, ASN1_OID, 0x09,
- 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
- ASN1_NULL, 0x00
- };
-
- int seq_offset;
- int seq_size = pre_adjust_with_size(
- ASN1_SEQUENCE, &seq_offset, buf, offset);
-
- memcpy(&buf[*offset], rsa_enc_oid, sizeof(rsa_enc_oid));
- *offset += sizeof(rsa_enc_oid);
- gen_pub_key1(rsa_ctx, buf, offset);
- adjust_with_size(seq_size, seq_offset, buf, offset);
-}
-
-static void gen_signature(const RSA_CTX *rsa_ctx, const uint8_t *sha_dgst,
- uint8_t *buf, int *offset)
-{
- static const uint8_t asn1_sig[] =
- {
- ASN1_SEQUENCE, 0x21, ASN1_SEQUENCE, 0x09, ASN1_OID, 0x05,
- 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* sha1 (1 3 14 3 2 26) */
- ASN1_NULL, 0x00, ASN1_OCTET_STRING, 0x14
- };
-
- uint8_t *enc_block = (uint8_t *)alloca(rsa_ctx->num_octets);
- uint8_t *block = (uint8_t *)alloca(sizeof(asn1_sig) + SHA1_SIZE);
- int sig_size;
-
- /* add the digest as an embedded asn.1 sequence */
- memcpy(block, asn1_sig, sizeof(asn1_sig));
- memcpy(&block[sizeof(asn1_sig)], sha_dgst, SHA1_SIZE);
-
- sig_size = RSA_encrypt(rsa_ctx, block,
- sizeof(asn1_sig) + SHA1_SIZE, enc_block, 1);
-
- buf[(*offset)++] = ASN1_BIT_STRING;
- set_gen_length(sig_size+1, buf, offset);
- buf[(*offset)++] = 0; /* bit string is multiple of 8 */
- memcpy(&buf[*offset], enc_block, sig_size);
- *offset += sig_size;
-}
-
-static int gen_tbs_cert(const char * dn[],
- const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset,
- uint8_t *sha_dgst)
-{
- int ret = X509_OK;
- SHA1_CTX sha_ctx;
- int seq_offset;
- int begin_tbs = *offset;
- int seq_size = pre_adjust_with_size(
- ASN1_SEQUENCE, &seq_offset, buf, offset);
-
- gen_serial_number(buf, offset);
- gen_signature_alg(buf, offset);
-
- /* CA certicate issuer */
- if ((ret = gen_issuer(dn, buf, offset)))
- goto error;
-
- gen_utc_time(buf, offset);
-
- /* certificate issuer */
- if ((ret = gen_issuer(dn, buf, offset)))
- goto error;
-
- gen_pub_key(rsa_ctx, buf, offset);
- adjust_with_size(seq_size, seq_offset, buf, offset);
-
- SHA1_Init(&sha_ctx);
- SHA1_Update(&sha_ctx, &buf[begin_tbs], *offset-begin_tbs);
- SHA1_Final(sha_dgst, &sha_ctx);
-
-error:
- return ret;
-}
-
-/**
- * Create a new certificate.
- */
-EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const char * dn[], uint8_t **cert_data)
-{
- int ret = X509_OK, offset = 0, seq_offset;
- /* allocate enough space to load a new certificate */
- uint8_t *buf = (uint8_t *)alloca(ssl_ctx->rsa_ctx->num_octets*2 + 512);
- uint8_t sha_dgst[SHA1_SIZE];
- int seq_size = pre_adjust_with_size(ASN1_SEQUENCE,
- &seq_offset, buf, &offset);
-
- if ((ret = gen_tbs_cert(dn, ssl_ctx->rsa_ctx, buf, &offset, sha_dgst)) < 0)
- goto error;
-
- gen_signature_alg(buf, &offset);
- gen_signature(ssl_ctx->rsa_ctx, sha_dgst, buf, &offset);
- adjust_with_size(seq_size, seq_offset, buf, &offset);
- *cert_data = (uint8_t *)malloc(offset); /* create the exact memory for it */
- memcpy(*cert_data, buf, offset);
-
-error:
- return ret < 0 ? ret : offset;
-}
-
-#endif
-
diff --git a/axTLS/src/ssl/loader.c b/axTLS/src/ssl/loader.c
deleted file mode 100644
index 90231f3..0000000
--- a/axTLS/src/ssl/loader.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Load certificates/keys into memory. These can be in many different formats.
- * PEM support and other formats can be processed here.
- *
- * The PEM private keys may be optionally encrypted with AES128 or AES256.
- * The encrypted PEM keys were generated with something like:
- *
- * openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include "os_port.h"
-#include "ssl.h"
-
-static int do_obj(SSL_CTX *ssl_ctx, int obj_type,
- SSLObjLoader *ssl_obj, const char *password);
-#ifdef CONFIG_SSL_HAS_PEM
-static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type,
- SSLObjLoader *ssl_obj, const char *password);
-#endif
-
-/*
- * Load a file into memory that is in binary DER (or ascii PEM) format.
- */
-EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type,
- const char *filename, const char *password)
-{
-#ifndef CONFIG_SSL_SKELETON_MODE
- static const char * const begin = "-----BEGIN";
- int ret = SSL_OK;
- SSLObjLoader *ssl_obj = NULL;
-
- if (filename == NULL)
- {
- ret = SSL_ERROR_INVALID_KEY;
- goto error;
- }
-
- ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
- ssl_obj->len = get_file(filename, &ssl_obj->buf);
- if (ssl_obj->len <= 0)
- {
- ret = SSL_ERROR_INVALID_KEY;
- goto error;
- }
-
- /* is the file a PEM file? */
- if (strstr((char *)ssl_obj->buf, begin) != NULL)
- {
-#ifdef CONFIG_SSL_HAS_PEM
- ret = ssl_obj_PEM_load(ssl_ctx, obj_type, ssl_obj, password);
-#else
- printf(unsupported_str);
- ret = SSL_ERROR_NOT_SUPPORTED;
-#endif
- }
- else
- ret = do_obj(ssl_ctx, obj_type, ssl_obj, password);
-
-error:
- ssl_obj_free(ssl_obj);
- return ret;
-#else
- printf(unsupported_str);
- return SSL_ERROR_NOT_SUPPORTED;
-#endif /* CONFIG_SSL_SKELETON_MODE */
-}
-
-/*
- * Transfer binary data into the object loader.
- */
-EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int mem_type,
- const uint8_t *data, int len, const char *password)
-{
- int ret;
- SSLObjLoader *ssl_obj;
-
- ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
- ssl_obj->buf = (uint8_t *)malloc(len);
- memcpy(ssl_obj->buf, data, len);
- ssl_obj->len = len;
- ret = do_obj(ssl_ctx, mem_type, ssl_obj, password);
- ssl_obj_free(ssl_obj);
- return ret;
-}
-
-/*
- * Actually work out what we are doing
- */
-static int do_obj(SSL_CTX *ssl_ctx, int obj_type,
- SSLObjLoader *ssl_obj, const char *password)
-{
- int ret = SSL_OK;
-
- switch (obj_type)
- {
- case SSL_OBJ_RSA_KEY:
- ret = add_private_key(ssl_ctx, ssl_obj);
- break;
-
- case SSL_OBJ_X509_CERT:
- ret = add_cert(ssl_ctx, ssl_obj->buf, ssl_obj->len);
- break;
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- case SSL_OBJ_X509_CACERT:
- add_cert_auth(ssl_ctx, ssl_obj->buf, ssl_obj->len);
- break;
-#endif
-
-#ifdef CONFIG_SSL_USE_PKCS12
- case SSL_OBJ_PKCS8:
- ret = pkcs8_decode(ssl_ctx, ssl_obj, password);
- break;
-
- case SSL_OBJ_PKCS12:
- ret = pkcs12_decode(ssl_ctx, ssl_obj, password);
- break;
-#endif
- default:
- printf(unsupported_str);
- ret = SSL_ERROR_NOT_SUPPORTED;
- break;
- }
-
- return ret;
-}
-
-/*
- * Clean up our mess.
- */
-void ssl_obj_free(SSLObjLoader *ssl_obj)
-{
- if (ssl_obj)
- {
- free(ssl_obj->buf);
- free(ssl_obj);
- }
-}
-
-/*
- * Support for PEM encoded keys/certificates.
- */
-#ifdef CONFIG_SSL_HAS_PEM
-
-#define NUM_PEM_TYPES 4
-#define IV_SIZE 16
-#define IS_RSA_PRIVATE_KEY 0
-#define IS_ENCRYPTED_PRIVATE_KEY 1
-#define IS_PRIVATE_KEY 2
-#define IS_CERTIFICATE 3
-
-static const char * const begins[NUM_PEM_TYPES] =
-{
- "-----BEGIN RSA PRIVATE KEY-----",
- "-----BEGIN ENCRYPTED PRIVATE KEY-----",
- "-----BEGIN PRIVATE KEY-----",
- "-----BEGIN CERTIFICATE-----",
-};
-
-static const char * const ends[NUM_PEM_TYPES] =
-{
- "-----END RSA PRIVATE KEY-----",
- "-----END ENCRYPTED PRIVATE KEY-----",
- "-----END PRIVATE KEY-----",
- "-----END CERTIFICATE-----",
-};
-
-static const char * const aes_str[2] =
-{
- "DEK-Info: AES-128-CBC,",
- "DEK-Info: AES-256-CBC,"
-};
-
-/**
- * Take a base64 blob of data and decrypt it (using AES) into its
- * proper ASN.1 form.
- */
-static int pem_decrypt(const char *where, const char *end,
- const char *password, SSLObjLoader *ssl_obj)
-{
- int ret = -1;
- int is_aes_256 = 0;
- char *start = NULL;
- uint8_t iv[IV_SIZE];
- int i, pem_size;
- MD5_CTX md5_ctx;
- AES_CTX aes_ctx;
- uint8_t key[32]; /* AES256 size */
-
- if (password == NULL || strlen(password) == 0)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: Need a password for this PEM file\n"); TTY_FLUSH();
-#endif
- goto error;
- }
-
- if ((start = strstr((const char *)where, aes_str[0]))) /* AES128? */
- {
- start += strlen(aes_str[0]);
- }
- else if ((start = strstr((const char *)where, aes_str[1]))) /* AES256? */
- {
- is_aes_256 = 1;
- start += strlen(aes_str[1]);
- }
- else
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: Unsupported password cipher\n"); TTY_FLUSH();
-#endif
- goto error;
- }
-
- /* convert from hex to binary - assumes uppercase hex */
- for (i = 0; i < IV_SIZE; i++)
- {
- char c = *start++ - '0';
- iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4;
- c = *start++ - '0';
- iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c);
- }
-
- while (*start == '\r' || *start == '\n')
- start++;
-
- /* turn base64 into binary */
- pem_size = (int)(end-start);
- if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0)
- goto error;
-
- /* work out the key */
- MD5_Init(&md5_ctx);
- MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
- MD5_Update(&md5_ctx, iv, SALT_SIZE);
- MD5_Final(key, &md5_ctx);
-
- if (is_aes_256)
- {
- MD5_Init(&md5_ctx);
- MD5_Update(&md5_ctx, key, MD5_SIZE);
- MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
- MD5_Update(&md5_ctx, iv, SALT_SIZE);
- MD5_Final(&key[MD5_SIZE], &md5_ctx);
- }
-
- /* decrypt using the key/iv */
- AES_set_key(&aes_ctx, key, iv, is_aes_256 ? AES_MODE_256 : AES_MODE_128);
- AES_convert_key(&aes_ctx);
- AES_cbc_decrypt(&aes_ctx, ssl_obj->buf, ssl_obj->buf, ssl_obj->len);
- ret = 0;
-
-error:
- return ret;
-}
-
-/**
- * Take a base64 blob of data and turn it into its proper ASN.1 form.
- */
-static int new_pem_obj(SSL_CTX *ssl_ctx, int is_cacert, char *where,
- int remain, const char *password)
-{
- int ret = SSL_ERROR_BAD_CERTIFICATE;
- SSLObjLoader *ssl_obj = NULL;
-
- while (remain > 0)
- {
- int i, pem_size, obj_type;
- char *start = NULL, *end = NULL;
-
- for (i = 0; i < NUM_PEM_TYPES; i++)
- {
- if ((start = strstr(where, begins[i])) &&
- (end = strstr(where, ends[i])))
- {
- remain -= (int)(end-where);
- start += strlen(begins[i]);
- pem_size = (int)(end-start);
-
- ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
-
- /* 4/3 bigger than what we need but so what */
- ssl_obj->buf = (uint8_t *)calloc(1, pem_size);
-
- if (i == IS_RSA_PRIVATE_KEY &&
- strstr(start, "Proc-Type:") &&
- strstr(start, "4,ENCRYPTED"))
- {
- /* check for encrypted PEM file */
- if (pem_decrypt(start, end, password, ssl_obj) < 0)
- {
- ret = SSL_ERROR_BAD_CERTIFICATE;
- goto error;
- }
- }
- else if (base64_decode(start, pem_size,
- ssl_obj->buf, &ssl_obj->len) != 0)
- {
- ret = SSL_ERROR_BAD_CERTIFICATE;
- goto error;
- }
-
- switch (i)
- {
- case IS_RSA_PRIVATE_KEY:
- obj_type = SSL_OBJ_RSA_KEY;
- break;
-
- case IS_ENCRYPTED_PRIVATE_KEY:
- case IS_PRIVATE_KEY:
- obj_type = SSL_OBJ_PKCS8;
- break;
-
- case IS_CERTIFICATE:
- obj_type = is_cacert ?
- SSL_OBJ_X509_CACERT : SSL_OBJ_X509_CERT;
- break;
-
- default:
- ret = SSL_ERROR_BAD_CERTIFICATE;
- goto error;
- }
-
- /* In a format we can now understand - so process it */
- if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password)))
- goto error;
-
- end += strlen(ends[i]);
- remain -= strlen(ends[i]);
- while (remain > 0 && (*end == '\r' || *end == '\n'))
- {
- end++;
- remain--;
- }
-
- where = end;
- break;
- }
- }
-
- ssl_obj_free(ssl_obj);
- ssl_obj = NULL;
- if (start == NULL)
- break;
- }
-error:
- ssl_obj_free(ssl_obj);
- return ret;
-}
-
-/*
- * Load a file into memory that is in ASCII PEM format.
- */
-static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type,
- SSLObjLoader *ssl_obj, const char *password)
-{
- char *start;
-
- /* add a null terminator */
- ssl_obj->len++;
- ssl_obj->buf = (uint8_t *)realloc(ssl_obj->buf, ssl_obj->len);
- ssl_obj->buf[ssl_obj->len-1] = 0;
- start = (char *)ssl_obj->buf;
- return new_pem_obj(ssl_ctx, obj_type == SSL_OBJ_X509_CACERT,
- start, ssl_obj->len, password);
-}
-#endif /* CONFIG_SSL_HAS_PEM */
-
-/**
- * Load the key/certificates in memory depending on compile-time and user
- * options.
- */
-int load_key_certs(SSL_CTX *ssl_ctx)
-{
- int ret = SSL_OK;
- uint32_t options = ssl_ctx->options;
-#ifdef CONFIG_SSL_GENERATE_X509_CERT
- uint8_t *cert_data = NULL;
- int cert_size;
- static const char *dn[] =
- {
- CONFIG_SSL_X509_COMMON_NAME,
- CONFIG_SSL_X509_ORGANIZATION_NAME,
- CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME
- };
-#endif
-
- /* do the private key first */
- if (strlen(CONFIG_SSL_PRIVATE_KEY_LOCATION) > 0)
- {
- if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY,
- CONFIG_SSL_PRIVATE_KEY_LOCATION,
- CONFIG_SSL_PRIVATE_KEY_PASSWORD)) < 0)
- goto error;
- }
- else if (!(options & SSL_NO_DEFAULT_KEY))
- {
-#if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
- static const /* saves a few more bytes */
-#include "private_key.h"
-
- ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key,
- default_private_key_len, NULL);
-#endif
- }
-
- /* now load the certificate */
-#ifdef CONFIG_SSL_GENERATE_X509_CERT
- if ((cert_size = ssl_x509_create(ssl_ctx, 0, dn, &cert_data)) < 0)
- {
- ret = cert_size;
- goto error;
- }
-
- ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, cert_data, cert_size, NULL);
- free(cert_data);
-#else
- if (strlen(CONFIG_SSL_X509_CERT_LOCATION))
- {
- if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT,
- CONFIG_SSL_X509_CERT_LOCATION, NULL)) < 0)
- goto error;
- }
- else if (!(options & SSL_NO_DEFAULT_KEY))
- {
-#if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
- static const /* saves a few bytes and RAM */
-#include "cert.h"
- ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT,
- default_certificate, default_certificate_len, NULL);
-#endif
- }
-#endif
-
-error:
-#ifdef CONFIG_SSL_FULL_MODE
- if (ret)
- {
- printf("Error: Certificate or key not loaded\n"); TTY_FLUSH();
- }
-#endif
-
- return ret;
-
-}
diff --git a/axTLS/src/ssl/openssl.c b/axTLS/src/ssl/openssl.c
deleted file mode 100644
index 6b5c4d8..0000000
--- a/axTLS/src/ssl/openssl.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Enable a subset of openssl compatible functions. We don't aim to be 100%
- * compatible - just to be able to do basic ports etc.
- *
- * Only really tested on mini_httpd, so I'm not too sure how extensive this
- * port is.
- */
-
-#include "config.h"
-
-#ifdef CONFIG_OPENSSL_COMPATIBLE
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include "os_port.h"
-#include "ssl.h"
-
-#define OPENSSL_CTX_ATTR ((OPENSSL_CTX *)ssl_ctx->bonus_attr)
-
-static char *key_password = NULL;
-
-void *SSLv23_server_method(void) { return NULL; }
-void *SSLv3_server_method(void) { return NULL; }
-void *TLSv1_server_method(void) { return NULL; }
-void *SSLv23_client_method(void) { return NULL; }
-void *SSLv3_client_method(void) { return NULL; }
-void *TLSv1_client_method(void) { return NULL; }
-
-typedef void * (*ssl_func_type_t)(void);
-typedef void * (*bio_func_type_t)(void);
-
-typedef struct
-{
- ssl_func_type_t ssl_func_type;
-} OPENSSL_CTX;
-
-SSL_CTX * SSL_CTX_new(ssl_func_type_t meth)
-{
- SSL_CTX *ssl_ctx = ssl_ctx_new(0, 5);
- ssl_ctx->bonus_attr = malloc(sizeof(OPENSSL_CTX));
- OPENSSL_CTX_ATTR->ssl_func_type = meth;
- return ssl_ctx;
-}
-
-void SSL_CTX_free(SSL_CTX * ssl_ctx)
-{
- free(ssl_ctx->bonus_attr);
- ssl_ctx_free(ssl_ctx);
-}
-
-SSL * SSL_new(SSL_CTX *ssl_ctx)
-{
- SSL *ssl;
- ssl_func_type_t ssl_func_type;
-
- ssl = ssl_new(ssl_ctx, -1); /* fd is set later */
- ssl_func_type = OPENSSL_CTX_ATTR->ssl_func_type;
-
-#ifdef CONFIG_SSL_ENABLE_CLIENT
- if (ssl_func_type == SSLv23_client_method ||
- ssl_func_type == SSLv3_client_method ||
- ssl_func_type == TLSv1_client_method)
- {
- SET_SSL_FLAG(SSL_IS_CLIENT);
- }
- else
-#endif
- {
- ssl->next_state = HS_CLIENT_HELLO;
- }
-
- return ssl;
-}
-
-int SSL_set_fd(SSL *s, int fd)
-{
- s->client_fd = fd;
- return 1; /* always succeeds */
-}
-
-int SSL_accept(SSL *ssl)
-{
- while (ssl_read(ssl, NULL) == SSL_OK)
- {
- if (ssl->next_state == HS_CLIENT_HELLO)
- return 1; /* we're done */
- }
-
- return -1;
-}
-
-#ifdef CONFIG_SSL_ENABLE_CLIENT
-int SSL_connect(SSL *ssl)
-{
- return do_client_connect(ssl) == SSL_OK ? 1 : -1;
-}
-#endif
-
-void SSL_free(SSL *ssl)
-{
- ssl_free(ssl);
-}
-
-int SSL_read(SSL *ssl, void *buf, int num)
-{
- uint8_t *read_buf;
- int ret;
-
- while ((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
-
- if (ret > SSL_OK)
- {
- memcpy(buf, read_buf, ret > num ? num : ret);
- }
-
- return ret;
-}
-
-int SSL_write(SSL *ssl, const void *buf, int num)
-{
- return ssl_write(ssl, buf, num);
-}
-
-int SSL_CTX_use_certificate_file(SSL_CTX *ssl_ctx, const char *file, int type)
-{
- return (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, file, NULL) == SSL_OK);
-}
-
-int SSL_CTX_use_PrivateKey_file(SSL_CTX *ssl_ctx, const char *file, int type)
-{
- return (ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY, file, key_password) == SSL_OK);
-}
-
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *ssl_ctx, int len, const uint8_t *d)
-{
- return (ssl_obj_memory_load(ssl_ctx,
- SSL_OBJ_X509_CERT, d, len, NULL) == SSL_OK);
-}
-
-int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx,
- unsigned int sid_ctx_len)
-{
- return 1;
-}
-
-int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
-{
- return 1;
-}
-
-int SSL_CTX_use_certificate_chain_file(SSL_CTX *ssl_ctx, const char *file)
-{
- return (ssl_obj_load(ssl_ctx,
- SSL_OBJ_X509_CERT, file, NULL) == SSL_OK);
-}
-
-int SSL_shutdown(SSL *ssl)
-{
- return 1;
-}
-
-/*** get/set session ***/
-SSL_SESSION *SSL_get1_session(SSL *ssl)
-{
- return (SSL_SESSION *)ssl_get_session_id(ssl); /* note: wrong cast */
-}
-
-int SSL_set_session(SSL *ssl, SSL_SESSION *session)
-{
- memcpy(ssl->session_id, (uint8_t *)session, SSL_SESSION_ID_SIZE);
- return 1;
-}
-
-void SSL_SESSION_free(SSL_SESSION *session) { }
-/*** end get/set session ***/
-
-long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
-{
- return 0;
-}
-
-void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
- int (*verify_callback)(int, void *)) { }
-
-void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) { }
-
-int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
- const char *CApath)
-{
- return 1;
-}
-
-void *SSL_load_client_CA_file(const char *file)
-{
- return (void *)file;
-}
-
-void SSL_CTX_set_client_CA_list(SSL_CTX *ssl_ctx, void *file)
-{
-
- ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, (const char *)file, NULL);
-}
-
-void SSLv23_method(void) { }
-
-void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, void *cb) { }
-
-void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u)
-{
- key_password = (char *)u;
-}
-
-int SSL_peek(SSL *ssl, void *buf, int num)
-{
- memcpy(buf, ssl->bm_data, num);
- return num;
-}
-
-void SSL_set_bio(SSL *ssl, void *rbio, void *wbio) { }
-
-long SSL_get_verify_result(const SSL *ssl)
-{
- return ssl_handshake_status(ssl);
-}
-
-int SSL_state(SSL *ssl)
-{
- return 0x03; // ok state
-}
-
-/** end of could do better list */
-
-void *SSL_get_peer_certificate(const SSL *ssl)
-{
- return &ssl->ssl_ctx->certs[0];
-}
-
-int SSL_clear(SSL *ssl)
-{
- return 1;
-}
-
-
-int SSL_CTX_check_private_key(const SSL_CTX *ctx)
-{
- return 1;
-}
-
-int SSL_CTX_set_cipher_list(SSL *s, const char *str)
-{
- return 1;
-}
-
-int SSL_get_error(const SSL *ssl, int ret)
-{
- ssl_display_error(ret);
- return 0; /* TODO: return proper return code */
-}
-
-void SSL_CTX_set_options(SSL_CTX *ssl_ctx, int option) {}
-int SSL_library_init(void ) { return 1; }
-void SSL_load_error_strings(void ) {}
-void ERR_print_errors_fp(FILE *fp) {}
-
-#ifndef CONFIG_SSL_SKELETON_MODE
-long SSL_CTX_get_timeout(const SSL_CTX *ssl_ctx) {
- return CONFIG_SSL_EXPIRY_TIME*3600; }
-long SSL_CTX_set_timeout(SSL_CTX *ssl_ctx, long t) {
- return SSL_CTX_get_timeout(ssl_ctx); }
-#endif
-void BIO_printf(FILE *f, const char *format, ...)
-{
- va_list(ap);
- va_start(ap, format);
- vfprintf(f, format, ap);
- va_end(ap);
-}
-
-void* BIO_s_null(void) { return NULL; }
-FILE *BIO_new(bio_func_type_t func)
-{
- if (func == BIO_s_null)
- return fopen("/dev/null", "r");
- else
- return NULL;
-}
-
-FILE *BIO_new_fp(FILE *stream, int close_flag) { return stream; }
-int BIO_free(FILE *a) { if (a != stdout && a != stderr) fclose(a); return 1; }
-
-
-
-#endif
diff --git a/axTLS/src/ssl/os_port.c b/axTLS/src/ssl/os_port.c
deleted file mode 100644
index 9859d08..0000000
--- a/axTLS/src/ssl/os_port.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file os_port.c
- *
- * OS specific functions.
- */
-#include <time.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stdarg.h>
-#include "os_port.h"
-
-#ifdef _MSC_VER
-/**
- * gettimeofday() not in Win32
- */
-EXP_FUNC void STDCALL gettimeofday(struct timeval* t, void* timezone)
-{
-#if defined(_WIN32_WCE)
- t->tv_sec = time(NULL);
- t->tv_usec = 0; /* 1sec precision only */
-#else
- struct _timeb timebuffer;
- _ftime(&timebuffer);
- t->tv_sec = (long)timebuffer.time;
- t->tv_usec = 1000 * timebuffer.millitm; /* 1ms precision */
-#endif
-}
-
-/**
- * strcasecmp() not in Win32
- */
-EXP_FUNC int STDCALL strcasecmp(const char *s1, const char *s2)
-{
- while (tolower(*s1) == tolower(*s2++))
- {
- if (*s1++ == '\0')
- {
- return 0;
- }
- }
-
- return *(unsigned char *)s1 - *(unsigned char *)(s2 - 1);
-}
-
-
-EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size)
-{
- HKEY hKey;
- unsigned long datatype;
- unsigned long bufferlength = buf_size;
-
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
- 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
- return -1;
-
- RegQueryValueEx(hKey, "Domain", NULL, &datatype, buf, &bufferlength);
- RegCloseKey(hKey);
- return 0;
-}
-#endif
-
-#undef malloc
-#undef realloc
-#undef calloc
-
-static const char * out_of_mem_str = "out of memory";
-static const char * file_open_str = "Could not open file \"%s\"";
-
-/*
- * Some functions that call display some error trace and then call abort().
- * This just makes life much easier on embedded systems, since we're
- * suffering major trauma...
- */
-EXP_FUNC void * STDCALL ax_malloc(size_t s)
-{
- void *x;
-
- if ((x = malloc(s)) == NULL)
- exit_now(out_of_mem_str);
-
- return x;
-}
-
-EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s)
-{
- void *x;
-
- if ((x = realloc(y, s)) == NULL)
- exit_now(out_of_mem_str);
-
- return x;
-}
-
-EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s)
-{
- void *x;
-
- if ((x = calloc(n, s)) == NULL)
- exit_now(out_of_mem_str);
-
- return x;
-}
-
-EXP_FUNC int STDCALL ax_open(const char *pathname, int flags)
-{
- int x;
-
- if ((x = open(pathname, flags)) < 0)
- exit_now(file_open_str, pathname);
-
- return x;
-}
-
-/**
- * This is a call which will deliberately exit an application, but will
- * display some information before dying.
- */
-void exit_now(const char *format, ...)
-{
- va_list argp;
-
- va_start(argp, format);
- vfprintf(stderr, format, argp);
- va_end(argp);
- abort();
-}
-
diff --git a/axTLS/src/ssl/os_port.h b/axTLS/src/ssl/os_port.h
deleted file mode 100644
index b2924b4..0000000
--- a/axTLS/src/ssl/os_port.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file os_port.h
- *
- * Some stuff to minimise the differences between windows and linux/unix
- */
-
-#ifndef HEADER_OS_PORT_H
-#define HEADER_OS_PORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdio.h>
-
-//#if defined(WIN32)
-//#define STDCALL __stdcall
-//#define EXP_FUNC __declspec(dllexport)
-//#else
-#define STDCALL
-#define EXP_FUNC
-//#endif
-
-#if defined(_WIN32_WCE)
-#undef WIN32
-#define WIN32
-#endif
-
-#ifdef WIN32
-
-/* Windows CE stuff */
-#if defined(_WIN32_WCE)
-#include <basetsd.h>
-#define abort() exit(1)
-#else
-#include <io.h>
-#include <process.h>
-#include <sys/timeb.h>
-#include <fcntl.h>
-#endif /* _WIN32_WCE */
-
-#include <winsock.h>
-#include <direct.h>
-#undef getpid
-#undef open
-#undef close
-#undef sleep
-#undef gettimeofday
-#undef dup2
-#undef unlink
-
-#define SOCKET_READ(A,B,C) recv(A,B,C,0)
-#define SOCKET_WRITE(A,B,C) send(A,B,C,0)
-#define SOCKET_CLOSE(A) closesocket(A)
-#define srandom(A) srand(A)
-#define random() rand()
-#define getpid() _getpid()
-#define snprintf _snprintf
-#define open(A,B) _open(A,B)
-#define dup2(A,B) _dup2(A,B)
-#define unlink(A) _unlink(A)
-#define close(A) _close(A)
-#define read(A,B,C) _read(A,B,C)
-#define write(A,B,C) _write(A,B,C)
-#define sleep(A) Sleep(A*1000)
-#define usleep(A) Sleep(A/1000)
-#define strdup(A) _strdup(A)
-#define chroot(A) _chdir(A)
-#define chdir(A) _chdir(A)
-#define alloca(A) _alloca(A)
-#ifndef lseek
-#define lseek(A,B,C) _lseek(A,B,C)
-#endif
-
-/* This fix gets around a problem where a win32 application on a cygwin xterm
- doesn't display regular output (until a certain buffer limit) - but it works
- fine under a normal DOS window. This is a hack to get around the issue -
- see http://www.khngai.com/emacs/tty.php */
-#define TTY_FLUSH() if (!_isatty(_fileno(stdout))) fflush(stdout);
-
-/*
- * automatically build some library dependencies.
- */
-#ifdef _MSC_VER
-#pragma comment(lib, "WS2_32.lib")
-#pragma comment(lib, "AdvAPI32.lib")
-
-typedef UINT8 uint8_t;
-typedef INT8 int8_t;
-typedef UINT16 uint16_t;
-typedef INT16 int16_t;
-typedef UINT32 uint32_t;
-typedef INT32 int32_t;
-typedef UINT64 uint64_t;
-typedef INT64 int64_t;
-typedef int socklen_t;
-
-EXP_FUNC void STDCALL gettimeofday(struct timeval* t,void* timezone);
-EXP_FUNC int STDCALL strcasecmp(const char *s1, const char *s2);
-EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size);
-#else
-#include <stdint.h>
-#endif
-
-#else /* Not Win32 */
-
-#ifdef CONFIG_PLATFORM_SOLARIS
-#include <inttypes.h>
-#else
-#include <stdint.h>
-#endif /* Not Solaris */
-
-#include <unistd.h>
-#include <pwd.h>
-#include <netdb.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#define SOCKET_READ(A,B,C) read(A,B,C)
-#define SOCKET_WRITE(A,B,C) write(A,B,C)
-#define SOCKET_CLOSE(A) if (A >= 0) close(A)
-#define TTY_FLUSH()
-
-#endif /* Not Win32 */
-
-/* some functions to mutate the way these work */
-#define malloc(A) ax_malloc(A)
-#ifndef realloc
-#define realloc(A,B) ax_realloc(A,B)
-#endif
-#define calloc(A,B) ax_calloc(A,B)
-
-EXP_FUNC void * STDCALL ax_malloc(size_t s);
-EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s);
-EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s);
-EXP_FUNC int STDCALL ax_open(const char *pathname, int flags);
-
-#ifdef CONFIG_PLATFORM_LINUX
-void exit_now(const char *format, ...) __attribute((noreturn));
-#else
-void exit_now(const char *format, ...);
-#endif
-
-/* Mutexing definitions */
-#if defined(CONFIG_SSL_CTX_MUTEXING)
-#if defined(WIN32)
-#define SSL_CTX_MUTEX_TYPE HANDLE
-#define SSL_CTX_MUTEX_INIT(A) A=CreateMutex(0, FALSE, 0)
-#define SSL_CTX_MUTEX_DESTROY(A) CloseHandle(A)
-#define SSL_CTX_LOCK(A) WaitForSingleObject(A, INFINITE)
-#define SSL_CTX_UNLOCK(A) ReleaseMutex(A)
-#else
-#include <pthread.h>
-#define SSL_CTX_MUTEX_TYPE pthread_mutex_t
-#define SSL_CTX_MUTEX_INIT(A) pthread_mutex_init(&A, NULL)
-#define SSL_CTX_MUTEX_DESTROY(A) pthread_mutex_destroy(&A)
-#define SSL_CTX_LOCK(A) pthread_mutex_lock(&A)
-#define SSL_CTX_UNLOCK(A) pthread_mutex_unlock(&A)
-#endif
-#else /* no mutexing */
-#define SSL_CTX_MUTEX_INIT(A)
-#define SSL_CTX_MUTEX_DESTROY(A)
-#define SSL_CTX_LOCK(A)
-#define SSL_CTX_UNLOCK(A)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/axTLS/src/ssl/p12.c b/axTLS/src/ssl/p12.c
deleted file mode 100644
index 2bafaf7..0000000
--- a/axTLS/src/ssl/p12.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Process PKCS#8/PKCS#12 keys.
- *
- * The decoding of a PKCS#12 key is fairly specific - this code was tested on a
- * key generated with:
- *
- * openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem
- * -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128
- * -name "p12_withoutCA" -out axTLS.withoutCA.p12 -password pass:abcd
- *
- * or with a certificate chain:
- *
- * openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem
- * -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe
- * PBE-SHA1-RC4-128 -name "p12_withCA" -out axTLS.withCA.p12 -password pass:abcd
- *
- * Note that the PBE has to be specified with PBE-SHA1-RC4-128. The
- * private/public keys/certs have to use RSA encryption. Both the integrity
- * and privacy passwords are the same.
- *
- * The PKCS#8 files were generated with something like:
- *
- * PEM format:
- * openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1
- * PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8
- *
- * DER format:
- * openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER
- * -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include "os_port.h"
-#include "ssl.h"
-
-/* all commented out if not used */
-#ifdef CONFIG_SSL_USE_PKCS12
-
-#define BLOCK_SIZE 64
-#define PKCS12_KEY_ID 1
-#define PKCS12_IV_ID 2
-#define PKCS12_MAC_ID 3
-
-static char *make_uni_pass(const char *password, int *uni_pass_len);
-static int p8_decrypt(const char *uni_pass, int uni_pass_len,
- const uint8_t *salt, int iter,
- uint8_t *priv_key, int priv_key_len, int id);
-static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key);
-static int get_pbe_params(uint8_t *buf, int *offset,
- const uint8_t **salt, int *iterations);
-
-/*
- * Take a raw pkcs8 block and then decrypt it and turn it into a normal key.
- */
-int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
-{
- uint8_t *buf = ssl_obj->buf;
- int len, offset = 0;
- int iterations;
- int ret = SSL_NOT_OK;
- uint8_t *version = NULL;
- const uint8_t *salt;
- uint8_t *priv_key;
- int uni_pass_len;
- char *uni_pass = make_uni_pass(password, &uni_pass_len);
-
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: Invalid p8 ASN.1 file\n");
-#endif
- goto error;
- }
-
- /* unencrypted key? */
- if (asn1_get_int(buf, &offset, &version) > 0 && *version == 0)
- {
- ret = p8_add_key(ssl_ctx, buf);
- goto error;
- }
-
- if (get_pbe_params(buf, &offset, &salt, &iterations) < 0)
- goto error;
-
- if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
- goto error;
-
- priv_key = &buf[offset];
-
- p8_decrypt(uni_pass, uni_pass_len, salt,
- iterations, priv_key, len, PKCS12_KEY_ID);
- ret = p8_add_key(ssl_ctx, priv_key);
-
-error:
- free(version);
- free(uni_pass);
- return ret;
-}
-
-/*
- * Take the unencrypted pkcs8 and turn it into a private key
- */
-static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key)
-{
- uint8_t *buf = priv_key;
- int len, offset = 0;
- int ret = SSL_NOT_OK;
-
- /* Skip the preamble and go straight to the private key.
- We only support rsaEncryption (1.2.840.113549.1.1.1) */
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
- asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
- goto error;
-
- ret = asn1_get_private_key(&buf[offset], len, &ssl_ctx->rsa_ctx);
-
-error:
- return ret;
-}
-
-/*
- * Create the unicode password
- */
-static char *make_uni_pass(const char *password, int *uni_pass_len)
-{
- int pass_len = 0, i;
- char *uni_pass;
-
- if (password == NULL)
- {
- password = "";
- }
-
- uni_pass = (char *)malloc((strlen(password)+1)*2);
-
- /* modify the password into a unicode version */
- for (i = 0; i < (int)strlen(password); i++)
- {
- uni_pass[pass_len++] = 0;
- uni_pass[pass_len++] = password[i];
- }
-
- uni_pass[pass_len++] = 0; /* null terminate */
- uni_pass[pass_len++] = 0;
- *uni_pass_len = pass_len;
- return uni_pass;
-}
-
-/*
- * Decrypt a pkcs8 block.
- */
-static int p8_decrypt(const char *uni_pass, int uni_pass_len,
- const uint8_t *salt, int iter,
- uint8_t *priv_key, int priv_key_len, int id)
-{
- uint8_t p[BLOCK_SIZE*2];
- uint8_t d[BLOCK_SIZE];
- uint8_t Ai[SHA1_SIZE];
- SHA1_CTX sha_ctx;
- RC4_CTX rc4_ctx;
- int i;
-
- for (i = 0; i < BLOCK_SIZE; i++)
- {
- p[i] = salt[i % SALT_SIZE];
- p[BLOCK_SIZE+i] = uni_pass[i % uni_pass_len];
- d[i] = id;
- }
-
- /* get the key - no IV since we are using RC4 */
- SHA1_Init(&sha_ctx);
- SHA1_Update(&sha_ctx, d, sizeof(d));
- SHA1_Update(&sha_ctx, p, sizeof(p));
- SHA1_Final(Ai, &sha_ctx);
-
- for (i = 1; i < iter; i++)
- {
- SHA1_Init(&sha_ctx);
- SHA1_Update(&sha_ctx, Ai, SHA1_SIZE);
- SHA1_Final(Ai, &sha_ctx);
- }
-
- /* do the decryption */
- if (id == PKCS12_KEY_ID)
- {
- RC4_setup(&rc4_ctx, Ai, 16);
- RC4_crypt(&rc4_ctx, priv_key, priv_key, priv_key_len);
- }
- else /* MAC */
- memcpy(priv_key, Ai, SHA1_SIZE);
-
- return 0;
-}
-
-/*
- * Take a raw pkcs12 block and the decrypt it and turn it into a certificate(s)
- * and keys.
- */
-int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
-{
- uint8_t *buf = ssl_obj->buf;
- int len, iterations, auth_safes_start,
- auth_safes_end, auth_safes_len, key_offset, offset = 0;
- int all_certs = 0;
- uint8_t *version = NULL, *auth_safes = NULL, *cert, *orig_mac;
- uint8_t key[SHA1_SIZE];
- uint8_t mac[SHA1_SIZE];
- const uint8_t *salt;
- int uni_pass_len, ret = SSL_OK;
- char *uni_pass = make_uni_pass(password, &uni_pass_len);
- static const uint8_t pkcs_data[] = /* pkc7 data */
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 };
- static const uint8_t pkcs_encrypted[] = /* pkc7 encrypted */
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06 };
- static const uint8_t pkcs8_key_bag[] = /* 1.2.840.113549.1.12.10.1.2 */
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02 };
-
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: Invalid p12 ASN.1 file\n");
-#endif
- goto error;
- }
-
- if (asn1_get_int(buf, &offset, &version) < 0 || *version != 3)
- {
- ret = SSL_ERROR_INVALID_VERSION;
- goto error;
- }
-
- /* remove all the boring pcks7 bits */
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- len != sizeof(pkcs_data) ||
- memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
- goto error;
-
- offset += len;
-
- if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0)
- goto error;
-
- /* work out the MAC start/end points (done on AuthSafes) */
- auth_safes_start = offset;
- auth_safes_end = offset;
- if (asn1_skip_obj(buf, &auth_safes_end, ASN1_SEQUENCE) < 0)
- goto error;
-
- auth_safes_len = auth_safes_end - auth_safes_start;
- auth_safes = malloc(auth_safes_len);
-
- memcpy(auth_safes, &buf[auth_safes_start], auth_safes_len);
-
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- (len != sizeof(pkcs_encrypted) ||
- memcmp(&buf[offset], pkcs_encrypted, sizeof(pkcs_encrypted))))
- goto error;
-
- offset += len;
-
- if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- len != sizeof(pkcs_data) ||
- memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
- goto error;
-
- offset += len;
-
- /* work out the salt for the certificate */
- if (get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_IMPLICIT_TAG)) < 0)
- goto error;
-
- /* decrypt the certificate */
- cert = &buf[offset];
- if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
- len, PKCS12_KEY_ID)) < 0)
- goto error;
-
- offset += len;
-
- /* load the certificate */
- key_offset = 0;
- all_certs = asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE);
-
- /* keep going until all certs are loaded */
- while (key_offset < all_certs)
- {
- int cert_offset = key_offset;
-
- if (asn1_skip_obj(cert, &cert_offset, ASN1_SEQUENCE) < 0 ||
- asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
- asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
- asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
- (len = asn1_next_obj(cert, &key_offset, ASN1_OCTET_STRING)) < 0)
- goto error;
-
- if ((ret = add_cert(ssl_ctx, &cert[key_offset], len)) < 0)
- goto error;
-
- key_offset = cert_offset;
- }
-
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- len != sizeof(pkcs_data) ||
- memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
- goto error;
-
- offset += len;
-
- if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- (len != sizeof(pkcs8_key_bag)) ||
- memcmp(&buf[offset], pkcs8_key_bag, sizeof(pkcs8_key_bag)))
- goto error;
-
- offset += len;
-
- /* work out the salt for the private key */
- if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
- goto error;
-
- /* decrypt the private key */
- cert = &buf[offset];
- if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
- len, PKCS12_KEY_ID)) < 0)
- goto error;
-
- offset += len;
-
- /* load the private key */
- if ((ret = p8_add_key(ssl_ctx, cert)) < 0)
- goto error;
-
- /* miss out on friendly name, local key id etc */
- if (asn1_skip_obj(buf, &offset, ASN1_SET) < 0)
- goto error;
-
- /* work out the MAC */
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 ||
- len != SHA1_SIZE)
- goto error;
-
- orig_mac = &buf[offset];
- offset += len;
-
- /* get the salt */
- if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || len != 8)
- goto error;
-
- salt = &buf[offset];
-
- /* work out what the mac should be */
- if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations,
- key, SHA1_SIZE, PKCS12_MAC_ID)) < 0)
- goto error;
-
- hmac_sha1(auth_safes, auth_safes_len, key, SHA1_SIZE, mac);
-
- if (memcmp(mac, orig_mac, SHA1_SIZE))
- {
- ret = SSL_ERROR_INVALID_HMAC;
- goto error;
- }
-
-error:
- free(version);
- free(uni_pass);
- free(auth_safes);
- return ret;
-}
-
-/*
- * Retrieve the salt/iteration details from a PBE block.
- */
-static int get_pbe_params(uint8_t *buf, int *offset,
- const uint8_t **salt, int *iterations)
-{
- static const uint8_t pbeSH1RC4[] = /* pbeWithSHAAnd128BitRC4 */
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x01 };
-
- int i, len;
- uint8_t *iter = NULL;
- int error_code = SSL_ERROR_NOT_SUPPORTED;
-
- /* Get the PBE type */
- if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
- goto error;
-
- /* we expect pbeWithSHAAnd128BitRC4 (1.2.840.113549.1.12.1.1)
- which is the only algorithm we support */
- if (len != sizeof(pbeSH1RC4) ||
- memcmp(&buf[*offset], pbeSH1RC4, sizeof(pbeSH1RC4)))
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: pkcs8/pkcs12 must use \"PBE-SHA1-RC4-128\"\n");
-#endif
- goto error;
- }
-
- *offset += len;
-
- if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, offset, ASN1_OCTET_STRING)) < 0 ||
- len != 8)
- goto error;
-
- *salt = &buf[*offset];
- *offset += len;
-
- if ((len = asn1_get_int(buf, offset, &iter)) < 0)
- goto error;
-
- *iterations = 0;
- for (i = 0; i < len; i++)
- {
- (*iterations) <<= 8;
- (*iterations) += iter[i];
- }
-
- free(iter);
- error_code = SSL_OK; /* got here - we are ok */
-
-error:
- return error_code;
-}
-
-#endif
diff --git a/axTLS/src/ssl/private_key.h b/axTLS/src/ssl/private_key.h
deleted file mode 100644
index ce7985c..0000000
--- a/axTLS/src/ssl/private_key.h
+++ /dev/null
@@ -1,54 +0,0 @@
-unsigned char default_private_key[] = {
- 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xcd,
- 0xfd, 0x89, 0x48, 0xbe, 0x36, 0xb9, 0x95, 0x76, 0xd4, 0x13, 0x30, 0x0e,
- 0xbf, 0xb2, 0xed, 0x67, 0x0a, 0xc0, 0x16, 0x3f, 0x51, 0x09, 0x9d, 0x29,
- 0x2f, 0xb2, 0x6d, 0x3f, 0x3e, 0x6c, 0x2f, 0x90, 0x80, 0xa1, 0x71, 0xdf,
- 0xbe, 0x38, 0xc5, 0xcb, 0xa9, 0x9a, 0x40, 0x14, 0x90, 0x0a, 0xf9, 0xb7,
- 0x07, 0x0b, 0xe1, 0xda, 0xe7, 0x09, 0xbf, 0x0d, 0x57, 0x41, 0x86, 0x60,
- 0xa1, 0xc1, 0x27, 0x91, 0x5b, 0x0a, 0x98, 0x46, 0x1b, 0xf6, 0xa2, 0x84,
- 0xf8, 0x65, 0xc7, 0xce, 0x2d, 0x96, 0x17, 0xaa, 0x91, 0xf8, 0x61, 0x04,
- 0x50, 0x70, 0xeb, 0xb4, 0x43, 0xb7, 0xdc, 0x9a, 0xcc, 0x31, 0x01, 0x14,
- 0xd4, 0xcd, 0xcc, 0xc2, 0x37, 0x6d, 0x69, 0x82, 0xd6, 0xc6, 0xc4, 0xbe,
- 0xf2, 0x34, 0xa5, 0xc9, 0xa6, 0x19, 0x53, 0x32, 0x7a, 0x86, 0x0e, 0x91,
- 0x82, 0x0f, 0xa1, 0x42, 0x54, 0xaa, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01,
- 0x02, 0x81, 0x81, 0x00, 0x95, 0xaa, 0x6e, 0x11, 0xf5, 0x6a, 0x8b, 0xa2,
- 0xc6, 0x48, 0xc6, 0x7c, 0x37, 0x6b, 0x1f, 0x55, 0x10, 0x76, 0x26, 0x24,
- 0xc3, 0xf2, 0x5c, 0x5a, 0xdd, 0x2e, 0xf3, 0xa4, 0x1e, 0xbc, 0x7b, 0x1c,
- 0x80, 0x10, 0x85, 0xbc, 0xd8, 0x45, 0x3c, 0xb8, 0xb2, 0x06, 0x53, 0xb5,
- 0xd5, 0x7a, 0xe7, 0x0e, 0x92, 0xe6, 0x42, 0xc2, 0xe2, 0x2a, 0xd5, 0xd1,
- 0x03, 0x9f, 0x6f, 0x53, 0x74, 0x68, 0x72, 0x8e, 0xbf, 0x03, 0xbb, 0xab,
- 0xbd, 0xa1, 0xf9, 0x81, 0x7d, 0x12, 0xd4, 0x9d, 0xb6, 0xae, 0x4c, 0xad,
- 0xca, 0xa8, 0xc9, 0x80, 0x8d, 0x0d, 0xd5, 0xd0, 0xa1, 0xbf, 0xec, 0x60,
- 0x48, 0x49, 0xed, 0x97, 0x0f, 0x5e, 0xed, 0xfc, 0x39, 0x15, 0x96, 0x9e,
- 0x5d, 0xe2, 0xb4, 0x5d, 0x2e, 0x04, 0xdc, 0x08, 0xa2, 0x65, 0x29, 0x2d,
- 0x37, 0xfb, 0x62, 0x90, 0x1b, 0x7b, 0xe5, 0x3a, 0x58, 0x05, 0x55, 0xc1,
- 0x02, 0x41, 0x00, 0xfc, 0x69, 0x28, 0xc9, 0xa8, 0xc4, 0x5c, 0xe3, 0xd0,
- 0x5e, 0xaa, 0xda, 0xde, 0x87, 0x74, 0xdb, 0xcb, 0x40, 0x78, 0x8e, 0x1d,
- 0x12, 0x96, 0x16, 0x61, 0x3f, 0xb3, 0x3e, 0xa3, 0x0d, 0xdc, 0x49, 0xa5,
- 0x25, 0x87, 0xc5, 0x97, 0x85, 0x9d, 0xbb, 0xb4, 0xf0, 0x44, 0xfd, 0x6c,
- 0xe8, 0xd2, 0x8c, 0xec, 0x33, 0x81, 0x46, 0x1e, 0x10, 0x12, 0x33, 0x16,
- 0x95, 0x00, 0x4f, 0x75, 0xb4, 0xe5, 0x79, 0x02, 0x41, 0x00, 0xd0, 0xeb,
- 0x65, 0x07, 0x10, 0x3b, 0xd9, 0x03, 0xeb, 0xdc, 0x6f, 0x4b, 0x8f, 0xc3,
- 0x87, 0xce, 0x76, 0xd6, 0xc5, 0x14, 0x21, 0x4e, 0xe7, 0x4f, 0x1b, 0xe8,
- 0x05, 0xf8, 0x84, 0x1a, 0xe0, 0xc5, 0xd6, 0xe3, 0x08, 0xb3, 0x54, 0x57,
- 0x02, 0x1f, 0xd4, 0xd9, 0xfb, 0xff, 0x40, 0xb1, 0x56, 0x1c, 0x60, 0xf7,
- 0xac, 0x91, 0xf3, 0xd3, 0xc6, 0x7f, 0x84, 0xfd, 0x84, 0x9d, 0xea, 0x26,
- 0xee, 0xc9, 0x02, 0x41, 0x00, 0xa6, 0xcf, 0x1c, 0x6c, 0x81, 0x03, 0x1c,
- 0x5c, 0x56, 0x05, 0x6a, 0x26, 0x70, 0xef, 0xd6, 0x13, 0xb7, 0x74, 0x28,
- 0xf7, 0xca, 0x50, 0xd1, 0x2d, 0x83, 0x21, 0x64, 0xe4, 0xdd, 0x3f, 0x38,
- 0xb8, 0xd6, 0xd2, 0x41, 0xb3, 0x1c, 0x9a, 0xea, 0x0d, 0xf5, 0xda, 0xdf,
- 0xcd, 0x17, 0x9f, 0x9a, 0x1e, 0x15, 0xaf, 0x48, 0x1c, 0xbd, 0x9b, 0x63,
- 0x5b, 0xad, 0xed, 0xd4, 0xa1, 0xae, 0xa9, 0x59, 0x09, 0x02, 0x40, 0x4e,
- 0x08, 0xce, 0xa8, 0x8f, 0xc0, 0xba, 0xf3, 0x83, 0x02, 0xc8, 0x33, 0x62,
- 0x14, 0x77, 0xc2, 0x7f, 0x93, 0x02, 0xf3, 0xdc, 0xe9, 0x1a, 0xee, 0xea,
- 0x8e, 0x84, 0xc4, 0x69, 0x9b, 0x9c, 0x7f, 0x69, 0x1f, 0x4e, 0x1d, 0xa5,
- 0x90, 0x06, 0x44, 0x1b, 0x7d, 0xfc, 0x69, 0x40, 0x21, 0xbc, 0xf7, 0x46,
- 0xa4, 0xdc, 0x39, 0x7b, 0xe8, 0x8b, 0x49, 0x10, 0x44, 0x9d, 0x67, 0x5a,
- 0x91, 0x86, 0x39, 0x02, 0x40, 0x41, 0x2c, 0x4e, 0xfe, 0xd9, 0x90, 0x89,
- 0x00, 0x5c, 0x94, 0x0a, 0x4a, 0x7e, 0x1b, 0x1a, 0x80, 0x06, 0x01, 0x37,
- 0xda, 0x50, 0x61, 0x9d, 0x9c, 0xfe, 0x25, 0x7f, 0xd8, 0xd4, 0xc4, 0x9e,
- 0x81, 0xf2, 0x0c, 0x1e, 0x38, 0x21, 0x1e, 0x90, 0x3f, 0xd4, 0xba, 0x6c,
- 0x53, 0xcb, 0xf0, 0x77, 0x79, 0x9b, 0xf1, 0xfa, 0x3f, 0x81, 0xdc, 0xf3,
- 0x21, 0x02, 0x6d, 0xb7, 0x95, 0xc3, 0x2e, 0xce, 0xd5
-};
-unsigned int default_private_key_len = 609;
diff --git a/axTLS/src/ssl/ssl.h b/axTLS/src/ssl/ssl.h
deleted file mode 100644
index 198efc6..0000000
--- a/axTLS/src/ssl/ssl.h
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @mainpage axTLS API
- *
- * @image html axolotl.jpg
- *
- * The axTLS library has features such as:
- * - The TLSv1 SSL client/server protocol
- * - No requirement to use any openssl libraries.
- * - A choice between AES block (128/256 bit) and RC4 (128 bit) stream ciphers.
- * - RSA encryption/decryption with variable sized keys (up to 4096 bits).
- * - Certificate chaining and peer authentication.
- * - Session resumption, session renegotiation.
- * - ASN.1, X.509, PKCS#8, PKCS#12 keys/certificates with DER/PEM encoding.
- * - Highly configurable compile time options.
- * - Portable across many platforms (written in ANSI C), and has language
- * bindings in C, C#, VB.NET, Java, Perl and Lua.
- * - Partial openssl API compatibility (via a wrapper).
- * - A very small footprint (around 50-60kB for the library in 'server-only'
- * mode).
- * - No dependencies on sockets - can use serial connections for example.
- * - A very simple API - ~ 20 functions/methods.
- *
- * A list of these functions/methods are described below.
- *
- * @ref c_api
- *
- * @ref bigint_api
- *
- * @ref csharp_api
- *
- * @ref java_api
- */
-#ifndef HEADER_SSL_H
-#define HEADER_SSL_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <time.h>
-
-/* need to predefine before ssl_lib.h gets to it */
-#define SSL_SESSION_ID_SIZE 32
-
-#include "tls1.h"
-
-/* The optional parameters that can be given to the client/server SSL engine */
-#define SSL_CLIENT_AUTHENTICATION 0x00010000
-#define SSL_SERVER_VERIFY_LATER 0x00020000
-#define SSL_NO_DEFAULT_KEY 0x00040000
-#define SSL_DISPLAY_STATES 0x00080000
-#define SSL_DISPLAY_BYTES 0x00100000
-#define SSL_DISPLAY_CERTS 0x00200000
-#define SSL_DISPLAY_RSA 0x00400000
-#define SSL_CONNECT_IN_PARTS 0x00800000
-
-/* errors that can be generated */
-#define SSL_OK 0
-#define SSL_NOT_OK -1
-#define SSL_ERROR_DEAD -2
-#define SSL_CLOSE_NOTIFY -3
-#define SSL_ERROR_CONN_LOST -256
-#define SSL_ERROR_SOCK_SETUP_FAILURE -258
-#define SSL_ERROR_INVALID_HANDSHAKE -260
-#define SSL_ERROR_INVALID_PROT_MSG -261
-#define SSL_ERROR_INVALID_HMAC -262
-#define SSL_ERROR_INVALID_VERSION -263
-#define SSL_ERROR_INVALID_SESSION -265
-#define SSL_ERROR_NO_CIPHER -266
-#define SSL_ERROR_BAD_CERTIFICATE -268
-#define SSL_ERROR_INVALID_KEY -269
-#define SSL_ERROR_FINISHED_INVALID -271
-#define SSL_ERROR_NO_CERT_DEFINED -272
-#define SSL_ERROR_NO_CLIENT_RENOG -273
-#define SSL_ERROR_NOT_SUPPORTED -274
-#define SSL_X509_OFFSET -512
-#define SSL_X509_ERROR(A) (SSL_X509_OFFSET+A)
-
-/* alert types that are recognized */
-#define SSL_ALERT_TYPE_WARNING 1
-#define SLL_ALERT_TYPE_FATAL 2
-
-/* these are all the alerts that are recognized */
-#define SSL_ALERT_CLOSE_NOTIFY 0
-#define SSL_ALERT_UNEXPECTED_MESSAGE 10
-#define SSL_ALERT_BAD_RECORD_MAC 20
-#define SSL_ALERT_HANDSHAKE_FAILURE 40
-#define SSL_ALERT_BAD_CERTIFICATE 42
-#define SSL_ALERT_ILLEGAL_PARAMETER 47
-#define SSL_ALERT_DECODE_ERROR 50
-#define SSL_ALERT_DECRYPT_ERROR 51
-#define SSL_ALERT_INVALID_VERSION 70
-#define SSL_ALERT_NO_RENEGOTIATION 100
-
-/* The ciphers that are supported */
-#define SSL_AES128_SHA 0x2f
-#define SSL_AES256_SHA 0x35
-#define SSL_RC4_128_SHA 0x05
-#define SSL_RC4_128_MD5 0x04
-
-/* build mode ids' */
-#define SSL_BUILD_SKELETON_MODE 0x01
-#define SSL_BUILD_SERVER_ONLY 0x02
-#define SSL_BUILD_ENABLE_VERIFICATION 0x03
-#define SSL_BUILD_ENABLE_CLIENT 0x04
-#define SSL_BUILD_FULL_MODE 0x05
-
-/* offsets to retrieve configuration information */
-#define SSL_BUILD_MODE 0
-#define SSL_MAX_CERT_CFG_OFFSET 1
-#define SSL_MAX_CA_CERT_CFG_OFFSET 2
-#define SSL_HAS_PEM 3
-
-/* default session sizes */
-#define SSL_DEFAULT_SVR_SESS 5
-#define SSL_DEFAULT_CLNT_SESS 1
-
-/* X.509/X.520 distinguished name types */
-#define SSL_X509_CERT_COMMON_NAME 0
-#define SSL_X509_CERT_ORGANIZATION 1
-#define SSL_X509_CERT_ORGANIZATIONAL_NAME 2
-#define SSL_X509_CA_CERT_COMMON_NAME 3
-#define SSL_X509_CA_CERT_ORGANIZATION 4
-#define SSL_X509_CA_CERT_ORGANIZATIONAL_NAME 5
-
-/* SSL object loader types */
-#define SSL_OBJ_X509_CERT 1
-#define SSL_OBJ_X509_CACERT 2
-#define SSL_OBJ_RSA_KEY 3
-#define SSL_OBJ_PKCS8 4
-#define SSL_OBJ_PKCS12 5
-
-/**
- * @defgroup c_api Standard C API
- * @brief The standard interface in C.
- * @{
- */
-
-/**
- * @brief Establish a new client/server context.
- *
- * This function is called before any client/server SSL connections are made.
- *
- * Each new connection will use the this context's private key and
- * certificate chain. If a different certificate chain is required, then a
- * different context needs to be be used.
- *
- * There are two threading models supported - a single thread with one
- * SSL_CTX can support any number of SSL connections - and multiple threads can
- * support one SSL_CTX object each (the default). But if a single SSL_CTX
- * object uses many SSL objects in individual threads, then the
- * CONFIG_SSL_CTX_MUTEXING option needs to be configured.
- *
- * @param options [in] Any particular options. At present the options
- * supported are:
- * - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if the server
- * authentication fails. The certificate can be authenticated later with a
- * call to ssl_verify_cert().
- * - SSL_CLIENT_AUTHENTICATION (server only): Enforce client authentication
- * i.e. each handshake will include a "certificate request" message from the
- * server. Only available if verification has been enabled.
- * - SSL_DISPLAY_BYTES (full mode build only): Display the byte sequences
- * during the handshake.
- * - SSL_DISPLAY_STATES (full mode build only): Display the state changes
- * during the handshake.
- * - SSL_DISPLAY_CERTS (full mode build only): Display the certificates that
- * are passed during a handshake.
- * - SSL_DISPLAY_RSA (full mode build only): Display the RSA key details that
- * are passed during a handshake.
- * - SSL_CONNECT_IN_PARTS (client only): To use a non-blocking version of
- * ssl_client_new().
- * @param num_sessions [in] The number of sessions to be used for session
- * caching. If this value is 0, then there is no session caching. This option
- * is not used in skeleton mode.
- * @return A client/server context.
- */
-EXP_FUNC SSL_CTX * STDCALL ssl_ctx_new(uint32_t options, int num_sessions);
-
-/**
- * @brief Remove a client/server context.
- *
- * Frees any used resources used by this context. Each connection will be
- * sent a "Close Notify" alert (if possible).
- * @param ssl_ctx [in] The client/server context.
- */
-EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);
-
-/**
- * @brief (server only) Establish a new SSL connection to an SSL client.
- *
- * It is up to the application to establish the logical connection (whether it
- * is a socket, serial connection etc).
- * @param ssl_ctx [in] The server context.
- * @param client_fd [in] The client's file descriptor.
- * @return An SSL object reference.
- */
-EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd);
-
-/**
- * @brief (client only) Establish a new SSL connection to an SSL server.
- *
- * It is up to the application to establish the initial logical connection
- * (whether it is a socket, serial connection etc).
- *
- * This is a normally a blocking call - it will finish when the handshake is
- * complete (or has failed). To use in non-blocking mode, set
- * SSL_CONNECT_IN_PARTS in ssl_ctx_new().
- * @param ssl_ctx [in] The client context.
- * @param client_fd [in] The client's file descriptor.
- * @param session_id [in] A 32 byte session id for session resumption. This
- * can be null if no session resumption is being used or required. This option
- * is not used in skeleton mode.
- * @param sess_id_size The size of the session id (max 32)
- * @return An SSL object reference. Use ssl_handshake_status() to check
- * if a handshake succeeded.
- */
-EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size);
-
-/**
- * @brief Free any used resources on this connection.
-
- * A "Close Notify" message is sent on this connection (if possible). It is up
- * to the application to close the socket or file descriptor.
- * @param ssl [in] The ssl object reference.
- */
-EXP_FUNC void STDCALL ssl_free(SSL *ssl);
-
-/**
- * @brief Read the SSL data stream.
- * If the socket is non-blocking and data is blocked then SSO_OK will be
- * returned.
- * @param ssl [in] An SSL object reference.
- * @param in_data [out] If the read was successful, a pointer to the read
- * buffer will be here. Do NOT ever free this memory as this buffer is used in
- * sucessive calls. If the call was unsuccessful, this value will be null.
- * @return The number of decrypted bytes:
- * - if > 0, then the handshaking is complete and we are returning the number
- * of decrypted bytes.
- * - SSL_OK if the handshaking stage is successful (but not yet complete).
- * - < 0 if an error.
- * @see ssl.h for the error code list.
- * @note Use in_data before doing any successive ssl calls.
- */
-EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data);
-
-/**
- * @brief Write to the SSL data stream.
- * if the socket is non-blocking and data is blocked then a check is made
- * to ensure that all data is sent (i.e. blocked mode is forced).
- * @param ssl [in] An SSL obect reference.
- * @param out_data [in] The data to be written
- * @param out_len [in] The number of bytes to be written.
- * @return The number of bytes sent, or if < 0 if an error.
- * @see ssl.h for the error code list.
- */
-EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len);
-
-/**
- * @brief Find an ssl object based on a file descriptor.
- *
- * Goes through the list of SSL objects maintained in a client/server context
- * to look for a file descriptor match.
- * @param ssl_ctx [in] The client/server context.
- * @param client_fd [in] The file descriptor.
- * @return A reference to the SSL object. Returns null if the object could not
- * be found.
- */
-EXP_FUNC SSL * STDCALL ssl_find(SSL_CTX *ssl_ctx, int client_fd);
-
-/**
- * @brief Get the session id for a handshake.
- *
- * This will be a 32 byte sequence and is available after the first
- * handshaking messages are sent.
- * @param ssl [in] An SSL object reference.
- * @return The session id as a 32 byte sequence.
- * @note A SSLv23 handshake may have only 16 valid bytes.
- */
-EXP_FUNC const uint8_t * STDCALL ssl_get_session_id(const SSL *ssl);
-
-/**
- * @brief Get the session id size for a handshake.
- *
- * This will normally be 32 but could be 0 (no session id) or something else.
- * @param ssl [in] An SSL object reference.
- * @return The size of the session id.
- */
-EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl);
-
-/**
- * @brief Return the cipher id (in the SSL form).
- * @param ssl [in] An SSL object reference.
- * @return The cipher id. This will be one of the following:
- * - SSL_AES128_SHA (0x2f)
- * - SSL_AES256_SHA (0x35)
- * - SSL_RC4_128_SHA (0x05)
- * - SSL_RC4_128_MD5 (0x04)
- */
-EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);
-
-/**
- * @brief Return the status of the handshake.
- * @param ssl [in] An SSL object reference.
- * @return SSL_OK if the handshake is complete and ok.
- * @see ssl.h for the error code list.
- */
-EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl);
-
-/**
- * @brief Retrieve various parameters about the axTLS engine.
- * @param offset [in] The configuration offset. It will be one of the following:
- * - SSL_BUILD_MODE The build mode. This will be one of the following:
- * - SSL_BUILD_SERVER_ONLY (basic server mode)
- * - SSL_BUILD_ENABLE_VERIFICATION (server can do client authentication)
- * - SSL_BUILD_ENABLE_CLIENT (client/server capabilties)
- * - SSL_BUILD_FULL_MODE (client/server with diagnostics)
- * - SSL_BUILD_SKELETON_MODE (skeleton mode)
- * - SSL_MAX_CERT_CFG_OFFSET The maximum number of certificates allowed.
- * - SSL_MAX_CA_CERT_CFG_OFFSET The maximum number of CA certificates allowed.
- * - SSL_HAS_PEM 1 if supported
- * @return The value of the requested parameter.
- */
-EXP_FUNC int STDCALL ssl_get_config(int offset);
-
-/**
- * @brief Display why the handshake failed.
- *
- * This call is only useful in a 'full mode' build. The output is to stdout.
- * @param error_code [in] An error code.
- * @see ssl.h for the error code list.
- */
-EXP_FUNC void STDCALL ssl_display_error(int error_code);
-
-/**
- * @brief Authenticate a received certificate.
- *
- * This call is usually made by a client after a handshake is complete and the
- * context is in SSL_SERVER_VERIFY_LATER mode.
- * @param ssl [in] An SSL object reference.
- * @return SSL_OK if the certificate is verified.
- */
-EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
-
-/**
- * @brief Retrieve an X.509 distinguished name component.
- *
- * When a handshake is complete and a certificate has been exchanged, then the
- * details of the remote certificate can be retrieved.
- *
- * This will usually be used by a client to check that the server's common
- * name matches the URL.
- *
- * @param ssl [in] An SSL object reference.
- * @param component [in] one of:
- * - SSL_X509_CERT_COMMON_NAME
- * - SSL_X509_CERT_ORGANIZATION
- * - SSL_X509_CERT_ORGANIZATIONAL_NAME
- * - SSL_X509_CA_CERT_COMMON_NAME
- * - SSL_X509_CA_CERT_ORGANIZATION
- * - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
- * @return The appropriate string (or null if not defined)
- * @note Verification build mode must be enabled.
- */
-EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component);
-
-/**
- * @brief Retrieve a Subject Alternative DNSName
- *
- * When a handshake is complete and a certificate has been exchanged, then the
- * details of the remote certificate can be retrieved.
- *
- * This will usually be used by a client to check that the server's DNS
- * name matches the URL.
- *
- * @param ssl [in] An SSL object reference.
- * @param dnsindex [in] The index of the DNS name to retrieve.
- * @return The appropriate string (or null if not defined)
- * @note Verification build mode must be enabled.
- */
-EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl, int dnsindex);
-
-/**
- * @brief Force the client to perform its handshake again.
- *
- * For a client this involves sending another "client hello" message.
- * For the server is means sending a "hello request" message.
- *
- * This is a blocking call on the client (until the handshake completes).
- *
- * @param ssl [in] An SSL object reference.
- * @return SSL_OK if renegotiation instantiation was ok
- */
-EXP_FUNC int STDCALL ssl_renegotiate(SSL *ssl);
-
-/**
- * @brief Process a file that is in binary DER or ASCII PEM format.
- *
- * These are temporary objects that are used to load private keys,
- * certificates etc into memory.
- * @param ssl_ctx [in] The client/server context.
- * @param obj_type [in] The format of the file. Can be one of:
- * - SSL_OBJ_X509_CERT (no password required)
- * - SSL_OBJ_X509_CACERT (no password required)
- * - SSL_OBJ_RSA_KEY (AES128/AES256 PEM encryption supported)
- * - SSL_OBJ_PKCS8 (RC4-128 encrypted data supported)
- * - SSL_OBJ_PKCS12 (RC4-128 encrypted data supported)
- *
- * PEM files are automatically detected (if supported). The object type is
- * also detected, and so is not relevant for these types of files.
- * @param filename [in] The location of a file in DER/PEM format.
- * @param password [in] The password used. Can be null if not required.
- * @return SSL_OK if all ok
- * @note Not available in skeleton build mode.
- */
-EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type, const char *filename, const char *password);
-
-/**
- * @brief Process binary data.
- *
- * These are temporary objects that are used to load private keys,
- * certificates etc into memory.
- * @param ssl_ctx [in] The client/server context.
- * @param obj_type [in] The format of the memory data.
- * @param data [in] The binary data to be loaded.
- * @param len [in] The amount of data to be loaded.
- * @param password [in] The password used. Can be null if not required.
- * @return SSL_OK if all ok
- * @see ssl_obj_load for more details on obj_type.
- */
-EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int obj_type, const uint8_t *data, int len, const char *password);
-
-#ifdef CONFIG_SSL_GENERATE_X509_CERT
-/**
- * @brief Create an X.509 certificate.
- *
- * This certificate is a self-signed v1 cert with a fixed start/stop validity
- * times. It is signed with an internal private key in ssl_ctx.
- *
- * @param ssl_ctx [in] The client/server context.
- * @param options [in] Not used yet.
- * @param dn [in] An array of distinguished name strings. The array is defined
- * by:
- * - SSL_X509_CERT_COMMON_NAME (0)
- * - If SSL_X509_CERT_COMMON_NAME is empty or not defined, then the
- * hostname will be used.
- * - SSL_X509_CERT_ORGANIZATION (1)
- * - If SSL_X509_CERT_ORGANIZATION is empty or not defined, then $USERNAME
- * will be used.
- * - SSL_X509_CERT_ORGANIZATIONAL_NAME (2)
- * - SSL_X509_CERT_ORGANIZATIONAL_NAME is optional.
- * @param cert_data [out] The certificate as a sequence of bytes.
- * @return < 0 if an error, or the size of the certificate in bytes.
- * @note cert_data must be freed when there is no more need for it.
- */
-EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const char * dn[], uint8_t **cert_data);
-#endif
-
-/**
- * @brief Return the axTLS library version as a string.
- */
-EXP_FUNC const char * STDCALL ssl_version(void);
-
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/axTLS/src/ssl/tls1.c b/axTLS/src/ssl/tls1.c
deleted file mode 100644
index 4b18365..0000000
--- a/axTLS/src/ssl/tls1.c
+++ /dev/null
@@ -1,2195 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Common ssl/tlsv1 code to both the client and server implementations.
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include "os_port.h"
-#include "ssl.h"
-
-/* The session expiry time */
-#define SSL_EXPIRY_TIME (CONFIG_SSL_EXPIRY_TIME*3600)
-
-static const uint8_t g_hello_request[] = { HS_HELLO_REQUEST, 0, 0, 0 };
-static const uint8_t g_chg_cipher_spec_pkt[] = { 1 };
-static const char * server_finished = "server finished";
-static const char * client_finished = "client finished";
-
-static int do_handshake(SSL *ssl, uint8_t *buf, int read_len);
-static int set_key_block(SSL *ssl, int is_write);
-static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len);
-static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt);
-static int send_raw_packet(SSL *ssl, uint8_t protocol);
-
-/**
- * The server will pick the cipher based on the order that the order that the
- * ciphers are listed. This order is defined at compile time.
- */
-#ifdef CONFIG_SSL_SKELETON_MODE
-const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] =
-{ SSL_RC4_128_SHA };
-#else
-static void session_free(SSL_SESSION *ssl_sessions[], int sess_index);
-
-const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] =
-#ifdef CONFIG_SSL_PROT_LOW /* low security, fast speed */
-{ SSL_RC4_128_SHA, SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_MD5 };
-#elif CONFIG_SSL_PROT_MEDIUM /* medium security, medium speed */
-{ SSL_AES128_SHA, SSL_AES256_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 };
-#else /* CONFIG_SSL_PROT_HIGH */ /* high security, low speed */
-{ SSL_AES256_SHA, SSL_AES128_SHA, SSL_RC4_128_SHA, SSL_RC4_128_MD5 };
-#endif
-#endif /* CONFIG_SSL_SKELETON_MODE */
-
-/**
- * The cipher map containing all the essentials for each cipher.
- */
-#ifdef CONFIG_SSL_SKELETON_MODE
-static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
-{
- { /* RC4-SHA */
- SSL_RC4_128_SHA, /* RC4-SHA */
- 16, /* key size */
- 0, /* iv size */
- 2*(SHA1_SIZE+16), /* key block size */
- 0, /* no padding */
- SHA1_SIZE, /* digest size */
- hmac_sha1, /* hmac algorithm */
- (crypt_func)RC4_crypt, /* encrypt */
- (crypt_func)RC4_crypt /* decrypt */
- },
-};
-#else
-static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
-{
- { /* AES128-SHA */
- SSL_AES128_SHA, /* AES128-SHA */
- 16, /* key size */
- 16, /* iv size */
- 2*(SHA1_SIZE+16+16), /* key block size */
- 16, /* block padding size */
- SHA1_SIZE, /* digest size */
- hmac_sha1, /* hmac algorithm */
- (crypt_func)AES_cbc_encrypt, /* encrypt */
- (crypt_func)AES_cbc_decrypt /* decrypt */
- },
- { /* AES256-SHA */
- SSL_AES256_SHA, /* AES256-SHA */
- 32, /* key size */
- 16, /* iv size */
- 2*(SHA1_SIZE+32+16), /* key block size */
- 16, /* block padding size */
- SHA1_SIZE, /* digest size */
- hmac_sha1, /* hmac algorithm */
- (crypt_func)AES_cbc_encrypt, /* encrypt */
- (crypt_func)AES_cbc_decrypt /* decrypt */
- },
- { /* RC4-SHA */
- SSL_RC4_128_SHA, /* RC4-SHA */
- 16, /* key size */
- 0, /* iv size */
- 2*(SHA1_SIZE+16), /* key block size */
- 0, /* no padding */
- SHA1_SIZE, /* digest size */
- hmac_sha1, /* hmac algorithm */
- (crypt_func)RC4_crypt, /* encrypt */
- (crypt_func)RC4_crypt /* decrypt */
- },
- /*
- * This protocol is from SSLv2 days and is unlikely to be used - but was
- * useful for testing different possible digest algorithms.
- */
- { /* RC4-MD5 */
- SSL_RC4_128_MD5, /* RC4-MD5 */
- 16, /* key size */
- 0, /* iv size */
- 2*(MD5_SIZE+16), /* key block size */
- 0, /* no padding */
- MD5_SIZE, /* digest size */
- hmac_md5, /* hmac algorithm */
- (crypt_func)RC4_crypt, /* encrypt */
- (crypt_func)RC4_crypt /* decrypt */
- },
-};
-#endif
-
-static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
- uint8_t *out, int olen);
-static const cipher_info_t *get_cipher_info(uint8_t cipher);
-static void increment_read_sequence(SSL *ssl);
-static void increment_write_sequence(SSL *ssl);
-static void add_hmac_digest(SSL *ssl, int snd, uint8_t *hmac_header,
- const uint8_t *buf, int buf_len, uint8_t *hmac_buf);
-
-/* win32 VC6.0 doesn't have variadic macros */
-#if defined(WIN32) && !defined(CONFIG_SSL_FULL_MODE)
-void DISPLAY_BYTES(SSL *ssl, const char *format,
- const uint8_t *data, int size, ...) {}
-#endif
-
-/**
- * Establish a new client/server context.
- */
-EXP_FUNC SSL_CTX *STDCALL ssl_ctx_new(uint32_t options, int num_sessions)
-{
- SSL_CTX *ssl_ctx = (SSL_CTX *)calloc(1, sizeof (SSL_CTX));
- ssl_ctx->options = options;
-
- if (load_key_certs(ssl_ctx) < 0)
- {
- free(ssl_ctx); /* can't load our key/certificate pair, so die */
- return NULL;
- }
-
-#ifndef CONFIG_SSL_SKELETON_MODE
- ssl_ctx->num_sessions = num_sessions;
-#endif
-
- SSL_CTX_MUTEX_INIT(ssl_ctx->mutex);
-
-#ifndef CONFIG_SSL_SKELETON_MODE
- if (num_sessions)
- {
- ssl_ctx->ssl_sessions = (SSL_SESSION **)
- calloc(1, num_sessions*sizeof(SSL_SESSION *));
- }
-#endif
-
- return ssl_ctx;
-}
-
-/*
- * Remove a client/server context.
- */
-EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx)
-{
- SSL *ssl;
- int i;
-
- if (ssl_ctx == NULL)
- return;
-
- ssl = ssl_ctx->head;
-
- /* clear out all the ssl entries */
- while (ssl)
- {
- SSL *next = ssl->next;
- ssl_free(ssl);
- ssl = next;
- }
-
-#ifndef CONFIG_SSL_SKELETON_MODE
- /* clear out all the sessions */
- for (i = 0; i < ssl_ctx->num_sessions; i++)
- session_free(ssl_ctx->ssl_sessions, i);
-
- free(ssl_ctx->ssl_sessions);
-#endif
-
- i = 0;
- while (i < CONFIG_SSL_MAX_CERTS && ssl_ctx->certs[i].buf)
- {
- free(ssl_ctx->certs[i].buf);
- ssl_ctx->certs[i++].buf = NULL;
- }
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- remove_ca_certs(ssl_ctx->ca_cert_ctx);
-#endif
- ssl_ctx->chain_length = 0;
- SSL_CTX_MUTEX_DESTROY(ssl_ctx->mutex);
- RSA_free(ssl_ctx->rsa_ctx);
- RNG_terminate();
- free(ssl_ctx);
-}
-
-/*
- * Free any used resources used by this connection.
- */
-EXP_FUNC void STDCALL ssl_free(SSL *ssl)
-{
- SSL_CTX *ssl_ctx;
-
- if (ssl == NULL) /* just ignore null pointers */
- return;
-
- /* only notify if we weren't notified first */
- /* spec says we must notify when we are dying */
- if (!IS_SET_SSL_FLAG(SSL_SENT_CLOSE_NOTIFY))
- send_alert(ssl, SSL_ALERT_CLOSE_NOTIFY);
-
- ssl_ctx = ssl->ssl_ctx;
-
- SSL_CTX_LOCK(ssl_ctx->mutex);
-
- /* adjust the server SSL list */
- if (ssl->prev)
- ssl->prev->next = ssl->next;
- else
- ssl_ctx->head = ssl->next;
-
- if (ssl->next)
- ssl->next->prev = ssl->prev;
- else
- ssl_ctx->tail = ssl->prev;
-
- SSL_CTX_UNLOCK(ssl_ctx->mutex);
-
- /* may already be free - but be sure */
- free(ssl->encrypt_ctx);
- free(ssl->decrypt_ctx);
- disposable_free(ssl);
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- x509_free(ssl->x509_ctx);
-#endif
-
- free(ssl);
-}
-
-EXP_FUNC int STDCALL ssl_handshake(SSL_CTX* ctx);
-
-/*
- * Read the SSL connection and send any alerts for various errors.
- */
-EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data)
-{
- int ret = basic_read(ssl, in_data);
-
- /* check for return code so we can send an alert */
- if (ret < SSL_OK && ret != SSL_CLOSE_NOTIFY)
- {
- if (ret != SSL_ERROR_CONN_LOST)
- {
- send_alert(ssl, ret);
-#ifndef CONFIG_SSL_SKELETON_MODE
- /* something nasty happened, so get rid of this session */
- kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl);
-#endif
- }
- }
-
- return ret;
-}
-
-/*
- * Write application data to the client
- */
-EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len)
-{
- int n = out_len, nw, i, tot = 0;
-
- /* maximum size of a TLS packet is around 16kB, so fragment */
- do
- {
- nw = n;
-
- if (nw > RT_MAX_PLAIN_LENGTH) /* fragment if necessary */
- nw = RT_MAX_PLAIN_LENGTH;
-
- if ((i = send_packet(ssl, PT_APP_PROTOCOL_DATA,
- &out_data[tot], nw)) <= 0)
- {
- out_len = i; /* an error */
- break;
- }
-
- tot += i;
- n -= i;
- } while (n > 0);
-
- return out_len;
-}
-
-/**
- * Add a certificate to the certificate chain.
- */
-int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len)
-{
- int ret = SSL_ERROR_NO_CERT_DEFINED, i = 0;
- SSL_CERT *ssl_cert;
- X509_CTX *cert = NULL;
- int offset;
-
- while (ssl_ctx->certs[i].buf && i < CONFIG_SSL_MAX_CERTS)
- i++;
-
- if (i == CONFIG_SSL_MAX_CERTS) /* too many certs */
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: maximum number of certs added (%d) - change of "
- "compile-time configuration required\n",
- CONFIG_SSL_MAX_CERTS);
-#endif
- goto error;
- }
-
- if ((ret = x509_new(buf, &offset, &cert)))
- goto error;
-
-#if defined (CONFIG_SSL_FULL_MODE)
- if (ssl_ctx->options & SSL_DISPLAY_CERTS)
- x509_print(cert, NULL);
-#endif
-
- ssl_cert = &ssl_ctx->certs[i];
- ssl_cert->size = len;
- ssl_cert->buf = (uint8_t *)malloc(len);
- memcpy(ssl_cert->buf, buf, len);
- ssl_ctx->chain_length++;
- len -= offset;
- ret = SSL_OK; /* ok so far */
-
- /* recurse? */
- if (len > 0)
- {
- ret = add_cert(ssl_ctx, &buf[offset], len);
- }
-
-error:
- x509_free(cert); /* don't need anymore */
- return ret;
-}
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-/**
- * Add a certificate authority.
- */
-int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len)
-{
- int ret = SSL_OK; /* ignore errors for now */
- int i = 0;
- CA_CERT_CTX *ca_cert_ctx;
-
- if (ssl_ctx->ca_cert_ctx == NULL)
- ssl_ctx->ca_cert_ctx = (CA_CERT_CTX *)calloc(1, sizeof(CA_CERT_CTX));
-
- ca_cert_ctx = ssl_ctx->ca_cert_ctx;
-
- while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
- i++;
-
- while (len > 0)
- {
- int offset;
- if (i >= CONFIG_X509_MAX_CA_CERTS)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: maximum number of CA certs added (%d) - change of "
- "compile-time configuration required\n",
- CONFIG_X509_MAX_CA_CERTS);
-#endif
- break;
- }
-
-
- /* ignore the return code */
- if (x509_new(buf, &offset, &ca_cert_ctx->cert[i]) == X509_OK)
- {
-#if defined (CONFIG_SSL_FULL_MODE)
- if (ssl_ctx->options & SSL_DISPLAY_CERTS)
- x509_print(ca_cert_ctx->cert[i], NULL);
-#endif
- }
-
- i++;
- len -= offset;
- }
-
- return ret;
-}
-
-/*
- * Retrieve an X.509 distinguished name component
- */
-EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component)
-{
- if (ssl->x509_ctx == NULL)
- return NULL;
-
- switch (component)
- {
- case SSL_X509_CERT_COMMON_NAME:
- return ssl->x509_ctx->cert_dn[X509_COMMON_NAME];
-
- case SSL_X509_CERT_ORGANIZATION:
- return ssl->x509_ctx->cert_dn[X509_ORGANIZATION];
-
- case SSL_X509_CERT_ORGANIZATIONAL_NAME:
- return ssl->x509_ctx->cert_dn[X509_ORGANIZATIONAL_UNIT];
-
- case SSL_X509_CA_CERT_COMMON_NAME:
- return ssl->x509_ctx->ca_cert_dn[X509_COMMON_NAME];
-
- case SSL_X509_CA_CERT_ORGANIZATION:
- return ssl->x509_ctx->ca_cert_dn[X509_ORGANIZATION];
-
- case SSL_X509_CA_CERT_ORGANIZATIONAL_NAME:
- return ssl->x509_ctx->ca_cert_dn[X509_ORGANIZATIONAL_UNIT];
-
- default:
- return NULL;
- }
-}
-
-/*
- * Retrieve a "Subject Alternative Name" from a v3 certificate
- */
-EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl,
- int dnsindex)
-{
- int i;
-
- if (ssl->x509_ctx == NULL || ssl->x509_ctx->subject_alt_dnsnames == NULL)
- return NULL;
-
- for (i = 0; i < dnsindex; ++i)
- {
- if (ssl->x509_ctx->subject_alt_dnsnames[i] == NULL)
- return NULL;
- }
-
- return ssl->x509_ctx->subject_alt_dnsnames[dnsindex];
-}
-
-#endif /* CONFIG_SSL_CERT_VERIFICATION */
-
-/*
- * Find an ssl object based on the client's file descriptor.
- */
-EXP_FUNC SSL * STDCALL ssl_find(SSL_CTX *ssl_ctx, int client_fd)
-{
- SSL *ssl;
-
- SSL_CTX_LOCK(ssl_ctx->mutex);
- ssl = ssl_ctx->head;
-
- /* search through all the ssl entries */
- while (ssl)
- {
- if (ssl->client_fd == client_fd)
- {
- SSL_CTX_UNLOCK(ssl_ctx->mutex);
- return ssl;
- }
-
- ssl = ssl->next;
- }
-
- SSL_CTX_UNLOCK(ssl_ctx->mutex);
- return NULL;
-}
-
-/*
- * Force the client to perform its handshake again.
- */
-EXP_FUNC int STDCALL ssl_renegotiate(SSL *ssl)
-{
- int ret = SSL_OK;
-
- disposable_new(ssl);
-#ifdef CONFIG_SSL_ENABLE_CLIENT
- if (IS_SET_SSL_FLAG(SSL_IS_CLIENT))
- {
- ret = do_client_connect(ssl);
- }
- else
-#endif
- {
- send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
- g_hello_request, sizeof(g_hello_request));
- SET_SSL_FLAG(SSL_NEED_RECORD);
- }
-
- return ret;
-}
-
-/**
- * @brief Get what we need for key info.
- * @param cipher [in] The cipher information we are after
- * @param key_size [out] The key size for the cipher
- * @param iv_size [out] The iv size for the cipher
- * @return The amount of key information we need.
- */
-static const cipher_info_t *get_cipher_info(uint8_t cipher)
-{
- int i;
-
- for (i = 0; i < NUM_PROTOCOLS; i++)
- {
- if (cipher_info[i].cipher == cipher)
- {
- return &cipher_info[i];
- }
- }
-
- return NULL; /* error */
-}
-
-/*
- * Get a new ssl context for a new connection.
- */
-SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd)
-{
- SSL *ssl = (SSL *)calloc(1, sizeof(SSL));
- ssl->ssl_ctx = ssl_ctx;
- ssl->need_bytes = SSL_RECORD_SIZE; /* need a record */
- ssl->client_fd = client_fd;
- ssl->flag = SSL_NEED_RECORD;
- ssl->bm_data = ssl->bm_all_data+BM_RECORD_OFFSET; /* space at the start */
- ssl->hs_status = SSL_NOT_OK; /* not connected */
-#ifdef CONFIG_ENABLE_VERIFICATION
- ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx;
-#endif
- disposable_new(ssl);
-
- /* a bit hacky but saves a few bytes of memory */
- ssl->flag |= ssl_ctx->options;
- SSL_CTX_LOCK(ssl_ctx->mutex);
-
- if (ssl_ctx->head == NULL)
- {
- ssl_ctx->head = ssl;
- ssl_ctx->tail = ssl;
- }
- else
- {
- ssl->prev = ssl_ctx->tail;
- ssl_ctx->tail->next = ssl;
- ssl_ctx->tail = ssl;
- }
-
- SSL_CTX_UNLOCK(ssl_ctx->mutex);
- return ssl;
-}
-
-/*
- * Add a private key to a context.
- */
-int add_private_key(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj)
-{
- int ret = SSL_OK;
-
- /* get the private key details */
- if (asn1_get_private_key(ssl_obj->buf, ssl_obj->len, &ssl_ctx->rsa_ctx))
- {
- ret = SSL_ERROR_INVALID_KEY;
- goto error;
- }
-
-error:
- return ret;
-}
-
-/**
- * Increment the read sequence number (as a 64 bit endian indepenent #)
- */
-static void increment_read_sequence(SSL *ssl)
-{
- int i;
-
- for (i = 7; i >= 0; i--)
- {
- if (++ssl->read_sequence[i])
- break;
- }
-}
-
-/**
- * Increment the read sequence number (as a 64 bit endian indepenent #)
- */
-static void increment_write_sequence(SSL *ssl)
-{
- int i;
-
- for (i = 7; i >= 0; i--)
- {
- if (++ssl->write_sequence[i])
- break;
- }
-}
-
-/**
- * Work out the HMAC digest in a packet.
- */
-static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
- const uint8_t *buf, int buf_len, uint8_t *hmac_buf)
-{
- int hmac_len = buf_len + 8 + SSL_RECORD_SIZE;
- uint8_t *t_buf = (uint8_t *)alloca(hmac_len+10);
-
- memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ?
- ssl->write_sequence : ssl->read_sequence, 8);
- memcpy(&t_buf[8], hmac_header, SSL_RECORD_SIZE);
- memcpy(&t_buf[8+SSL_RECORD_SIZE], buf, buf_len);
-
- ssl->cipher_info->hmac(t_buf, hmac_len,
- (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ) ?
- ssl->server_mac : ssl->client_mac,
- ssl->cipher_info->digest_size, hmac_buf);
-
-#if 0
- print_blob("record", ssl->hmac_tx, SSL_RECORD_SIZE);
- print_blob("buf", buf, buf_len);
- if (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE)
- {
- print_blob("write seq", ssl->write_sequence, 8);
- }
- else
- {
- print_blob("read seq", ssl->read_sequence, 8);
- }
-
- if (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ)
- {
- print_blob("server mac",
- ssl->server_mac, ssl->cipher_info->digest_size);
- }
- else
- {
- print_blob("client mac",
- ssl->client_mac, ssl->cipher_info->digest_size);
- }
- print_blob("hmac", hmac_buf, SHA1_SIZE);
-#endif
-}
-
-/**
- * Verify that the digest of a packet is correct.
- */
-static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len)
-{
- uint8_t hmac_buf[SHA1_SIZE];
- int hmac_offset;
-
- if (ssl->cipher_info->padding_size)
- {
- int last_blk_size = buf[read_len-1], i;
- hmac_offset = read_len-last_blk_size-ssl->cipher_info->digest_size-1;
-
- /* guard against a timing attack - make sure we do the digest */
- if (hmac_offset < 0)
- {
- hmac_offset = 0;
- }
- else
- {
- /* already looked at last byte */
- for (i = 1; i < last_blk_size; i++)
- {
- if (buf[read_len-i] != last_blk_size)
- {
- hmac_offset = 0;
- break;
- }
- }
- }
- }
- else /* stream cipher */
- {
- hmac_offset = read_len - ssl->cipher_info->digest_size;
-
- if (hmac_offset < 0)
- {
- hmac_offset = 0;
- }
- }
-
- /* sanity check the offset */
- ssl->hmac_header[3] = hmac_offset >> 8; /* insert size */
- ssl->hmac_header[4] = hmac_offset & 0xff;
- add_hmac_digest(ssl, mode, ssl->hmac_header, buf, hmac_offset, hmac_buf);
-
- if (memcmp(hmac_buf, &buf[hmac_offset], ssl->cipher_info->digest_size))
- {
- return SSL_ERROR_INVALID_HMAC;
- }
-
- return hmac_offset;
-}
-
-/**
- * Add a packet to the end of our sent and received packets, so that we may use
- * it to calculate the hash at the end.
- */
-void add_packet(SSL *ssl, const uint8_t *pkt, int len)
-{
- MD5_Update(&ssl->dc->md5_ctx, pkt, len);
- SHA1_Update(&ssl->dc->sha1_ctx, pkt, len);
-}
-
-/**
- * Work out the MD5 PRF.
- */
-static void p_hash_md5(const uint8_t *sec, int sec_len,
- uint8_t *seed, int seed_len, uint8_t *out, int olen)
-{
- uint8_t a1[128];
-
- /* A(1) */
- hmac_md5(seed, seed_len, sec, sec_len, a1);
- memcpy(&a1[MD5_SIZE], seed, seed_len);
- hmac_md5(a1, MD5_SIZE+seed_len, sec, sec_len, out);
-
- while (olen > MD5_SIZE)
- {
- uint8_t a2[MD5_SIZE];
- out += MD5_SIZE;
- olen -= MD5_SIZE;
-
- /* A(N) */
- hmac_md5(a1, MD5_SIZE, sec, sec_len, a2);
- memcpy(a1, a2, MD5_SIZE);
-
- /* work out the actual hash */
- hmac_md5(a1, MD5_SIZE+seed_len, sec, sec_len, out);
- }
-}
-
-/**
- * Work out the SHA1 PRF.
- */
-static void p_hash_sha1(const uint8_t *sec, int sec_len,
- uint8_t *seed, int seed_len, uint8_t *out, int olen)
-{
- uint8_t a1[128];
-
- /* A(1) */
- hmac_sha1(seed, seed_len, sec, sec_len, a1);
- memcpy(&a1[SHA1_SIZE], seed, seed_len);
- hmac_sha1(a1, SHA1_SIZE+seed_len, sec, sec_len, out);
-
- while (olen > SHA1_SIZE)
- {
- uint8_t a2[SHA1_SIZE];
- out += SHA1_SIZE;
- olen -= SHA1_SIZE;
-
- /* A(N) */
- hmac_sha1(a1, SHA1_SIZE, sec, sec_len, a2);
- memcpy(a1, a2, SHA1_SIZE);
-
- /* work out the actual hash */
- hmac_sha1(a1, SHA1_SIZE+seed_len, sec, sec_len, out);
- }
-}
-
-/**
- * Work out the PRF.
- */
-static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
- uint8_t *out, int olen)
-{
- int len, i;
- const uint8_t *S1, *S2;
- uint8_t xbuf[256]; /* needs to be > the amount of key data */
- uint8_t ybuf[256]; /* needs to be > the amount of key data */
-
- len = sec_len/2;
- S1 = sec;
- S2 = &sec[len];
- len += (sec_len & 1); /* add for odd, make longer */
-
- p_hash_md5(S1, len, seed, seed_len, xbuf, olen);
- p_hash_sha1(S2, len, seed, seed_len, ybuf, olen);
-
- for (i = 0; i < olen; i++)
- out[i] = xbuf[i] ^ ybuf[i];
-}
-
-/**
- * Generate a master secret based on the client/server random data and the
- * premaster secret.
- */
-void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret)
-{
- uint8_t buf[128]; /* needs to be > 13+32+32 in size */
- strcpy((char *)buf, "master secret");
- memcpy(&buf[13], ssl->dc->client_random, SSL_RANDOM_SIZE);
- memcpy(&buf[45], ssl->dc->server_random, SSL_RANDOM_SIZE);
- prf(premaster_secret, SSL_SECRET_SIZE, buf, 77, ssl->dc->master_secret,
- SSL_SECRET_SIZE);
-}
-
-/**
- * Generate a 'random' blob of data used for the generation of keys.
- */
-static void generate_key_block(uint8_t *client_random, uint8_t *server_random,
- uint8_t *master_secret, uint8_t *key_block, int key_block_size)
-{
- uint8_t buf[128];
- strcpy((char *)buf, "key expansion");
- memcpy(&buf[13], server_random, SSL_RANDOM_SIZE);
- memcpy(&buf[45], client_random, SSL_RANDOM_SIZE);
- prf(master_secret, SSL_SECRET_SIZE, buf, 77, key_block, key_block_size);
-}
-
-/**
- * Calculate the digest used in the finished message. This function also
- * doubles up as a certificate verify function.
- */
-void finished_digest(SSL *ssl, const char *label, uint8_t *digest)
-{
- uint8_t mac_buf[128];
- uint8_t *q = mac_buf;
- MD5_CTX md5_ctx = ssl->dc->md5_ctx;
- SHA1_CTX sha1_ctx = ssl->dc->sha1_ctx;
-
- if (label)
- {
- strcpy((char *)q, label);
- q += strlen(label);
- }
-
- MD5_Final(q, &md5_ctx);
- q += MD5_SIZE;
-
- SHA1_Final(q, &sha1_ctx);
- q += SHA1_SIZE;
-
- if (label)
- {
- prf(ssl->dc->master_secret, SSL_SECRET_SIZE, mac_buf, (int)(q-mac_buf),
- digest, SSL_FINISHED_HASH_SIZE);
- }
- else /* for use in a certificate verify */
- {
- memcpy(digest, mac_buf, MD5_SIZE + SHA1_SIZE);
- }
-
-#if 0
- printf("label: %s\n", label);
- print_blob("master secret", ssl->dc->master_secret, 48);
- print_blob("mac_buf", mac_buf, q-mac_buf);
- print_blob("finished digest", digest, SSL_FINISHED_HASH_SIZE);
-#endif
-}
-
-/**
- * Retrieve (and initialise) the context of a cipher.
- */
-static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
-{
- switch (ssl->cipher)
- {
-#ifndef CONFIG_SSL_SKELETON_MODE
- case SSL_AES128_SHA:
- {
- AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX));
- AES_set_key(aes_ctx, key, iv, AES_MODE_128);
-
- if (is_decrypt)
- {
- AES_convert_key(aes_ctx);
- }
-
- return (void *)aes_ctx;
- }
-
- case SSL_AES256_SHA:
- {
- AES_CTX *aes_ctx = (AES_CTX *)malloc(sizeof(AES_CTX));
- AES_set_key(aes_ctx, key, iv, AES_MODE_256);
-
- if (is_decrypt)
- {
- AES_convert_key(aes_ctx);
- }
-
- return (void *)aes_ctx;
- }
-
- case SSL_RC4_128_MD5:
-#endif
- case SSL_RC4_128_SHA:
- {
- RC4_CTX *rc4_ctx = (RC4_CTX *)malloc(sizeof(RC4_CTX));
- RC4_setup(rc4_ctx, key, 16);
- return (void *)rc4_ctx;
- }
- }
-
- return NULL; /* its all gone wrong */
-}
-
-/**
- * Send a packet over the socket.
- */
-static int send_raw_packet(SSL *ssl, uint8_t protocol)
-{
- uint8_t *rec_buf = ssl->bm_all_data;
- int pkt_size = SSL_RECORD_SIZE+ssl->bm_index;
- int sent = 0;
- int ret = SSL_OK;
-
- rec_buf[0] = protocol;
- rec_buf[1] = 0x03; /* version = 3.1 or higher */
- rec_buf[2] = ssl->version & 0x0f;
- rec_buf[3] = ssl->bm_index >> 8;
- rec_buf[4] = ssl->bm_index & 0xff;
-
- DISPLAY_BYTES(ssl, "sending %d bytes", ssl->bm_all_data,
- pkt_size, pkt_size);
-
- while (sent < pkt_size)
- {
- ret = SOCKET_WRITE(ssl->client_fd,
- &ssl->bm_all_data[sent], pkt_size-sent);
-
- if (ret >= 0)
- sent += ret;
- else
- {
-
-#ifdef WIN32
- if (GetLastError() != WSAEWOULDBLOCK)
-#else
- if (errno != EAGAIN && errno != EWOULDBLOCK)
-#endif
- return SSL_ERROR_CONN_LOST;
- }
-
- /* keep going until the write buffer has some space */
- if (sent != pkt_size)
- {
- fd_set wfds;
- FD_ZERO(&wfds);
- FD_SET(ssl->client_fd, &wfds);
-
- /* block and wait for it */
- if (select(ssl->client_fd + 1, NULL, &wfds, NULL, NULL) < 0)
- return SSL_ERROR_CONN_LOST;
- }
- }
-
- SET_SSL_FLAG(SSL_NEED_RECORD); /* reset for next time */
- ssl->bm_index = 0;
-
- if (protocol != PT_APP_PROTOCOL_DATA)
- {
- /* always return SSL_OK during handshake */
- ret = SSL_OK;
- }
-
- return ret;
-}
-
-/**
- * Send an encrypted packet with padding bytes if necessary.
- */
-int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
-{
- int ret, msg_length = 0;
-
- /* if our state is bad, don't bother */
- if (ssl->hs_status == SSL_ERROR_DEAD)
- return SSL_ERROR_CONN_LOST;
-
- if (in) /* has the buffer already been initialised? */
- {
- memcpy(ssl->bm_data, in, length);
- }
-
- msg_length += length;
-
- if (IS_SET_SSL_FLAG(SSL_TX_ENCRYPTED))
- {
- int mode = IS_SET_SSL_FLAG(SSL_IS_CLIENT) ?
- SSL_CLIENT_WRITE : SSL_SERVER_WRITE;
- uint8_t hmac_header[SSL_RECORD_SIZE] =
- {
- protocol,
- 0x03, /* version = 3.1 or higher */
- ssl->version & 0x0f,
- msg_length >> 8,
- msg_length & 0xff
- };
-
- if (protocol == PT_HANDSHAKE_PROTOCOL)
- {
- DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
-
- if (ssl->bm_data[0] != HS_HELLO_REQUEST)
- {
- add_packet(ssl, ssl->bm_data, msg_length);
- }
- }
-
- /* add the packet digest */
- add_hmac_digest(ssl, mode, hmac_header, ssl->bm_data, msg_length,
- &ssl->bm_data[msg_length]);
- msg_length += ssl->cipher_info->digest_size;
-
- /* add padding? */
- if (ssl->cipher_info->padding_size)
- {
- int last_blk_size = msg_length%ssl->cipher_info->padding_size;
- int pad_bytes = ssl->cipher_info->padding_size - last_blk_size;
-
- /* ensure we always have at least 1 padding byte */
- if (pad_bytes == 0)
- pad_bytes += ssl->cipher_info->padding_size;
-
- memset(&ssl->bm_data[msg_length], pad_bytes-1, pad_bytes);
- msg_length += pad_bytes;
- }
-
- DISPLAY_BYTES(ssl, "unencrypted write", ssl->bm_data, msg_length);
- increment_write_sequence(ssl);
-
- /* add the explicit IV for TLS1.1 */
- if (ssl->version >= SSL_PROTOCOL_VERSION1_1 &&
- ssl->cipher_info->iv_size)
-
- {
- uint8_t iv_size = ssl->cipher_info->iv_size;
- uint8_t *t_buf = alloca(msg_length + iv_size);
- memcpy(t_buf + iv_size, ssl->bm_data, msg_length);
- get_random(iv_size, t_buf);
- msg_length += iv_size;
- memcpy(ssl->bm_data, t_buf, msg_length);
- }
-
- /* now encrypt the packet */
- ssl->cipher_info->encrypt(ssl->encrypt_ctx, ssl->bm_data,
- ssl->bm_data, msg_length);
- }
- else if (protocol == PT_HANDSHAKE_PROTOCOL)
- {
- DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
-
- if (ssl->bm_data[0] != HS_HELLO_REQUEST)
- {
- add_packet(ssl, ssl->bm_data, length);
- }
- }
-
- ssl->bm_index = msg_length;
- if ((ret = send_raw_packet(ssl, protocol)) <= 0)
- return ret;
-
- return length; /* just return what we wanted to send */
-}
-
-/**
- * Work out the cipher keys we are going to use for this session based on the
- * master secret.
- */
-static int set_key_block(SSL *ssl, int is_write)
-{
- const cipher_info_t *ciph_info = get_cipher_info(ssl->cipher);
- uint8_t *q;
- uint8_t client_key[32], server_key[32]; /* big enough for AES256 */
- uint8_t client_iv[16], server_iv[16]; /* big enough for AES128/256 */
- int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
-
- if (ciph_info == NULL)
- return -1;
-
- /* only do once in a handshake */
- if (ssl->dc->key_block == NULL)
- {
- ssl->dc->key_block = (uint8_t *)malloc(ciph_info->key_block_size);
-
-#if 0
- print_blob("client", ssl->dc->client_random, 32);
- print_blob("server", ssl->dc->server_random, 32);
- print_blob("master", ssl->dc->master_secret, SSL_SECRET_SIZE);
-#endif
- generate_key_block(ssl->dc->client_random, ssl->dc->server_random,
- ssl->dc->master_secret, ssl->dc->key_block,
- ciph_info->key_block_size);
-#if 0
- print_blob("keyblock", ssl->key_block, ciph_info->key_block_size);
-#endif
- }
-
- q = ssl->dc->key_block;
-
- if ((is_client && is_write) || (!is_client && !is_write))
- {
- memcpy(ssl->client_mac, q, ciph_info->digest_size);
- }
-
- q += ciph_info->digest_size;
-
- if ((!is_client && is_write) || (is_client && !is_write))
- {
- memcpy(ssl->server_mac, q, ciph_info->digest_size);
- }
-
- q += ciph_info->digest_size;
- memcpy(client_key, q, ciph_info->key_size);
- q += ciph_info->key_size;
- memcpy(server_key, q, ciph_info->key_size);
- q += ciph_info->key_size;
-
-#ifndef CONFIG_SSL_SKELETON_MODE
- if (ciph_info->iv_size) /* RC4 has no IV, AES does */
- {
- memcpy(client_iv, q, ciph_info->iv_size);
- q += ciph_info->iv_size;
- memcpy(server_iv, q, ciph_info->iv_size);
- q += ciph_info->iv_size;
- }
-#endif
-
- free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx);
-
- /* now initialise the ciphers */
- if (is_client)
- {
- finished_digest(ssl, server_finished, ssl->dc->final_finish_mac);
-
- if (is_write)
- ssl->encrypt_ctx = crypt_new(ssl, client_key, client_iv, 0);
- else
- ssl->decrypt_ctx = crypt_new(ssl, server_key, server_iv, 1);
- }
- else
- {
- finished_digest(ssl, client_finished, ssl->dc->final_finish_mac);
-
- if (is_write)
- ssl->encrypt_ctx = crypt_new(ssl, server_key, server_iv, 0);
- else
- ssl->decrypt_ctx = crypt_new(ssl, client_key, client_iv, 1);
- }
-
- ssl->cipher_info = ciph_info;
- return 0;
-}
-
-/**
- * Read the SSL connection.
- */
-int basic_read(SSL *ssl, uint8_t **in_data)
-{
- int ret = SSL_OK;
- int read_len, is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
- uint8_t *buf = ssl->bm_data;
-
- read_len = SOCKET_READ(ssl->client_fd, &buf[ssl->bm_read_index],
- ssl->need_bytes-ssl->got_bytes);
-
- if (read_len < 0)
- {
-#ifdef WIN32
- if (GetLastError() == WSAEWOULDBLOCK)
-#else
- if (errno == EAGAIN || errno == EWOULDBLOCK)
-#endif
- return 0;
- }
-
- /* connection has gone, so die */
- if (read_len <= 0)
- {
- ret = SSL_ERROR_CONN_LOST;
- ssl->hs_status = SSL_ERROR_DEAD; /* make sure it stays dead */
- goto error;
- }
-
- DISPLAY_BYTES(ssl, "received %d bytes",
- &ssl->bm_data[ssl->bm_read_index], read_len, read_len);
-
- ssl->got_bytes += read_len;
- ssl->bm_read_index += read_len;
-
- /* haven't quite got what we want, so try again later */
- if (ssl->got_bytes < ssl->need_bytes)
- return SSL_OK;
-
- read_len = ssl->got_bytes;
- ssl->got_bytes = 0;
-
- if (IS_SET_SSL_FLAG(SSL_NEED_RECORD))
- {
- /* check for sslv2 "client hello" */
- if (buf[0] & 0x80 && buf[2] == 1)
- {
-#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
- uint8_t version = (buf[3] << 4) + buf[4];
- DISPLAY_BYTES(ssl, "ssl2 record", buf, 5);
-
- /* should be v3.1 (TLSv1) or better */
- ssl->version = ssl->client_version = version;
-
- if (version > SSL_PROTOCOL_VERSION_MAX)
- {
- /* use client's version */
- ssl->version = SSL_PROTOCOL_VERSION_MAX;
- }
- else if (version < SSL_PROTOCOL_MIN_VERSION)
- {
- ret = SSL_ERROR_INVALID_VERSION;
- ssl_display_error(ret);
- return ret;
- }
-
- add_packet(ssl, &buf[2], 3);
- ret = process_sslv23_client_hello(ssl);
-#else
- printf("Error: no SSLv23 handshaking allowed\n"); TTY_FLUSH();
- ret = SSL_ERROR_NOT_SUPPORTED;
-#endif
- goto error; /* not an error - just get out of here */
- }
-
- ssl->need_bytes = (buf[3] << 8) + buf[4];
-
- /* do we violate the spec with the message size? */
- if (ssl->need_bytes > RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET)
- {
- ret = SSL_ERROR_INVALID_PROT_MSG;
- goto error;
- }
-
- CLR_SSL_FLAG(SSL_NEED_RECORD);
- memcpy(ssl->hmac_header, buf, 3); /* store for hmac */
- ssl->record_type = buf[0];
- goto error; /* no error, we're done */
- }
-
- /* for next time - just do it now in case of an error */
- SET_SSL_FLAG(SSL_NEED_RECORD);
- ssl->need_bytes = SSL_RECORD_SIZE;
-
- /* decrypt if we need to */
- if (IS_SET_SSL_FLAG(SSL_RX_ENCRYPTED))
- {
- ssl->cipher_info->decrypt(ssl->decrypt_ctx, buf, buf, read_len);
-
- if (ssl->version >= SSL_PROTOCOL_VERSION1_1 &&
- ssl->cipher_info->iv_size)
- {
- buf += ssl->cipher_info->iv_size;
- read_len -= ssl->cipher_info->iv_size;
- }
-
- read_len = verify_digest(ssl,
- is_client ? SSL_CLIENT_READ : SSL_SERVER_READ, buf, read_len);
-
- /* does the hmac work? */
- if (read_len < 0)
- {
- ret = read_len;
- goto error;
- }
-
- DISPLAY_BYTES(ssl, "decrypted", buf, read_len);
- increment_read_sequence(ssl);
- }
-
- /* The main part of the SSL packet */
- switch (ssl->record_type)
- {
- case PT_HANDSHAKE_PROTOCOL:
- if (ssl->dc != NULL)
- {
- ssl->dc->bm_proc_index = 0;
- ret = do_handshake(ssl, buf, read_len);
- }
- else /* no client renegotiation allowed */
- {
- ret = SSL_ERROR_NO_CLIENT_RENOG;
- goto error;
- }
- break;
-
- case PT_CHANGE_CIPHER_SPEC:
- if (ssl->next_state != HS_FINISHED)
- {
- ret = SSL_ERROR_INVALID_HANDSHAKE;
- goto error;
- }
-
- /* all encrypted from now on */
- SET_SSL_FLAG(SSL_RX_ENCRYPTED);
- if (set_key_block(ssl, 0) < 0)
- {
- ret = SSL_ERROR_INVALID_HANDSHAKE;
- goto error;
- }
-
- memset(ssl->read_sequence, 0, 8);
- break;
-
- case PT_APP_PROTOCOL_DATA:
- if (in_data)
- {
- *in_data = buf; /* point to the work buffer */
- (*in_data)[read_len] = 0; /* null terminate just in case */
- }
-
- ret = read_len;
- break;
-
- case PT_ALERT_PROTOCOL:
- /* return the alert # with alert bit set */
- if(buf[0] == SSL_ALERT_TYPE_WARNING &&
- buf[1] == SSL_ALERT_CLOSE_NOTIFY)
- {
- ret = SSL_CLOSE_NOTIFY;
- send_alert(ssl, SSL_ALERT_CLOSE_NOTIFY);
- SET_SSL_FLAG(SSL_SENT_CLOSE_NOTIFY);
- }
- else
- {
- ret = -buf[1];
- DISPLAY_ALERT(ssl, buf[1]);
- }
-
- break;
-
- default:
- ret = SSL_ERROR_INVALID_PROT_MSG;
- break;
- }
-
-error:
- ssl->bm_read_index = 0; /* reset to go again */
-
- if (ret < SSL_OK && in_data)/* if all wrong, then clear this buffer ptr */
- *in_data = NULL;
-
- return ret;
-}
-
-/**
- * Do some basic checking of data and then perform the appropriate handshaking.
- */
-static int do_handshake(SSL *ssl, uint8_t *buf, int read_len)
-{
- int hs_len = (buf[2]<<8) + buf[3];
- uint8_t handshake_type = buf[0];
- int ret = SSL_OK;
- int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
-
- /* some integrity checking on the handshake */
- PARANOIA_CHECK(read_len-SSL_HS_HDR_SIZE, hs_len);
-
- if (handshake_type != ssl->next_state)
- {
- /* handle a special case on the client */
- if (!is_client || handshake_type != HS_CERT_REQ ||
- ssl->next_state != HS_SERVER_HELLO_DONE)
- {
- ret = SSL_ERROR_INVALID_HANDSHAKE;
- goto error;
- }
- }
-
- hs_len += SSL_HS_HDR_SIZE; /* adjust for when adding packets */
- ssl->bm_index = hs_len; /* store the size and check later */
- DISPLAY_STATE(ssl, 0, handshake_type, 0);
-
- if (handshake_type != HS_CERT_VERIFY && handshake_type != HS_HELLO_REQUEST)
- add_packet(ssl, buf, hs_len);
-
-#if defined(CONFIG_SSL_ENABLE_CLIENT)
- ret = is_client ?
- do_clnt_handshake(ssl, handshake_type, buf, hs_len) :
- do_svr_handshake(ssl, handshake_type, buf, hs_len);
-#else
- ret = do_svr_handshake(ssl, handshake_type, buf, hs_len);
-#endif
-
- /* just use recursion to get the rest */
- if (hs_len < read_len && ret == SSL_OK)
- ret = do_handshake(ssl, &buf[hs_len], read_len-hs_len);
-
-error:
- return ret;
-}
-
-/**
- * Sends the change cipher spec message. We have just read a finished message
- * from the client.
- */
-int send_change_cipher_spec(SSL *ssl)
-{
- int ret = send_packet(ssl, PT_CHANGE_CIPHER_SPEC,
- g_chg_cipher_spec_pkt, sizeof(g_chg_cipher_spec_pkt));
- SET_SSL_FLAG(SSL_TX_ENCRYPTED);
-
- if (ret >= 0 && set_key_block(ssl, 1) < 0)
- ret = SSL_ERROR_INVALID_HANDSHAKE;
-
- memset(ssl->write_sequence, 0, 8);
- return ret;
-}
-
-/**
- * Send a "finished" message
- */
-int send_finished(SSL *ssl)
-{
- uint8_t buf[SSL_FINISHED_HASH_SIZE+4] = {
- HS_FINISHED, 0, 0, SSL_FINISHED_HASH_SIZE };
-
- /* now add the finished digest mac (12 bytes) */
- finished_digest(ssl,
- IS_SET_SSL_FLAG(SSL_IS_CLIENT) ?
- client_finished : server_finished, &buf[4]);
-
-#ifndef CONFIG_SSL_SKELETON_MODE
- /* store in the session cache */
- if (!IS_SET_SSL_FLAG(SSL_SESSION_RESUME) && ssl->ssl_ctx->num_sessions)
- {
- memcpy(ssl->session->master_secret,
- ssl->dc->master_secret, SSL_SECRET_SIZE);
- }
-#endif
-
- return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
- buf, SSL_FINISHED_HASH_SIZE+4);
-}
-
-/**
- * Send an alert message.
- * Return 1 if the alert was an "error".
- */
-int send_alert(SSL *ssl, int error_code)
-{
- int alert_num = 0;
- int is_warning = 0;
- uint8_t buf[2];
-
- /* Don't bother we're already dead */
- if (ssl->hs_status == SSL_ERROR_DEAD)
- {
- return SSL_ERROR_CONN_LOST;
- }
-
-#ifdef CONFIG_SSL_FULL_MODE
- if (IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
- ssl_display_error(error_code);
-#endif
-
- switch (error_code)
- {
- case SSL_ALERT_CLOSE_NOTIFY:
- is_warning = 1;
- alert_num = SSL_ALERT_CLOSE_NOTIFY;
- break;
-
- case SSL_ERROR_CONN_LOST: /* don't send alert just yet */
- is_warning = 1;
- break;
-
- case SSL_ERROR_INVALID_HANDSHAKE:
- case SSL_ERROR_INVALID_PROT_MSG:
- alert_num = SSL_ALERT_HANDSHAKE_FAILURE;
- break;
-
- case SSL_ERROR_INVALID_HMAC:
- case SSL_ERROR_FINISHED_INVALID:
- alert_num = SSL_ALERT_BAD_RECORD_MAC;
- break;
-
- case SSL_ERROR_INVALID_VERSION:
- alert_num = SSL_ALERT_INVALID_VERSION;
- break;
-
- case SSL_ERROR_INVALID_SESSION:
- case SSL_ERROR_NO_CIPHER:
- case SSL_ERROR_INVALID_KEY:
- alert_num = SSL_ALERT_ILLEGAL_PARAMETER;
- break;
-
- case SSL_ERROR_BAD_CERTIFICATE:
- alert_num = SSL_ALERT_BAD_CERTIFICATE;
- break;
-
- case SSL_ERROR_NO_CLIENT_RENOG:
- alert_num = SSL_ALERT_NO_RENEGOTIATION;
- break;
-
- default:
- /* a catch-all for any badly verified certificates */
- alert_num = (error_code <= SSL_X509_OFFSET) ?
- SSL_ALERT_BAD_CERTIFICATE : SSL_ALERT_UNEXPECTED_MESSAGE;
- break;
- }
-
- buf[0] = is_warning ? 1 : 2;
- buf[1] = alert_num;
- send_packet(ssl, PT_ALERT_PROTOCOL, buf, sizeof(buf));
- DISPLAY_ALERT(ssl, alert_num);
- return is_warning ? 0 : 1;
-}
-
-/**
- * Process a client finished message.
- */
-int process_finished(SSL *ssl, uint8_t *buf, int hs_len)
-{
- int ret = SSL_OK;
- int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
- int resume = IS_SET_SSL_FLAG(SSL_SESSION_RESUME);
-
- PARANOIA_CHECK(ssl->bm_index, SSL_FINISHED_HASH_SIZE+4);
-
- /* check that we all work before we continue */
- if (memcmp(ssl->dc->final_finish_mac, &buf[4], SSL_FINISHED_HASH_SIZE))
- return SSL_ERROR_FINISHED_INVALID;
-
- if ((!is_client && !resume) || (is_client && resume))
- {
- if ((ret = send_change_cipher_spec(ssl)) == SSL_OK)
- ret = send_finished(ssl);
- }
-
- /* if we ever renegotiate */
- ssl->next_state = is_client ? HS_HELLO_REQUEST : HS_CLIENT_HELLO;
- ssl->hs_status = ret; /* set the final handshake status */
-
-error:
- return ret;
-}
-
-/**
- * Send a certificate.
- */
-int send_certificate(SSL *ssl)
-{
- int i = 0;
- uint8_t *buf = ssl->bm_data;
- int offset = 7;
- int chain_length;
-
- buf[0] = HS_CERTIFICATE;
- buf[1] = 0;
- buf[4] = 0;
-
- while (i < ssl->ssl_ctx->chain_length)
- {
- SSL_CERT *cert = &ssl->ssl_ctx->certs[i];
- buf[offset++] = 0;
- buf[offset++] = cert->size >> 8; /* cert 1 length */
- buf[offset++] = cert->size & 0xff;
- memcpy(&buf[offset], cert->buf, cert->size);
- offset += cert->size;
- i++;
- }
-
- chain_length = offset - 7;
- buf[5] = chain_length >> 8; /* cert chain length */
- buf[6] = chain_length & 0xff;
- chain_length += 3;
- buf[2] = chain_length >> 8; /* handshake length */
- buf[3] = chain_length & 0xff;
- ssl->bm_index = offset;
- return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
-}
-
-/**
- * Create a blob of memory that we'll get rid of once the handshake is
- * complete.
- */
-void disposable_new(SSL *ssl)
-{
- if (ssl->dc == NULL)
- {
- ssl->dc = (DISPOSABLE_CTX *)calloc(1, sizeof(DISPOSABLE_CTX));
- MD5_Init(&ssl->dc->md5_ctx);
- SHA1_Init(&ssl->dc->sha1_ctx);
- }
-}
-
-/**
- * Remove the temporary blob of memory.
- */
-void disposable_free(SSL *ssl)
-{
- if (ssl->dc)
- {
- free(ssl->dc->key_block);
- memset(ssl->dc, 0, sizeof(DISPOSABLE_CTX));
- free(ssl->dc);
- ssl->dc = NULL;
- }
-
-}
-
-#ifndef CONFIG_SSL_SKELETON_MODE /* no session resumption in this mode */
-/**
- * Find if an existing session has the same session id. If so, use the
- * master secret from this session for session resumption.
- */
-SSL_SESSION *ssl_session_update(int max_sessions, SSL_SESSION *ssl_sessions[],
- SSL *ssl, const uint8_t *session_id)
-{
- time_t tm = time(NULL);
- time_t oldest_sess_time = tm;
- SSL_SESSION *oldest_sess = NULL;
- int i;
-
- /* no sessions? Then bail */
- if (max_sessions == 0)
- return NULL;
-
- SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
- if (session_id)
- {
- for (i = 0; i < max_sessions; i++)
- {
- if (ssl_sessions[i])
- {
- /* kill off any expired sessions */
- if (tm > ssl_sessions[i]->conn_time + SSL_EXPIRY_TIME)
- {
- session_free(ssl_sessions, i);
- continue;
- }
-
- /* if the session id matches, it must still be less than
- the expiry time */
- if (memcmp(ssl_sessions[i]->session_id, session_id,
- SSL_SESSION_ID_SIZE) == 0)
- {
- ssl->session_index = i;
- memcpy(ssl->dc->master_secret,
- ssl_sessions[i]->master_secret, SSL_SECRET_SIZE);
- SET_SSL_FLAG(SSL_SESSION_RESUME);
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
- return ssl_sessions[i]; /* a session was found */
- }
- }
- }
- }
-
- /* If we've got here, no matching session was found - so create one */
- for (i = 0; i < max_sessions; i++)
- {
- if (ssl_sessions[i] == NULL)
- {
- /* perfect, this will do */
- ssl_sessions[i] = (SSL_SESSION *)calloc(1, sizeof(SSL_SESSION));
- ssl_sessions[i]->conn_time = tm;
- ssl->session_index = i;
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
- return ssl_sessions[i]; /* return the session object */
- }
- else if (ssl_sessions[i]->conn_time <= oldest_sess_time)
- {
- /* find the oldest session */
- oldest_sess_time = ssl_sessions[i]->conn_time;
- oldest_sess = ssl_sessions[i];
- ssl->session_index = i;
- }
- }
-
- /* ok, we've used up all of our sessions. So blow the oldest session away */
- if (oldest_sess != NULL)
- {
- oldest_sess->conn_time = tm;
- memset(oldest_sess->session_id, 0, sizeof(SSL_SESSION_ID_SIZE));
- memset(oldest_sess->master_secret, 0, sizeof(SSL_SECRET_SIZE));
- }
-
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
- return oldest_sess;
-}
-
-/**
- * Free an existing session.
- */
-static void session_free(SSL_SESSION *ssl_sessions[], int sess_index)
-{
- if (ssl_sessions[sess_index])
- {
- free(ssl_sessions[sess_index]);
- ssl_sessions[sess_index] = NULL;
- }
-}
-
-/**
- * This ssl object doesn't want this session anymore.
- */
-void kill_ssl_session(SSL_SESSION **ssl_sessions, SSL *ssl)
-{
- SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
-
- if (ssl->ssl_ctx->num_sessions)
- {
- session_free(ssl_sessions, ssl->session_index);
- ssl->session = NULL;
- }
-
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
-}
-#endif /* CONFIG_SSL_SKELETON_MODE */
-
-/*
- * Get the session id for a handshake. This will be a 32 byte sequence.
- */
-EXP_FUNC const uint8_t * STDCALL ssl_get_session_id(const SSL *ssl)
-{
- return ssl->session_id;
-}
-
-/*
- * Get the session id size for a handshake.
- */
-EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl)
-{
- return ssl->sess_id_size;
-}
-
-/*
- * Return the cipher id (in the SSL form).
- */
-EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl)
-{
- return ssl->cipher;
-}
-
-/*
- * Return the status of the handshake.
- */
-EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl)
-{
- return ssl->hs_status;
-}
-
-/*
- * Retrieve various parameters about the SSL engine.
- */
-EXP_FUNC int STDCALL ssl_get_config(int offset)
-{
- switch (offset)
- {
- /* return the appropriate build mode */
- case SSL_BUILD_MODE:
-#if defined(CONFIG_SSL_FULL_MODE)
- return SSL_BUILD_FULL_MODE;
-#elif defined(CONFIG_SSL_ENABLE_CLIENT)
- return SSL_BUILD_ENABLE_CLIENT;
-#elif defined(CONFIG_ENABLE_VERIFICATION)
- return SSL_BUILD_ENABLE_VERIFICATION;
-#elif defined(CONFIG_SSL_SERVER_ONLY )
- return SSL_BUILD_SERVER_ONLY;
-#else
- return SSL_BUILD_SKELETON_MODE;
-#endif
-
- case SSL_MAX_CERT_CFG_OFFSET:
- return CONFIG_SSL_MAX_CERTS;
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- case SSL_MAX_CA_CERT_CFG_OFFSET:
- return CONFIG_X509_MAX_CA_CERTS;
-#endif
-#ifdef CONFIG_SSL_HAS_PEM
- case SSL_HAS_PEM:
- return 1;
-#endif
- default:
- return 0;
- }
-}
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-/**
- * Authenticate a received certificate.
- */
-EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl)
-{
- int ret;
- SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
- ret = x509_verify(ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx);
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
-
- if (ret) /* modify into an SSL error type */
- {
- ret = SSL_X509_ERROR(ret);
- }
-
- return ret;
-}
-
-/**
- * Process a certificate message.
- */
-int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
-{
- int ret = SSL_OK;
- uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
- int pkt_size = ssl->bm_index;
- int cert_size, offset = 5;
- int total_cert_size = (buf[offset]<<8) + buf[offset+1];
- int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
- X509_CTX **chain = x509_ctx;
- offset += 2;
-
- PARANOIA_CHECK(total_cert_size, offset);
-
- while (offset < total_cert_size)
- {
- offset++; /* skip empty char */
- cert_size = (buf[offset]<<8) + buf[offset+1];
- offset += 2;
-
- if (x509_new(&buf[offset], NULL, chain))
- {
- ret = SSL_ERROR_BAD_CERTIFICATE;
- goto error;
- }
-
- chain = &((*chain)->next);
- offset += cert_size;
- }
-
- PARANOIA_CHECK(pkt_size, offset);
-
- /* if we are client we can do the verify now or later */
- if (is_client && !IS_SET_SSL_FLAG(SSL_SERVER_VERIFY_LATER))
- {
- ret = ssl_verify_cert(ssl);
- }
-
- ssl->next_state = is_client ? HS_SERVER_HELLO_DONE : HS_CLIENT_KEY_XCHG;
- ssl->dc->bm_proc_index += offset;
-error:
- return ret;
-}
-
-#endif /* CONFIG_SSL_CERT_VERIFICATION */
-
-/**
- * Debugging routine to display SSL handshaking stuff.
- */
-#ifdef CONFIG_SSL_FULL_MODE
-/**
- * Debugging routine to display SSL states.
- */
-void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok)
-{
- const char *str;
-
- if (!IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
- return;
-
- printf(not_ok ? "Error - invalid State:\t" : "State:\t");
- printf(is_send ? "sending " : "receiving ");
-
- switch (state)
- {
- case HS_HELLO_REQUEST:
- str = "Hello Request (0)";
- break;
-
- case HS_CLIENT_HELLO:
- str = "Client Hello (1)";
- break;
-
- case HS_SERVER_HELLO:
- str = "Server Hello (2)";
- break;
-
- case HS_CERTIFICATE:
- str = "Certificate (11)";
- break;
-
- case HS_SERVER_KEY_XCHG:
- str = "Certificate Request (12)";
- break;
-
- case HS_CERT_REQ:
- str = "Certificate Request (13)";
- break;
-
- case HS_SERVER_HELLO_DONE:
- str = "Server Hello Done (14)";
- break;
-
- case HS_CERT_VERIFY:
- str = "Certificate Verify (15)";
- break;
-
- case HS_CLIENT_KEY_XCHG:
- str = "Client Key Exchange (16)";
- break;
-
- case HS_FINISHED:
- str = "Finished (16)";
- break;
-
- default:
- str = "Error (Unknown)";
-
- break;
- }
-
- printf("%s\n", str);
- TTY_FLUSH();
-}
-
-/**
- * Debugging routine to display RSA objects
- */
-void DISPLAY_RSA(SSL *ssl, const RSA_CTX *rsa_ctx)
-{
- if (!IS_SET_SSL_FLAG(SSL_DISPLAY_RSA))
- return;
-
- RSA_print(rsa_ctx);
- TTY_FLUSH();
-}
-
-/**
- * Debugging routine to display SSL handshaking bytes.
- */
-void DISPLAY_BYTES(SSL *ssl, const char *format,
- const uint8_t *data, int size, ...)
-{
- va_list(ap);
-
- if (!IS_SET_SSL_FLAG(SSL_DISPLAY_BYTES))
- return;
-
- va_start(ap, size);
- print_blob(format, data, size, va_arg(ap, char *));
- va_end(ap);
- TTY_FLUSH();
-}
-
-/**
- * Debugging routine to display SSL handshaking errors.
- */
-EXP_FUNC void STDCALL ssl_display_error(int error_code)
-{
- if (error_code == SSL_OK)
- return;
-
- printf("Error: ");
-
- /* X509 error? */
- if (error_code < SSL_X509_OFFSET)
- {
- printf("%s\n", x509_display_error(error_code - SSL_X509_OFFSET));
- return;
- }
-
- /* SSL alert error code */
- if (error_code > SSL_ERROR_CONN_LOST)
- {
- printf("SSL error %d\n", -error_code);
- return;
- }
-
- switch (error_code)
- {
- case SSL_ERROR_DEAD:
- printf("connection dead");
- break;
-
- case SSL_ERROR_INVALID_HANDSHAKE:
- printf("invalid handshake");
- break;
-
- case SSL_ERROR_INVALID_PROT_MSG:
- printf("invalid protocol message");
- break;
-
- case SSL_ERROR_INVALID_HMAC:
- printf("invalid mac");
- break;
-
- case SSL_ERROR_INVALID_VERSION:
- printf("invalid version");
- break;
-
- case SSL_ERROR_INVALID_SESSION:
- printf("invalid session");
- break;
-
- case SSL_ERROR_NO_CIPHER:
- printf("no cipher");
- break;
-
- case SSL_ERROR_CONN_LOST:
- printf("connection lost");
- break;
-
- case SSL_ERROR_BAD_CERTIFICATE:
- printf("bad certificate");
- break;
-
- case SSL_ERROR_INVALID_KEY:
- printf("invalid key");
- break;
-
- case SSL_ERROR_FINISHED_INVALID:
- printf("finished invalid");
- break;
-
- case SSL_ERROR_NO_CERT_DEFINED:
- printf("no certificate defined");
- break;
-
- case SSL_ERROR_NO_CLIENT_RENOG:
- printf("client renegotiation not supported");
- break;
-
- case SSL_ERROR_NOT_SUPPORTED:
- printf("Option not supported");
- break;
-
- default:
- printf("undefined as yet - %d", error_code);
- break;
- }
-
- printf("\n");
- TTY_FLUSH();
-}
-
-/**
- * Debugging routine to display alerts.
- */
-void DISPLAY_ALERT(SSL *ssl, int alert)
-{
- if (!IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
- return;
-
- printf("Alert: ");
-
- switch (alert)
- {
- case SSL_ALERT_CLOSE_NOTIFY:
- printf("close notify");
- break;
-
- case SSL_ALERT_INVALID_VERSION:
- printf("invalid version");
- break;
-
- case SSL_ALERT_BAD_CERTIFICATE:
- printf("bad certificate");
- break;
-
- case SSL_ALERT_UNEXPECTED_MESSAGE:
- printf("unexpected message");
- break;
-
- case SSL_ALERT_BAD_RECORD_MAC:
- printf("bad record mac");
- break;
-
- case SSL_ALERT_HANDSHAKE_FAILURE:
- printf("handshake failure");
- break;
-
- case SSL_ALERT_ILLEGAL_PARAMETER:
- printf("illegal parameter");
- break;
-
- case SSL_ALERT_DECODE_ERROR:
- printf("decode error");
- break;
-
- case SSL_ALERT_DECRYPT_ERROR:
- printf("decrypt error");
- break;
-
- case SSL_ALERT_NO_RENEGOTIATION:
- printf("no renegotiation");
- break;
-
- default:
- printf("alert - (unknown %d)", alert);
- break;
- }
-
- printf("\n");
- TTY_FLUSH();
-}
-
-#endif /* CONFIG_SSL_FULL_MODE */
-
-/**
- * Return the version of this library.
- */
-EXP_FUNC const char * STDCALL ssl_version()
-{
- static const char * axtls_version = AXTLS_VERSION;
- return axtls_version;
-}
-
-/**
- * Enable the various language bindings to work regardless of the
- * configuration - they just return an error statement and a bad return code.
- */
-#if !defined(CONFIG_SSL_FULL_MODE)
-EXP_FUNC void STDCALL ssl_display_error(int error_code) {}
-#endif
-
-#ifdef CONFIG_BINDINGS
-#if !defined(CONFIG_SSL_ENABLE_CLIENT)
-EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const
- uint8_t *session_id, uint8_t sess_id_size)
-{
- printf(unsupported_str);
- return NULL;
-}
-#endif
-
-#if !defined(CONFIG_SSL_CERT_VERIFICATION)
-EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl)
-{
- printf(unsupported_str);
- return -1;
-}
-
-
-EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component)
-{
- printf(unsupported_str);
- return NULL;
-}
-
-EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl, int index)
-{
- printf(unsupported_str);
- return NULL;
-}
-
-#endif /* CONFIG_SSL_CERT_VERIFICATION */
-
-#endif /* CONFIG_BINDINGS */
-
diff --git a/axTLS/src/ssl/tls1.h b/axTLS/src/ssl/tls1.h
deleted file mode 100644
index e73bc1a..0000000
--- a/axTLS/src/ssl/tls1.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file tls1.h
- *
- * @brief The definitions for the TLS library.
- */
-#ifndef HEADER_SSL_LIB_H
-#define HEADER_SSL_LIB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "version.h"
-#include "crypto.h"
-#include "crypto_misc.h"
-
-#define SSL_PROTOCOL_MIN_VERSION 0x31 /* TLS v1.0 */
-#define SSL_PROTOCOL_MINOR_VERSION 0x02 /* TLS v1.1 */
-#define SSL_PROTOCOL_VERSION_MAX 0x32 /* TLS v1.1 */
-#define SSL_PROTOCOL_VERSION1_1 0x32 /* TLS v1.1 */
-#define SSL_RANDOM_SIZE 32
-#define SSL_SECRET_SIZE 48
-#define SSL_FINISHED_HASH_SIZE 12
-#define SSL_RECORD_SIZE 5
-#define SSL_SERVER_READ 0
-#define SSL_SERVER_WRITE 1
-#define SSL_CLIENT_READ 2
-#define SSL_CLIENT_WRITE 3
-#define SSL_HS_HDR_SIZE 4
-
-/* the flags we use while establishing a connection */
-#define SSL_NEED_RECORD 0x0001
-#define SSL_TX_ENCRYPTED 0x0002
-#define SSL_RX_ENCRYPTED 0x0004
-#define SSL_SESSION_RESUME 0x0008
-#define SSL_IS_CLIENT 0x0010
-#define SSL_HAS_CERT_REQ 0x0020
-#define SSL_SENT_CLOSE_NOTIFY 0x0040
-
-/* some macros to muck around with flag bits */
-#define SET_SSL_FLAG(A) (ssl->flag |= A)
-#define CLR_SSL_FLAG(A) (ssl->flag &= ~A)
-#define IS_SET_SSL_FLAG(A) (ssl->flag & A)
-
-#define MAX_KEY_BYTE_SIZE 512 /* for a 4096 bit key */
-#define RT_MAX_PLAIN_LENGTH 16384
-#define RT_EXTRA 1024
-#define BM_RECORD_OFFSET 5
-
-#ifdef CONFIG_SSL_SKELETON_MODE
-#define NUM_PROTOCOLS 1
-#else
-#define NUM_PROTOCOLS 4
-#endif
-
-#define PARANOIA_CHECK(A, B) if (A < B) { \
- ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; }
-
-/* protocol types */
-enum
-{
- PT_CHANGE_CIPHER_SPEC = 20,
- PT_ALERT_PROTOCOL,
- PT_HANDSHAKE_PROTOCOL,
- PT_APP_PROTOCOL_DATA
-};
-
-/* handshaking types */
-enum
-{
- HS_HELLO_REQUEST,
- HS_CLIENT_HELLO,
- HS_SERVER_HELLO,
- HS_CERTIFICATE = 11,
- HS_SERVER_KEY_XCHG,
- HS_CERT_REQ,
- HS_SERVER_HELLO_DONE,
- HS_CERT_VERIFY,
- HS_CLIENT_KEY_XCHG,
- HS_FINISHED = 20
-};
-
-typedef struct
-{
- uint8_t cipher;
- uint8_t key_size;
- uint8_t iv_size;
- uint8_t key_block_size;
- uint8_t padding_size;
- uint8_t digest_size;
- hmac_func hmac;
- crypt_func encrypt;
- crypt_func decrypt;
-} cipher_info_t;
-
-struct _SSLObjLoader
-{
- uint8_t *buf;
- int len;
-};
-
-typedef struct _SSLObjLoader SSLObjLoader;
-
-typedef struct
-{
- time_t conn_time;
- uint8_t session_id[SSL_SESSION_ID_SIZE];
- uint8_t master_secret[SSL_SECRET_SIZE];
-} SSL_SESSION;
-
-typedef struct
-{
- uint8_t *buf;
- int size;
-} SSL_CERT;
-
-typedef struct
-{
- MD5_CTX md5_ctx;
- SHA1_CTX sha1_ctx;
- uint8_t final_finish_mac[SSL_FINISHED_HASH_SIZE];
- uint8_t *key_block;
- uint8_t master_secret[SSL_SECRET_SIZE];
- uint8_t client_random[SSL_RANDOM_SIZE]; /* client's random sequence */
- uint8_t server_random[SSL_RANDOM_SIZE]; /* server's random sequence */
- uint16_t bm_proc_index;
-} DISPOSABLE_CTX;
-
-struct _SSL
-{
- uint32_t flag;
- uint16_t need_bytes;
- uint16_t got_bytes;
- uint8_t record_type;
- uint8_t cipher;
- uint8_t sess_id_size;
- uint8_t version;
- uint8_t client_version;
- int16_t next_state;
- int16_t hs_status;
- DISPOSABLE_CTX *dc; /* temporary data which we'll get rid of soon */
- int client_fd;
- const cipher_info_t *cipher_info;
- void *encrypt_ctx;
- void *decrypt_ctx;
- uint8_t bm_all_data[RT_MAX_PLAIN_LENGTH+RT_EXTRA];
- uint8_t *bm_data;
- uint16_t bm_index;
- uint16_t bm_read_index;
- struct _SSL *next; /* doubly linked list */
- struct _SSL *prev;
- struct _SSL_CTX *ssl_ctx; /* back reference to a clnt/svr ctx */
-#ifndef CONFIG_SSL_SKELETON_MODE
- uint16_t session_index;
- SSL_SESSION *session;
-#endif
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- X509_CTX *x509_ctx;
-#endif
-
- uint8_t session_id[SSL_SESSION_ID_SIZE];
- uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */
- uint8_t server_mac[SHA1_SIZE]; /* for HMAC verification */
- uint8_t read_sequence[8]; /* 64 bit sequence number */
- uint8_t write_sequence[8]; /* 64 bit sequence number */
- uint8_t hmac_header[SSL_RECORD_SIZE]; /* rx hmac */
-};
-
-typedef struct _SSL SSL;
-
-struct _SSL_CTX
-{
- uint32_t options;
- uint8_t chain_length;
- RSA_CTX *rsa_ctx;
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- CA_CERT_CTX *ca_cert_ctx;
-#endif
- SSL *head;
- SSL *tail;
- SSL_CERT certs[CONFIG_SSL_MAX_CERTS];
-#ifndef CONFIG_SSL_SKELETON_MODE
- uint16_t num_sessions;
- SSL_SESSION **ssl_sessions;
-#endif
-#ifdef CONFIG_SSL_CTX_MUTEXING
- SSL_CTX_MUTEX_TYPE mutex;
-#endif
-#ifdef CONFIG_OPENSSL_COMPATIBLE
- void *bonus_attr;
-#endif
-};
-
-typedef struct _SSL_CTX SSL_CTX;
-
-/* backwards compatibility */
-typedef struct _SSL_CTX SSLCTX;
-
-extern const uint8_t ssl_prot_prefs[NUM_PROTOCOLS];
-
-SSL *ssl_new(SSL_CTX *ssl_ctx, int client_fd);
-void disposable_new(SSL *ssl);
-void disposable_free(SSL *ssl);
-int send_packet(SSL *ssl, uint8_t protocol,
- const uint8_t *in, int length);
-int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len);
-int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len);
-int process_finished(SSL *ssl, uint8_t *buf, int hs_len);
-int process_sslv23_client_hello(SSL *ssl);
-int send_alert(SSL *ssl, int error_code);
-int send_finished(SSL *ssl);
-int send_certificate(SSL *ssl);
-int basic_read(SSL *ssl, uint8_t **in_data);
-int send_change_cipher_spec(SSL *ssl);
-void finished_digest(SSL *ssl, const char *label, uint8_t *digest);
-void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret);
-void add_packet(SSL *ssl, const uint8_t *pkt, int len);
-int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
-int add_private_key(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj);
-void ssl_obj_free(SSLObjLoader *ssl_obj);
-int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password);
-int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password);
-int load_key_certs(SSL_CTX *ssl_ctx);
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-int add_cert_auth(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
-void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx);
-#endif
-#ifdef CONFIG_SSL_ENABLE_CLIENT
-int do_client_connect(SSL *ssl);
-#endif
-
-#ifdef CONFIG_SSL_FULL_MODE
-void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok);
-void DISPLAY_BYTES(SSL *ssl, const char *format,
- const uint8_t *data, int size, ...);
-void DISPLAY_CERT(SSL *ssl, const X509_CTX *x509_ctx);
-void DISPLAY_RSA(SSL *ssl, const RSA_CTX *rsa_ctx);
-void DISPLAY_ALERT(SSL *ssl, int alert);
-#else
-#define DISPLAY_STATE(A,B,C,D)
-#define DISPLAY_CERT(A,B)
-#define DISPLAY_RSA(A,B)
-#define DISPLAY_ALERT(A, B)
-#ifdef WIN32
-void DISPLAY_BYTES(SSL *ssl, const char *format,/* win32 has no variadic macros */
- const uint8_t *data, int size, ...);
-#else
-#define DISPLAY_BYTES(A,B,C,D,...)
-#endif
-#endif
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-int process_certificate(SSL *ssl, X509_CTX **x509_ctx);
-#endif
-
-SSL_SESSION *ssl_session_update(int max_sessions,
- SSL_SESSION *ssl_sessions[], SSL *ssl,
- const uint8_t *session_id);
-void kill_ssl_session(SSL_SESSION **ssl_sessions, SSL *ssl);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/axTLS/src/ssl/tls1_clnt.c b/axTLS/src/ssl/tls1_clnt.c
deleted file mode 100644
index 196b40e..0000000
--- a/axTLS/src/ssl/tls1_clnt.c
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <stdio.h>
-#include "os_port.h"
-#include "ssl.h"
-
-#ifdef CONFIG_SSL_ENABLE_CLIENT /* all commented out if no client */
-
-static int send_client_hello(SSL *ssl);
-static int process_server_hello(SSL *ssl);
-static int process_server_hello_done(SSL *ssl);
-static int send_client_key_xchg(SSL *ssl);
-static int process_cert_req(SSL *ssl);
-static int send_cert_verify(SSL *ssl);
-
-/*
- * Establish a new SSL connection to an SSL server.
- */
-EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const
- uint8_t *session_id, uint8_t sess_id_size)
-{
- SSL *ssl = ssl_new(ssl_ctx, client_fd);
- ssl->version = SSL_PROTOCOL_VERSION_MAX; /* try top version first */
-
- if (session_id && ssl_ctx->num_sessions)
- {
- if (sess_id_size > SSL_SESSION_ID_SIZE) /* validity check */
- {
- ssl_free(ssl);
- return NULL;
- }
-
- memcpy(ssl->session_id, session_id, sess_id_size);
- ssl->sess_id_size = sess_id_size;
- SET_SSL_FLAG(SSL_SESSION_RESUME); /* just flag for later */
- }
-
- SET_SSL_FLAG(SSL_IS_CLIENT);
- do_client_connect(ssl);
- return ssl;
-}
-
-/*
- * Process the handshake record.
- */
-int do_clnt_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
-{
- int ret;
-
- /* To get here the state must be valid */
- switch (handshake_type)
- {
- case HS_SERVER_HELLO:
- ret = process_server_hello(ssl);
- break;
-
- case HS_CERTIFICATE:
- ret = process_certificate(ssl, &ssl->x509_ctx);
- break;
-
- case HS_SERVER_HELLO_DONE:
- if ((ret = process_server_hello_done(ssl)) == SSL_OK)
- {
- if (IS_SET_SSL_FLAG(SSL_HAS_CERT_REQ))
- {
- if ((ret = send_certificate(ssl)) == SSL_OK &&
- (ret = send_client_key_xchg(ssl)) == SSL_OK)
- {
- send_cert_verify(ssl);
- }
- }
- else
- {
- ret = send_client_key_xchg(ssl);
- }
-
- if (ret == SSL_OK &&
- (ret = send_change_cipher_spec(ssl)) == SSL_OK)
- {
- ret = send_finished(ssl);
- }
- }
- break;
-
- case HS_CERT_REQ:
- ret = process_cert_req(ssl);
- break;
-
- case HS_FINISHED:
- ret = process_finished(ssl, buf, hs_len);
- disposable_free(ssl); /* free up some memory */
- /* note: client renegotiation is not allowed after this */
- break;
-
- case HS_HELLO_REQUEST:
- disposable_new(ssl);
- ret = do_client_connect(ssl);
- break;
-
- default:
- ret = SSL_ERROR_INVALID_HANDSHAKE;
- break;
- }
-
- return ret;
-}
-
-/*
- * Do the handshaking from the beginning.
- */
-int do_client_connect(SSL *ssl)
-{
- int ret = SSL_OK;
-
- send_client_hello(ssl); /* send the client hello */
- ssl->bm_read_index = 0;
- ssl->next_state = HS_SERVER_HELLO;
- ssl->hs_status = SSL_NOT_OK; /* not connected */
-
- /* sit in a loop until it all looks good */
- if (!IS_SET_SSL_FLAG(SSL_CONNECT_IN_PARTS))
- {
- while (ssl->hs_status != SSL_OK)
- {
- ret = ssl_read(ssl, NULL);
-
- if (ret < SSL_OK)
- break;
- }
-
- ssl->hs_status = ret; /* connected? */
- }
-
- return ret;
-}
-
-/*
- * Send the initial client hello.
- */
-static int send_client_hello(SSL *ssl)
-{
- uint8_t *buf = ssl->bm_data;
- time_t tm = time(NULL);
- uint8_t *tm_ptr = &buf[6]; /* time will go here */
- int i, offset;
-
- buf[0] = HS_CLIENT_HELLO;
- buf[1] = 0;
- buf[2] = 0;
- /* byte 3 is calculated later */
- buf[4] = 0x03;
- buf[5] = ssl->version & 0x0f;
-
- /* client random value - spec says that 1st 4 bytes are big endian time */
- *tm_ptr++ = (uint8_t)(((long)tm & 0xff000000) >> 24);
- *tm_ptr++ = (uint8_t)(((long)tm & 0x00ff0000) >> 16);
- *tm_ptr++ = (uint8_t)(((long)tm & 0x0000ff00) >> 8);
- *tm_ptr++ = (uint8_t)(((long)tm & 0x000000ff));
- get_random(SSL_RANDOM_SIZE-4, &buf[10]);
- memcpy(ssl->dc->client_random, &buf[6], SSL_RANDOM_SIZE);
- offset = 6 + SSL_RANDOM_SIZE;
-
- /* give session resumption a go */
- if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME)) /* set initially by user */
- {
- buf[offset++] = ssl->sess_id_size;
- memcpy(&buf[offset], ssl->session_id, ssl->sess_id_size);
- offset += ssl->sess_id_size;
- CLR_SSL_FLAG(SSL_SESSION_RESUME); /* clear so we can set later */
- }
- else
- {
- /* no session id - because no session resumption just yet */
- buf[offset++] = 0;
- }
-
- buf[offset++] = 0; /* number of ciphers */
- buf[offset++] = NUM_PROTOCOLS*2;/* number of ciphers */
-
- /* put all our supported protocols in our request */
- for (i = 0; i < NUM_PROTOCOLS; i++)
- {
- buf[offset++] = 0; /* cipher we are using */
- buf[offset++] = ssl_prot_prefs[i];
- }
-
- buf[offset++] = 1; /* no compression */
- buf[offset++] = 0;
- buf[3] = offset - 4; /* handshake size */
-
- return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
-}
-
-/*
- * Process the server hello.
- */
-static int process_server_hello(SSL *ssl)
-{
- uint8_t *buf = ssl->bm_data;
- int pkt_size = ssl->bm_index;
- int num_sessions = ssl->ssl_ctx->num_sessions;
- uint8_t sess_id_size;
- int offset, ret = SSL_OK;
-
- /* check that we are talking to a TLSv1 server */
- uint8_t version = (buf[4] << 4) + buf[5];
- if (version > SSL_PROTOCOL_VERSION_MAX)
- {
- version = SSL_PROTOCOL_VERSION_MAX;
- }
- else if (ssl->version < SSL_PROTOCOL_MIN_VERSION)
- {
- ret = SSL_ERROR_INVALID_VERSION;
- ssl_display_error(ret);
- goto error;
- }
-
- ssl->version = version;
-
- /* get the server random value */
- memcpy(ssl->dc->server_random, &buf[6], SSL_RANDOM_SIZE);
- offset = 6 + SSL_RANDOM_SIZE; /* skip of session id size */
- sess_id_size = buf[offset++];
-
- if (sess_id_size > SSL_SESSION_ID_SIZE)
- {
- ret = SSL_ERROR_INVALID_SESSION;
- goto error;
- }
-
- if (num_sessions)
- {
- ssl->session = ssl_session_update(num_sessions,
- ssl->ssl_ctx->ssl_sessions, ssl, &buf[offset]);
- memcpy(ssl->session->session_id, &buf[offset], sess_id_size);
-
- /* pad the rest with 0's */
- if (sess_id_size < SSL_SESSION_ID_SIZE)
- {
- memset(&ssl->session->session_id[sess_id_size], 0,
- SSL_SESSION_ID_SIZE-sess_id_size);
- }
- }
-
- memcpy(ssl->session_id, &buf[offset], sess_id_size);
- ssl->sess_id_size = sess_id_size;
- offset += sess_id_size;
-
- /* get the real cipher we are using */
- ssl->cipher = buf[++offset];
- ssl->next_state = IS_SET_SSL_FLAG(SSL_SESSION_RESUME) ?
- HS_FINISHED : HS_CERTIFICATE;
-
- offset++; // skip the compr
- PARANOIA_CHECK(pkt_size, offset);
- ssl->dc->bm_proc_index = offset+1;
-
-error:
- return ret;
-}
-
-/**
- * Process the server hello done message.
- */
-static int process_server_hello_done(SSL *ssl)
-{
- ssl->next_state = HS_FINISHED;
- return SSL_OK;
-}
-
-/*
- * Send a client key exchange message.
- */
-static int send_client_key_xchg(SSL *ssl)
-{
- uint8_t *buf = ssl->bm_data;
- uint8_t premaster_secret[SSL_SECRET_SIZE];
- int enc_secret_size = -1;
-
- buf[0] = HS_CLIENT_KEY_XCHG;
- buf[1] = 0;
-
- premaster_secret[0] = 0x03; /* encode the version number */
- premaster_secret[1] = SSL_PROTOCOL_MINOR_VERSION; /* must be TLS 1.1 */
- get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]);
- DISPLAY_RSA(ssl, ssl->x509_ctx->rsa_ctx);
-
- /* rsa_ctx->bi_ctx is not thread-safe */
- SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
- enc_secret_size = RSA_encrypt(ssl->x509_ctx->rsa_ctx, premaster_secret,
- SSL_SECRET_SIZE, &buf[6], 0);
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
-
- buf[2] = (enc_secret_size + 2) >> 8;
- buf[3] = (enc_secret_size + 2) & 0xff;
- buf[4] = enc_secret_size >> 8;
- buf[5] = enc_secret_size & 0xff;
-
- generate_master_secret(ssl, premaster_secret);
- return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, enc_secret_size+6);
-}
-
-/*
- * Process the certificate request.
- */
-static int process_cert_req(SSL *ssl)
-{
- uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
- int ret = SSL_OK;
- int offset = (buf[2] << 4) + buf[3];
- int pkt_size = ssl->bm_index;
-
- /* don't do any processing - we will send back an RSA certificate anyway */
- ssl->next_state = HS_SERVER_HELLO_DONE;
- SET_SSL_FLAG(SSL_HAS_CERT_REQ);
- ssl->dc->bm_proc_index += offset;
- PARANOIA_CHECK(pkt_size, offset);
-error:
- return ret;
-}
-
-/*
- * Send a certificate verify message.
- */
-static int send_cert_verify(SSL *ssl)
-{
- uint8_t *buf = ssl->bm_data;
- uint8_t dgst[MD5_SIZE+SHA1_SIZE];
- RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
- int n = 0, ret;
-
- DISPLAY_RSA(ssl, rsa_ctx);
-
- buf[0] = HS_CERT_VERIFY;
- buf[1] = 0;
-
- finished_digest(ssl, NULL, dgst); /* calculate the digest */
-
- /* rsa_ctx->bi_ctx is not thread-safe */
- if (rsa_ctx)
- {
- SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
- n = RSA_encrypt(rsa_ctx, dgst, sizeof(dgst), &buf[6], 1);
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
-
- if (n == 0)
- {
- ret = SSL_ERROR_INVALID_KEY;
- goto error;
- }
- }
-
- buf[4] = n >> 8; /* add the RSA size (not officially documented) */
- buf[5] = n & 0xff;
- n += 2;
- buf[2] = n >> 8;
- buf[3] = n & 0xff;
- ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n+4);
-
-error:
- return ret;
-}
-
-#endif /* CONFIG_SSL_ENABLE_CLIENT */
diff --git a/axTLS/src/ssl/tls1_svr.c b/axTLS/src/ssl/tls1_svr.c
deleted file mode 100644
index f374928..0000000
--- a/axTLS/src/ssl/tls1_svr.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include "os_port.h"
-#include "ssl.h"
-
-static const uint8_t g_hello_done[] = { HS_SERVER_HELLO_DONE, 0, 0, 0 };
-
-static int process_client_hello(SSL *ssl);
-static int send_server_hello_sequence(SSL *ssl);
-static int send_server_hello(SSL *ssl);
-static int send_server_hello_done(SSL *ssl);
-static int process_client_key_xchg(SSL *ssl);
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-static int send_certificate_request(SSL *ssl);
-static int process_cert_verify(SSL *ssl);
-#endif
-
-/*
- * Establish a new SSL connection to an SSL client.
- */
-EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd)
-{
- SSL *ssl;
-
- ssl = ssl_new(ssl_ctx, client_fd);
- ssl->next_state = HS_CLIENT_HELLO;
-
-#ifdef CONFIG_SSL_FULL_MODE
- if (ssl_ctx->chain_length == 0)
- printf("Warning - no server certificate defined\n"); TTY_FLUSH();
-#endif
-
- return ssl;
-}
-
-/*
- * Process the handshake record.
- */
-int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
-{
- int ret = SSL_OK;
- ssl->hs_status = SSL_NOT_OK; /* not connected */
-
- /* To get here the state must be valid */
- switch (handshake_type)
- {
- case HS_CLIENT_HELLO:
- if ((ret = process_client_hello(ssl)) == SSL_OK)
- ret = send_server_hello_sequence(ssl);
- break;
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- case HS_CERTIFICATE:/* the client sends its cert */
- ret = process_certificate(ssl, &ssl->x509_ctx);
-
- if (ret == SSL_OK) /* verify the cert */
- {
- int cert_res;
- cert_res = x509_verify(
- ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx);
- ret = (cert_res == 0) ? SSL_OK : SSL_X509_ERROR(cert_res);
- }
- break;
-
- case HS_CERT_VERIFY:
- ret = process_cert_verify(ssl);
- add_packet(ssl, buf, hs_len); /* needs to be done after */
- break;
-#endif
- case HS_CLIENT_KEY_XCHG:
- ret = process_client_key_xchg(ssl);
- break;
-
- case HS_FINISHED:
- ret = process_finished(ssl, buf, hs_len);
- disposable_free(ssl); /* free up some memory */
- break;
- }
-
- return ret;
-}
-
-/*
- * Process a client hello message.
- */
-static int process_client_hello(SSL *ssl)
-{
- uint8_t *buf = ssl->bm_data;
- uint8_t *record_buf = ssl->hmac_header;
- int pkt_size = ssl->bm_index;
- int i, j, cs_len, id_len, offset = 6 + SSL_RANDOM_SIZE;
- int ret = SSL_OK;
-
- uint8_t version = (record_buf[1] << 4) + record_buf[2];
- ssl->version = ssl->client_version = version;
-
- if (version > SSL_PROTOCOL_VERSION_MAX)
- {
- /* use client's version instead */
- ssl->version = SSL_PROTOCOL_VERSION_MAX;
- }
- else if (version < SSL_PROTOCOL_MIN_VERSION) /* old version supported? */
- {
- ret = SSL_ERROR_INVALID_VERSION;
- ssl_display_error(ret);
- goto error;
- }
-
- memcpy(ssl->dc->client_random, &buf[6], SSL_RANDOM_SIZE);
-
- /* process the session id */
- id_len = buf[offset++];
- if (id_len > SSL_SESSION_ID_SIZE)
- {
- return SSL_ERROR_INVALID_SESSION;
- }
-
-#ifndef CONFIG_SSL_SKELETON_MODE
- ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
- ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
-#endif
-
- offset += id_len;
- cs_len = (buf[offset]<<8) + buf[offset+1];
- offset += 3; /* add 1 due to all cipher suites being 8 bit */
-
- PARANOIA_CHECK(pkt_size, offset);
-
- /* work out what cipher suite we are going to use - client defines
- the preference */
- for (i = 0; i < cs_len; i += 2)
- {
- for (j = 0; j < NUM_PROTOCOLS; j++)
- {
- if (ssl_prot_prefs[j] == buf[offset+i]) /* got a match? */
- {
- ssl->cipher = ssl_prot_prefs[j];
- goto do_state;
- }
- }
- }
-
- /* ouch! protocol is not supported */
- ret = SSL_ERROR_NO_CIPHER;
-
-do_state:
-error:
- return ret;
-}
-
-#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
-/*
- * Some browsers use a hybrid SSLv2 "client hello"
- */
-int process_sslv23_client_hello(SSL *ssl)
-{
- uint8_t *buf = ssl->bm_data;
- int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1];
- int ret = SSL_OK;
-
- /* we have already read 3 extra bytes so far */
- int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3);
- int cs_len = buf[1];
- int id_len = buf[3];
- int ch_len = buf[5];
- int i, j, offset = 8; /* start at first cipher */
- int random_offset = 0;
-
- DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len);
-
- add_packet(ssl, buf, read_len);
-
- /* connection has gone, so die */
- if (bytes_needed < 0)
- {
- return SSL_ERROR_CONN_LOST;
- }
-
- /* now work out what cipher suite we are going to use */
- for (j = 0; j < NUM_PROTOCOLS; j++)
- {
- for (i = 0; i < cs_len; i += 3)
- {
- if (ssl_prot_prefs[j] == buf[offset+i])
- {
- ssl->cipher = ssl_prot_prefs[j];
- goto server_hello;
- }
- }
- }
-
- /* ouch! protocol is not supported */
- ret = SSL_ERROR_NO_CIPHER;
- goto error;
-
-server_hello:
- /* get the session id */
- offset += cs_len - 2; /* we've gone 2 bytes past the end */
-#ifndef CONFIG_SSL_SKELETON_MODE
- ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
- ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
-#endif
-
- /* get the client random data */
- offset += id_len;
-
- /* random can be anywhere between 16 and 32 bytes long - so it is padded
- * with 0's to the left */
- if (ch_len == 0x10)
- {
- random_offset += 0x10;
- }
-
- memcpy(&ssl->dc->client_random[random_offset], &buf[offset], ch_len);
- ret = send_server_hello_sequence(ssl);
-
-error:
- return ret;
-}
-#endif
-
-/*
- * Send the entire server hello sequence
- */
-static int send_server_hello_sequence(SSL *ssl)
-{
- int ret;
-
- if ((ret = send_server_hello(ssl)) == SSL_OK)
- {
-#ifndef CONFIG_SSL_SKELETON_MODE
- /* resume handshake? */
- if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))
- {
- if ((ret = send_change_cipher_spec(ssl)) == SSL_OK)
- {
- ret = send_finished(ssl);
- ssl->next_state = HS_FINISHED;
- }
- }
- else
-#endif
- if ((ret = send_certificate(ssl)) == SSL_OK)
- {
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- /* ask the client for its certificate */
- if (IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION))
- {
- if ((ret = send_certificate_request(ssl)) == SSL_OK)
- {
- ret = send_server_hello_done(ssl);
- ssl->next_state = HS_CERTIFICATE;
- }
- }
- else
-#endif
- {
- ret = send_server_hello_done(ssl);
- ssl->next_state = HS_CLIENT_KEY_XCHG;
- }
- }
- }
-
- return ret;
-}
-
-/*
- * Send a server hello message.
- */
-static int send_server_hello(SSL *ssl)
-{
- uint8_t *buf = ssl->bm_data;
- int offset = 0;
-
- buf[0] = HS_SERVER_HELLO;
- buf[1] = 0;
- buf[2] = 0;
- /* byte 3 is calculated later */
- buf[4] = 0x03;
- buf[5] = ssl->version & 0x0f;
-
- /* server random value */
- get_random(SSL_RANDOM_SIZE, &buf[6]);
- memcpy(ssl->dc->server_random, &buf[6], SSL_RANDOM_SIZE);
- offset = 6 + SSL_RANDOM_SIZE;
-
-#ifndef CONFIG_SSL_SKELETON_MODE
- if (IS_SET_SSL_FLAG(SSL_SESSION_RESUME))
- {
- /* retrieve id from session cache */
- buf[offset++] = SSL_SESSION_ID_SIZE;
- memcpy(&buf[offset], ssl->session->session_id, SSL_SESSION_ID_SIZE);
- memcpy(ssl->session_id, ssl->session->session_id, SSL_SESSION_ID_SIZE);
- ssl->sess_id_size = SSL_SESSION_ID_SIZE;
- offset += SSL_SESSION_ID_SIZE;
- }
- else /* generate our own session id */
-#endif
- {
-#ifndef CONFIG_SSL_SKELETON_MODE
- buf[offset++] = SSL_SESSION_ID_SIZE;
- get_random(SSL_SESSION_ID_SIZE, &buf[offset]);
- memcpy(ssl->session_id, &buf[offset], SSL_SESSION_ID_SIZE);
- ssl->sess_id_size = SSL_SESSION_ID_SIZE;
-
- /* store id in session cache */
- if (ssl->ssl_ctx->num_sessions)
- {
- memcpy(ssl->session->session_id,
- ssl->session_id, SSL_SESSION_ID_SIZE);
- }
-
- offset += SSL_SESSION_ID_SIZE;
-#else
- buf[offset++] = 0; /* don't bother with session id in skelton mode */
-#endif
- }
-
- buf[offset++] = 0; /* cipher we are using */
- buf[offset++] = ssl->cipher;
- buf[offset++] = 0; /* no compression */
- buf[3] = offset - 4; /* handshake size */
- return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
-}
-
-/*
- * Send the server hello done message.
- */
-static int send_server_hello_done(SSL *ssl)
-{
- return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
- g_hello_done, sizeof(g_hello_done));
-}
-
-/*
- * Pull apart a client key exchange message. Decrypt the pre-master key (using
- * our RSA private key) and then work out the master key. Initialise the
- * ciphers.
- */
-static int process_client_key_xchg(SSL *ssl)
-{
- uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
- int pkt_size = ssl->bm_index;
- int premaster_size, secret_length = (buf[2] << 8) + buf[3];
- uint8_t premaster_secret[MAX_KEY_BYTE_SIZE];
- RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
- int offset = 4;
- int ret = SSL_OK;
-
- if (rsa_ctx == NULL)
- {
- ret = SSL_ERROR_NO_CERT_DEFINED;
- goto error;
- }
-
- /* is there an extra size field? */
- if ((secret_length - 2) == rsa_ctx->num_octets)
- offset += 2;
-
- PARANOIA_CHECK(pkt_size, rsa_ctx->num_octets+offset);
-
- /* rsa_ctx->bi_ctx is not thread-safe */
- SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
- premaster_size = RSA_decrypt(rsa_ctx, &buf[offset], premaster_secret, 1);
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
-
- if (premaster_size != SSL_SECRET_SIZE ||
- premaster_secret[0] != 0x03 || /* must be the same as client
- offered version */
- premaster_secret[1] != (ssl->client_version & 0x0f))
- {
- /* guard against a Bleichenbacher attack */
- get_random(SSL_SECRET_SIZE, premaster_secret);
- /* and continue - will die eventually when checking the mac */
- }
-
-#if 0
- print_blob("pre-master", premaster_secret, SSL_SECRET_SIZE);
-#endif
-
- generate_master_secret(ssl, premaster_secret);
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- ssl->next_state = IS_SET_SSL_FLAG(SSL_CLIENT_AUTHENTICATION) ?
- HS_CERT_VERIFY : HS_FINISHED;
-#else
- ssl->next_state = HS_FINISHED;
-#endif
-
- ssl->dc->bm_proc_index += rsa_ctx->num_octets+offset;
-error:
- return ret;
-}
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 };
-
-/*
- * Send the certificate request message.
- */
-static int send_certificate_request(SSL *ssl)
-{
- return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
- g_cert_request, sizeof(g_cert_request));
-}
-
-/*
- * Ensure the client has the private key by first decrypting the packet and
- * then checking the packet digests.
- */
-static int process_cert_verify(SSL *ssl)
-{
- uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
- int pkt_size = ssl->bm_index;
- uint8_t dgst_buf[MAX_KEY_BYTE_SIZE];
- uint8_t dgst[MD5_SIZE+SHA1_SIZE];
- X509_CTX *x509_ctx = ssl->x509_ctx;
- int ret = SSL_OK;
- int n;
-
- PARANOIA_CHECK(pkt_size, x509_ctx->rsa_ctx->num_octets+6);
- DISPLAY_RSA(ssl, x509_ctx->rsa_ctx);
-
- /* rsa_ctx->bi_ctx is not thread-safe */
- SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
- n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, 0);
- SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
-
- if (n != SHA1_SIZE + MD5_SIZE)
- {
- ret = SSL_ERROR_INVALID_KEY;
- goto end_cert_vfy;
- }
-
- finished_digest(ssl, NULL, dgst); /* calculate the digest */
- if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE))
- {
- ret = SSL_ERROR_INVALID_KEY;
- }
-
-end_cert_vfy:
- ssl->next_state = HS_FINISHED;
-error:
- return ret;
-}
-
-#endif
diff --git a/axTLS/src/ssl/version.h b/axTLS/src/ssl/version.h
deleted file mode 100644
index cc1ddb2..0000000
--- a/axTLS/src/ssl/version.h
+++ /dev/null
@@ -1 +0,0 @@
-#define AXTLS_VERSION "1.4.4"
diff --git a/axTLS/src/ssl/x509.c b/axTLS/src/ssl/x509.c
deleted file mode 100644
index 116fa00..0000000
--- a/axTLS/src/ssl/x509.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * Copyright (c) 2007, Cameron Rich
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file x509.c
- *
- * Certificate processing.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "os_port.h"
-#include "crypto_misc.h"
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-/**
- * Retrieve the signature from a certificate.
- */
-static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
-{
- int offset = 0;
- const uint8_t *ptr = NULL;
-
- if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
- goto end_get_sig;
-
- if (asn1_sig[offset++] != ASN1_OCTET_STRING)
- goto end_get_sig;
- *len = get_asn1_length(asn1_sig, &offset);
- ptr = &asn1_sig[offset]; /* all ok */
-
-end_get_sig:
- return ptr;
-}
-
-#endif
-
-/**
- * Construct a new x509 object.
- * @return 0 if ok. < 0 if there was a problem.
- */
-int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
-{
- int begin_tbs, end_tbs;
- int ret = X509_NOT_OK, offset = 0, cert_size = 0;
- X509_CTX *x509_ctx;
- BI_CTX *bi_ctx;
- SHA1_CTX sha_ctx_fp;
-
- *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
- x509_ctx = *ctx;
-
- /* get the certificate size */
- asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE);
-
- if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
- goto end_cert;
-
- begin_tbs = offset; /* start of the tbs */
- end_tbs = begin_tbs; /* work out the end of the tbs */
- asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
-
- if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
- goto end_cert;
-
- if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */
- {
- if (asn1_version(cert, &offset, x509_ctx))
- goto end_cert;
- }
-
- if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */
- asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
- goto end_cert;
-
- /* make sure the signature is ok */
- if (asn1_signature_type(cert, &offset, x509_ctx))
- {
- ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
- goto end_cert;
- }
-
- if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) ||
- asn1_validity(cert, &offset, x509_ctx) ||
- asn1_name(cert, &offset, x509_ctx->cert_dn) ||
- asn1_public_key(cert, &offset, x509_ctx))
- {
- goto end_cert;
- }
-
- bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
-
- SHA1_Init(&sha_ctx_fp);
- SHA1_Update(&sha_ctx_fp, cert, cert_size);
- SHA1_Final(x509_ctx->sha1_fingerprint, &sha_ctx_fp);
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
- /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
- if (x509_ctx->sig_type == SIG_TYPE_MD5)
- {
- MD5_CTX md5_ctx;
- uint8_t md5_dgst[MD5_SIZE];
- MD5_Init(&md5_ctx);
- MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
- MD5_Final(md5_dgst, &md5_ctx);
- x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
- }
- else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
- {
- SHA1_CTX sha_ctx;
- uint8_t sha_dgst[SHA1_SIZE];
- SHA1_Init(&sha_ctx);
- SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
- SHA1_Final(sha_dgst, &sha_ctx);
- x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
- }
- else if (x509_ctx->sig_type == SIG_TYPE_MD2)
- {
- MD2_CTX md2_ctx;
- uint8_t md2_dgst[MD2_SIZE];
- MD2_Init(&md2_ctx);
- MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
- MD2_Final(md2_dgst, &md2_ctx);
- x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
- }
-
- if (cert[offset] == ASN1_V3_DATA)
- {
- int suboffset;
-
- ++offset;
- get_asn1_length(cert, &offset);
-
- if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0)
- {
- if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0)
- {
- int altlen;
-
- if ((altlen = asn1_next_obj(cert,
- &suboffset, ASN1_SEQUENCE)) > 0)
- {
- int endalt = suboffset + altlen;
- int totalnames = 0;
-
- while (suboffset < endalt)
- {
- int type = cert[suboffset++];
- int dnslen = get_asn1_length(cert, &suboffset);
-
- if (type == ASN1_CONTEXT_DNSNAME)
- {
- x509_ctx->subject_alt_dnsnames = (char**)
- realloc(x509_ctx->subject_alt_dnsnames,
- (totalnames + 2) * sizeof(char*));
- x509_ctx->subject_alt_dnsnames[totalnames] =
- (char*)malloc(dnslen + 1);
- x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL;
- memcpy(x509_ctx->subject_alt_dnsnames[totalnames],
- cert + suboffset, dnslen);
- x509_ctx->subject_alt_dnsnames[
- totalnames][dnslen] = 0;
- ++totalnames;
- }
-
- suboffset += dnslen;
- }
- }
- }
- }
- }
-
- offset = end_tbs; /* skip the rest of v3 data */
- if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
- asn1_signature(cert, &offset, x509_ctx))
- goto end_cert;
-#endif
- ret = X509_OK;
-end_cert:
- if (len)
- {
- *len = cert_size;
- }
-
- if (ret)
- {
-#ifdef CONFIG_SSL_FULL_MODE
- printf("Error: Invalid X509 ASN.1 file (%s)\n",
- x509_display_error(ret));
-#endif
- x509_free(x509_ctx);
- *ctx = NULL;
- }
-
- return ret;
-}
-
-/**
- * Free an X.509 object's resources.
- */
-void x509_free(X509_CTX *x509_ctx)
-{
- X509_CTX *next;
- int i;
-
- if (x509_ctx == NULL) /* if already null, then don't bother */
- return;
-
- for (i = 0; i < X509_NUM_DN_TYPES; i++)
- {
- free(x509_ctx->ca_cert_dn[i]);
- free(x509_ctx->cert_dn[i]);
- }
-
- free(x509_ctx->signature);
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
- if (x509_ctx->digest)
- {
- bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
- }
-
- if (x509_ctx->subject_alt_dnsnames)
- {
- for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i)
- free(x509_ctx->subject_alt_dnsnames[i]);
-
- free(x509_ctx->subject_alt_dnsnames);
- }
-#endif
-
- RSA_free(x509_ctx->rsa_ctx);
- next = x509_ctx->next;
- free(x509_ctx);
- x509_free(next); /* clear the chain */
-}
-
-#ifdef CONFIG_SSL_CERT_VERIFICATION
-/**
- * Take a signature and decrypt it.
- */
-static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
- bigint *modulus, bigint *pub_exp)
-{
- int i, size;
- bigint *decrypted_bi, *dat_bi;
- bigint *bir = NULL;
- uint8_t *block = (uint8_t *)alloca(sig_len);
-
- /* decrypt */
- dat_bi = bi_import(ctx, sig, sig_len);
- ctx->mod_offset = BIGINT_M_OFFSET;
-
- /* convert to a normal block */
- decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
-
- bi_export(ctx, decrypted_bi, block, sig_len);
- ctx->mod_offset = BIGINT_M_OFFSET;
-
- i = 10; /* start at the first possible non-padded byte */
- while (block[i++] && i < sig_len);
- size = sig_len - i;
-
- /* get only the bit we want */
- if (size > 0)
- {
- int len;
- const uint8_t *sig_ptr = get_signature(&block[i], &len);
-
- if (sig_ptr)
- {
- bir = bi_import(ctx, sig_ptr, len);
- }
- }
-
- /* save a few bytes of memory */
- bi_clear_cache(ctx);
- return bir;
-}
-
-/**
- * Do some basic checks on the certificate chain.
- *
- * Certificate verification consists of a number of checks:
- * - The date of the certificate is after the start date.
- * - The date of the certificate is before the finish date.
- * - A root certificate exists in the certificate store.
- * - That the certificate(s) are not self-signed.
- * - The certificate chain is valid.
- * - The signature of the certificate is valid.
- */
-int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
-{
- int ret = X509_OK, i = 0;
- bigint *cert_sig;
- X509_CTX *next_cert = NULL;
- BI_CTX *ctx = NULL;
- bigint *mod = NULL, *expn = NULL;
- int match_ca_cert = 0;
- struct timeval tv;
- uint8_t is_self_signed = 0;
-
- if (cert == NULL)
- {
- ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
- goto end_verify;
- }
-
- /* a self-signed certificate that is not in the CA store - use this
- to check the signature */
- if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
- {
- is_self_signed = 1;
- ctx = cert->rsa_ctx->bi_ctx;
- mod = cert->rsa_ctx->m;
- expn = cert->rsa_ctx->e;
- }
-
- gettimeofday(&tv, NULL);
-
- /* check the not before date */
- if (tv.tv_sec < cert->not_before)
- {
- ret = X509_VFY_ERROR_NOT_YET_VALID;
- goto end_verify;
- }
-
- /* check the not after date */
- if (tv.tv_sec > cert->not_after)
- {
- ret = X509_VFY_ERROR_EXPIRED;
- goto end_verify;
- }
-
- next_cert = cert->next;
-
- /* last cert in the chain - look for a trusted cert */
- if (next_cert == NULL)
- {
- if (ca_cert_ctx != NULL)
- {
- /* go thu the CA store */
- while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
- {
- if (asn1_compare_dn(cert->ca_cert_dn,
- ca_cert_ctx->cert[i]->cert_dn) == 0)
- {
- /* use this CA certificate for signature verification */
- match_ca_cert = 1;
- ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx;
- mod = ca_cert_ctx->cert[i]->rsa_ctx->m;
- expn = ca_cert_ctx->cert[i]->rsa_ctx->e;
- break;
- }
-
- i++;
- }
- }
-
- /* couldn't find a trusted cert (& let self-signed errors
- be returned) */
- if (!match_ca_cert && !is_self_signed)
- {
- ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
- goto end_verify;
- }
- }
- else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
- {
- /* check the chain */
- ret = X509_VFY_ERROR_INVALID_CHAIN;
- goto end_verify;
- }
- else /* use the next certificate in the chain for signature verify */
- {
- ctx = next_cert->rsa_ctx->bi_ctx;
- mod = next_cert->rsa_ctx->m;
- expn = next_cert->rsa_ctx->e;
- }
-
- /* cert is self signed */
- if (!match_ca_cert && is_self_signed)
- {
- ret = X509_VFY_ERROR_SELF_SIGNED;
- goto end_verify;
- }
-
- /* check the signature */
- cert_sig = sig_verify(ctx, cert->signature, cert->sig_len,
- bi_clone(ctx, mod), bi_clone(ctx, expn));
-
- if (cert_sig && cert->digest)
- {
- if (bi_compare(cert_sig, cert->digest) != 0)
- ret = X509_VFY_ERROR_BAD_SIGNATURE;
-
-
- bi_free(ctx, cert_sig);
- }
- else
- {
- ret = X509_VFY_ERROR_BAD_SIGNATURE;
- }
-
- if (ret)
- goto end_verify;
-
- /* go down the certificate chain using recursion. */
- if (next_cert != NULL)
- {
- ret = x509_verify(ca_cert_ctx, next_cert);
- }
-
-end_verify:
- return ret;
-}
-#endif
-
-#if defined (CONFIG_SSL_FULL_MODE)
-/**
- * Used for diagnostics.
- */
-static const char *not_part_of_cert = "<Not Part Of Certificate>";
-void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
-{
- if (cert == NULL)
- return;
-
- printf("=== CERTIFICATE ISSUED TO ===\n");
- printf("Common Name (CN):\t\t");
- printf("%s\n", cert->cert_dn[X509_COMMON_NAME] ?
- cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert);
-
- printf("Organization (O):\t\t");
- printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ?
- cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
-
- printf("Organizational Unit (OU):\t");
- printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ?
- cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
-
- printf("=== CERTIFICATE ISSUED BY ===\n");
- printf("Common Name (CN):\t\t");
- printf("%s\n", cert->ca_cert_dn[X509_COMMON_NAME] ?
- cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert);
-
- printf("Organization (O):\t\t");
- printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
- cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
-
- printf("Organizational Unit (OU):\t");
- printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ?
- cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
-
- printf("Not Before:\t\t\t%s", ctime(&cert->not_before));
- printf("Not After:\t\t\t%s", ctime(&cert->not_after));
- printf("RSA bitsize:\t\t\t%d\n", cert->rsa_ctx->num_octets*8);
- printf("Sig Type:\t\t\t");
- switch (cert->sig_type)
- {
- case SIG_TYPE_MD5:
- printf("MD5\n");
- break;
- case SIG_TYPE_SHA1:
- printf("SHA1\n");
- break;
- case SIG_TYPE_MD2:
- printf("MD2\n");
- break;
- default:
- printf("Unrecognized: %d\n", cert->sig_type);
- break;
- }
-
- if (ca_cert_ctx)
- {
- printf("Verify:\t\t\t\t%s\n",
- x509_display_error(x509_verify(ca_cert_ctx, cert)));
- }
-
-#if 0
- print_blob("Signature", cert->signature, cert->sig_len);
- bi_print("Modulus", cert->rsa_ctx->m);
- bi_print("Pub Exp", cert->rsa_ctx->e);
-#endif
-
- if (ca_cert_ctx)
- {
- x509_print(cert->next, ca_cert_ctx);
- }
-
- TTY_FLUSH();
-}
-
-const char * x509_display_error(int error)
-{
- switch (error)
- {
- case X509_OK:
- return "Certificate verify successful";
-
- case X509_NOT_OK:
- return "X509 not ok";
-
- case X509_VFY_ERROR_NO_TRUSTED_CERT:
- return "No trusted cert is available";
-
- case X509_VFY_ERROR_BAD_SIGNATURE:
- return "Bad signature";
-
- case X509_VFY_ERROR_NOT_YET_VALID:
- return "Cert is not yet valid";
-
- case X509_VFY_ERROR_EXPIRED:
- return "Cert has expired";
-
- case X509_VFY_ERROR_SELF_SIGNED:
- return "Cert is self-signed";
-
- case X509_VFY_ERROR_INVALID_CHAIN:
- return "Chain is invalid (check order of certs)";
-
- case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
- return "Unsupported digest";
-
- case X509_INVALID_PRIV_KEY:
- return "Invalid private key";
-
- default:
- return "Unknown";
- }
-}
-#endif /* CONFIG_SSL_FULL_MODE */
-
diff --git a/axTLS/src/www/index.html b/axTLS/src/www/index.html
deleted file mode 100644
index 7055794..0000000
--- a/axTLS/src/www/index.html
+++ /dev/null
@@ -1,7106 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<script type="text/javascript">
-//<![CDATA[
-var version = {major: 2, minor: 1, revision: 3, date: new Date("Nov 3, 2006"), extensions: {}};
-//]]>
-</script>
-<!--
-TiddlyWiki 2.1.3 by Jeremy Ruston, (jeremy [at] osmosoft [dot] com)
-
-Copyright (c) Osmosoft Limited 2004-2006
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this
-list of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-Neither the name of the Osmosoft Limited nor the names of its contributors may be
-used to endorse or promote products derived from this software without specific
-prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
--->
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
-<!--PRE-HEAD-START-->
-<!--{{{-->
-<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
-<!--}}}-->
-<!--PRE-HEAD-END-->
-<title> axTLS Embedded SSL - changes, notes and errata </title>
-<script type="text/javascript">
-//<![CDATA[
-// ---------------------------------------------------------------------------------
-// Configuration repository
-// ---------------------------------------------------------------------------------
-
-// Miscellaneous options
-var config = {
- numRssItems: 20, // Number of items in the RSS feed
- animFast: 0.12, // Speed for animations (lower == slower)
- animSlow: 0.01, // Speed for EasterEgg animations
- cascadeFast: 20, // Speed for cascade animations (higher == slower)
- cascadeSlow: 60, // Speed for EasterEgg cascade animations
- cascadeDepth: 5, // Depth of cascade animation
- displayStartupTime: false // Whether to display startup time
- };
-
-// Messages
-config.messages = {
- messageClose: {},
- dates: {}
-};
-
-// Options that can be set in the options panel and/or cookies
-config.options = {
- chkRegExpSearch: false,
- chkCaseSensitiveSearch: false,
- chkAnimate: true,
- chkSaveBackups: true,
- chkAutoSave: false,
- chkGenerateAnRssFeed: false,
- chkSaveEmptyTemplate: false,
- chkOpenInNewWindow: true,
- chkToggleLinks: false,
- chkHttpReadOnly: true,
- chkForceMinorUpdate: false,
- chkConfirmDelete: true,
- chkInsertTabs: false,
- txtBackupFolder: "",
- txtMainTab: "tabTimeline",
- txtMoreTab: "moreTabAll",
- txtMaxEditRows: "30"
- };
-
-// List of notification functions to be called when certain tiddlers are changed or deleted
-config.notifyTiddlers = [
- {name: "StyleSheetLayout", notify: refreshStyles},
- {name: "StyleSheetColors", notify: refreshStyles},
- {name: "StyleSheet", notify: refreshStyles},
- {name: "StyleSheetPrint", notify: refreshStyles},
- {name: "PageTemplate", notify: refreshPageTemplate},
- {name: "SiteTitle", notify: refreshPageTitle},
- {name: "SiteSubtitle", notify: refreshPageTitle},
- {name: "ColorPalette", notify: refreshColorPalette},
- {name: null, notify: refreshDisplay}
- ];
-
-// Default tiddler templates
-var DEFAULT_VIEW_TEMPLATE = 1;
-var DEFAULT_EDIT_TEMPLATE = 2;
-config.tiddlerTemplates = {
- 1: "ViewTemplate",
- 2: "EditTemplate"
- };
-
-// More messages (rather a legacy layout that shouldn't really be like this)
-config.views = {
- wikified: {
- tag: {}
- },
- editor: {
- tagChooser: {}
- }
- };
-
-// Macros; each has a 'handler' member that is inserted later
-config.macros = {
- today: {},
- version: {},
- search: {sizeTextbox: 15},
- tiddler: {},
- tag: {},
- tags: {},
- tagging: {},
- timeline: {},
- allTags: {},
- list: {
- all: {},
- missing: {},
- orphans: {},
- shadowed: {}
- },
- closeAll: {},
- permaview: {},
- saveChanges: {},
- slider: {},
- option: {},
- newTiddler: {},
- newJournal: {},
- sparkline: {},
- tabs: {},
- gradient: {},
- message: {},
- view: {},
- edit: {},
- tagChooser: {},
- toolbar: {},
- br: {},
- plugins: {},
- refreshDisplay: {},
- importTiddlers: {}
- };
-
-// Commands supported by the toolbar macro
-config.commands = {
- closeTiddler: {},
- closeOthers: {},
- editTiddler: {},
- saveTiddler: {hideReadOnly: true},
- cancelTiddler: {},
- deleteTiddler: {hideReadOnly: true},
- permalink: {},
- references: {},
- jump: {}
- };
-
-// Browser detection... In a very few places, there's nothing else for it but to
-// know what browser we're using.
-config.userAgent = navigator.userAgent.toLowerCase();
-config.browser = {
- isIE: config.userAgent.indexOf("msie") != -1 && config.userAgent.indexOf("opera") == -1,
- ieVersion: /MSIE (\d.\d)/i.exec(config.userAgent), // config.browser.ieVersion[1], if it exists, will be the IE version string, eg "6.0"
- isSafari: config.userAgent.indexOf("applewebkit") != -1,
- isBadSafari: !((new RegExp("[\u0150\u0170]","g")).test("\u0150")),
- firefoxDate: /Gecko\/(\d{8})/i.exec(config.userAgent), // config.browser.firefoxDate[1], if it exists, will be Firefox release date as "YYYYMMDD"
- isOpera: config.userAgent.indexOf("opera") != -1,
- isLinux: config.userAgent.indexOf("linux") != -1,
- isUnix: config.userAgent.indexOf("x11") != -1,
- isMac: config.userAgent.indexOf("mac") != -1,
- isWindows: config.userAgent.indexOf("win") != -1
- };
-
-// Basic regular expressions
-config.textPrimitives = {
- upperLetter: "[A-Z\u00c0-\u00de\u0150\u0170]",
- lowerLetter: "[a-z0-9_\\-\u00df-\u00ff\u0151\u0171]",
- anyLetter: "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]",
- anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]"
- };
-if(config.browser.isBadSafari)
- config.textPrimitives = {
- upperLetter: "[A-Z\u00c0-\u00de]",
- lowerLetter: "[a-z0-9_\\-\u00df-\u00ff]",
- anyLetter: "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff]",
- anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff]"
- }
-config.textPrimitives.sliceSeparator = "::";
-config.textPrimitives.urlPattern = "[a-z]{3,8}:[^\\s:'\"][^\\s'\"]*(?:/|\\b)";
-config.textPrimitives.unWikiLink = "~";
-config.textPrimitives.wikiLink = "(?:(?:" + config.textPrimitives.upperLetter + "+" +
- config.textPrimitives.lowerLetter + "+" +
- config.textPrimitives.upperLetter +
- config.textPrimitives.anyLetter + "*)|(?:" +
- config.textPrimitives.upperLetter + "{2,}" +
- config.textPrimitives.lowerLetter + "+))";
-
-config.textPrimitives.cssLookahead = "(?:(" + config.textPrimitives.anyLetter + "+)\\(([^\\)\\|\\n]+)(?:\\):))|(?:(" + config.textPrimitives.anyLetter + "+):([^;\\|\\n]+);)";
-config.textPrimitives.cssLookaheadRegExp = new RegExp(config.textPrimitives.cssLookahead,"mg");
-
-config.textPrimitives.brackettedLink = "\\[\\[([^\\]]+)\\]\\]";
-config.textPrimitives.titledBrackettedLink = "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+)\\]\\]";
-config.textPrimitives.tiddlerForcedLinkRegExp = new RegExp("(?:" + config.textPrimitives.titledBrackettedLink + ")|(?:" +
- config.textPrimitives.brackettedLink + ")|(?:" +
- config.textPrimitives.urlPattern + ")","mg");
-config.textPrimitives.tiddlerAnyLinkRegExp = new RegExp("("+ config.textPrimitives.wikiLink + ")|(?:" +
- config.textPrimitives.titledBrackettedLink + ")|(?:" +
- config.textPrimitives.brackettedLink + ")|(?:" +
- config.textPrimitives.urlPattern + ")","mg");
-
-// ---------------------------------------------------------------------------------
-// Shadow tiddlers
-// ---------------------------------------------------------------------------------
-
-config.shadowTiddlers = {
- ColorPalette: "Background: #fff\n" +
- "Foreground: #000\n" +
- "PrimaryPale: #8cf\n" +
- "PrimaryLight: #18f\n" +
- "PrimaryMid: #04b\n" +
- "PrimaryDark: #014\n" +
- "SecondaryPale: #ffc\n" +
- "SecondaryLight: #fe8\n" +
- "SecondaryMid: #db4\n" +
- "SecondaryDark: #841\n" +
- "TertiaryPale: #eee\n" +
- "TertiaryLight: #ccc\n" +
- "TertiaryMid: #999\n" +
- "TertiaryDark: #666\n" +
- "Error: #f88\n",
- StyleSheet: "",
- StyleSheetColors: "/*{{{*/\nbody {\n background: [[ColorPalette::Background]];\n color: [[ColorPalette::Foreground]];\n}\n\na{\n color: [[ColorPalette::PrimaryMid]];\n}\n\na:hover{\n background: [[ColorPalette::PrimaryMid]];\n color: [[ColorPalette::Background]];\n}\n\na img{\n border: 0;\n}\n\nh1,h2,h3,h4,h5 {\n color: [[ColorPalette::SecondaryDark]];\n background: [[ColorPalette::PrimaryPale]];\n}\n\n.button {\n color: [[ColorPalette::PrimaryDark]];\n border: 1px solid [[ColorPalette::Background]];\n}\n\n.button:hover {\n color: [[ColorPalette::PrimaryDark]];\n background: [[ColorPalette::SecondaryLight]];\n border-color: [[ColorPalette::SecondaryMid]];\n}\n\n.button:active {\n color: [[ColorPalette::Background]];\n background: [[ColorPalette::SecondaryMid]];\n border: 1px solid [[ColorPalette::SecondaryDark]];\n}\n\n.header {\n background: [[ColorPalette::PrimaryMid]];\n}\n\n.headerShadow {\n color: [[ColorPalette::Foreground]];\n}\n\n.headerShadow a {\n font-weight: normal;\n color: [[ColorPalette::Foreground]];\n}\n\n.headerForeground {\n color: [[ColorPalette::Background]];\n}\n\n.headerForeground a {\n font-weight: normal;\n color: [[ColorPalette::PrimaryPale]];\n}\n\n.tabSelected{\n color: [[ColorPalette::PrimaryDark]];\n background: [[ColorPalette::TertiaryPale]];\n border-left: 1px solid [[ColorPalette::TertiaryLight]];\n border-top: 1px solid [[ColorPalette::TertiaryLight]];\n border-right: 1px solid [[ColorPalette::TertiaryLight]];\n}\n\n.tabUnselected {\n color: [[ColorPalette::Background]];\n background: [[ColorPalette::TertiaryMid]];\n}\n\n.tabContents {\n color: [[ColorPalette::PrimaryDark]];\n background: [[ColorPalette::TertiaryPale]];\n border: 1px solid [[ColorPalette::TertiaryLight]];\n}\n\n.tabContents .button {\n border: 0;}\n\n#sidebar {\n}\n\n#sidebarOptions input {\n border: 1px solid [[ColorPalette::PrimaryMid]];\n}\n\n#sidebarOptions .sliderPanel {\n background: [[ColorPalette::PrimaryPale]];\n}\n\n#sidebarOptions .sliderPanel a {\n border: none;\n color: [[ColorPalette::PrimaryMid]];\n}\n\n#sidebarOptions .sliderPanel a:hover {\n color: [[ColorPalette::Background]];\n background: [[ColorPalette::PrimaryMid]];\n}\n\n#sidebarOptions .sliderPanel a:active {\n color: [[ColorPalette::PrimaryMid]];\n background: [[ColorPalette::Background]];\n}\n\n.wizard {\n background: [[ColorPalette::SecondaryLight]];\n border-top: 1px solid [[ColorPalette::SecondaryMid]];\n border-left: 1px solid [[ColorPalette::SecondaryMid]];\n}\n\n.wizard h1 {\n color: [[ColorPalette::SecondaryDark]];\n}\n\n.wizard h2 {\n color: [[ColorPalette::Foreground]];\n}\n\n.wizardStep {\n background: [[ColorPalette::Background]];\n border-top: 1px solid [[ColorPalette::SecondaryMid]];\n border-bottom: 1px solid [[ColorPalette::SecondaryMid]];\n border-left: 1px solid [[ColorPalette::SecondaryMid]];\n}\n\n.wizard .button {\n color: [[ColorPalette::Background]];\n background: [[ColorPalette::PrimaryMid]];\n border-top: 1px solid [[ColorPalette::PrimaryLight]];\n border-right: 1px solid [[ColorPalette::PrimaryDark]];\n border-bottom: 1px solid [[ColorPalette::PrimaryDark]];\n border-left: 1px solid [[ColorPalette::PrimaryLight]];\n}\n\n.wizard .button:hover {\n color: [[ColorPalette::PrimaryLight]];\n background: [[ColorPalette::PrimaryDark]];\n border-color: [[ColorPalette::PrimaryLight]];\n}\n\n.wizard .button:active {\n color: [[ColorPalette::Background]];\n background: [[ColorPalette::PrimaryMid]];\n border-top: 1px solid [[ColorPalette::PrimaryLight]];\n border-right: 1px solid [[ColorPalette::PrimaryDark]];\n border-bottom: 1px solid [[ColorPalette::PrimaryDark]];\n border-left: 1px solid [[ColorPalette::PrimaryLight]];\n}\n\n#messageArea {\n border: 1px solid [[ColorPalette::SecondaryDark]];\n background: [[ColorPalette::SecondaryMid]];\n color: [[ColorPalette::PrimaryDark]];\n}\n\n#messageArea .button {\n padding: 0.2em 0.2em 0.2em 0.2em;\n color: [[ColorPalette::PrimaryDark]];\n background: [[ColorPalette::Background]];\n}\n\n.popup {\n background: [[ColorPalette::PrimaryLight]];\n border: 1px solid [[ColorPalette::PrimaryMid]];\n}\n\n.popup hr {\n color: [[ColorPalette::PrimaryDark]];\n background: [[ColorPalette::PrimaryDark]];\n border-bottom: 1px;\n}\n\n.listBreak div{\n border-bottom: 1px solid [[ColorPalette::PrimaryDark]];\n}\n\n.popup li.disabled {\n color: [[ColorPalette::PrimaryMid]];\n}\n\n.popup li a, .popup li a:visited {\n color: [[ColorPalette::TertiaryPale]];\n border: none;\n}\n\n.popup li a:hover {\n background: [[ColorPalette::PrimaryDark]];\n color: [[ColorPalette::Background]];\n border: none;\n}\n\n.tiddler .defaultCommand {\n font-weight: bold;\n}\n\n.shadow .title {\n color: [[ColorPalette::TertiaryDark]];\n}\n\n.title {\n color: [[ColorPalette::SecondaryDark]];\n}\n\n.subtitle {\n color: [[ColorPalette::TertiaryDark]];\n}\n\n.toolbar {\n color: [[ColorPalette::PrimaryMid]];\n}\n\n.tagging, .tagged {\n border: 1px solid [[ColorPalette::TertiaryPale]];\n background-color: [[ColorPalette::TertiaryPale]];\n}\n\n.selected .tagging, .selected .tagged {\n background-color: [[ColorPalette::TertiaryLight]];\n border: 1px solid [[ColorPalette::TertiaryMid]];\n}\n\n.tagging .listTitle, .tagged .listTitle {\n color: [[ColorPalette::PrimaryDark]];\n}\n\n.tagging .button, .tagged .button {\n border: none;\n}\n\n.footer {\n color: [[ColorPalette::TertiaryLight]];\n}\n\n.selected .footer {\n color: [[ColorPalette::TertiaryMid]];\n}\n\n.sparkline {\n background: [[ColorPalette::PrimaryPale]];\n border: 0;\n}\n\n.sparktick {\n background: [[ColorPalette::PrimaryDark]];\n}\n\n.error, .errorButton {\n color: [[ColorPalette::Foreground]];\n background: [[ColorPalette::Error]];\n}\n\n.warning {\n color: [[ColorPalette::Foreground]];\n background: [[ColorPalette::SecondaryPale]];\n}\n\n.cascade {\n background: [[ColorPalette::TertiaryPale]];\n color: [[ColorPalette::TertiaryMid]];\n border: 1px solid [[ColorPalette::TertiaryMid]];\n}\n\n.imageLink, #displayArea .imageLink {\n background: transparent;\n}\n\n.viewer .listTitle {list-style-type: none; margin-left: -2em;}\n\n.viewer .button {\n border: 1px solid [[ColorPalette::SecondaryMid]];\n}\n\n.viewer blockquote {\n border-left: 3px solid [[ColorPalette::TertiaryDark]];\n}\n\n.viewer table {\n border: 2px solid [[ColorPalette::TertiaryDark]];\n}\n\n.viewer th, thead td {\n background: [[ColorPalette::SecondaryMid]];\n border: 1px solid [[ColorPalette::TertiaryDark]];\n color: [[ColorPalette::Background]];\n}\n\n.viewer td, .viewer tr {\n border: 1px solid [[ColorPalette::TertiaryDark]];\n}\n\n.viewer pre {\n border: 1px solid [[ColorPalette::SecondaryLight]];\n background: [[ColorPalette::SecondaryPale]];\n}\n\n.viewer code {\n color: [[ColorPalette::SecondaryDark]];\n}\n\n.viewer hr {\n border: 0;\n border-top: dashed 1px [[ColorPalette::TertiaryDark]];\n color: [[ColorPalette::TertiaryDark]];\n}\n\n.highlight, .marked {\n background: [[ColorPalette::SecondaryLight]];\n}\n\n.editor input {\n border: 1px solid [[ColorPalette::PrimaryMid]];\n}\n\n.editor textarea {\n border: 1px solid [[ColorPalette::PrimaryMid]];\n width: 100%;\n}\n\n.editorFooter {\n color: [[ColorPalette::TertiaryMid]];\n}\n\n/*}}}*/",
- StyleSheetLayout: "/*{{{*/\n* html .tiddler {\n height: 1%;\n}\n\nbody {\n font-size: .75em;\n font-family: arial,helvetica;\n margin: 0;\n padding: 0;\n}\n\nh1,h2,h3,h4,h5 {\n font-weight: bold;\n text-decoration: none;\n padding-left: 0.4em;\n}\n\nh1 {font-size: 1.35em;}\nh2 {font-size: 1.25em;}\nh3 {font-size: 1.1em;}\nh4 {font-size: 1em;}\nh5 {font-size: .9em;}\n\nhr {\n height: 1px;\n}\n\na{\n text-decoration: none;\n}\n\ndt {font-weight: bold;}\n\nol { list-style-type: decimal }\nol ol { list-style-type: lower-alpha }\nol ol ol { list-style-type: lower-roman }\nol ol ol ol { list-style-type: decimal }\nol ol ol ol ol { list-style-type: lower-alpha }\nol ol ol ol ol ol { list-style-type: lower-roman }\nol ol ol ol ol ol ol { list-style-type: decimal }\n\n.txtOptionInput {\n width: 11em;\n}\n\n#contentWrapper .chkOptionInput {\n border: 0;\n}\n\n.externalLink {\n text-decoration: underline;\n}\n\n.indent {margin-left:3em;}\n.outdent {margin-left:3em; text-indent:-3em;}\ncode.escaped {white-space:nowrap;}\n\n.tiddlyLinkExisting {\n font-weight: bold;\n}\n\n.tiddlyLinkNonExisting {\n font-style: italic;\n}\n\n/* the 'a' is required for IE, otherwise it renders the whole tiddler a bold */\na.tiddlyLinkNonExisting.shadow {\n font-weight: bold;\n}\n\n#mainMenu .tiddlyLinkExisting, \n#mainMenu .tiddlyLinkNonExisting,\n#sidebarTabs .tiddlyLinkNonExisting{\n font-weight: normal;\n font-style: normal;\n}\n\n#sidebarTabs .tiddlyLinkExisting {\n font-weight: bold;\n font-style: normal;\n}\n\n.header {\n position: relative;\n}\n\n.header a:hover {\n background: transparent;\n}\n\n.headerShadow {\n position: relative;\n padding: 4.5em 0em 1em 1em;\n left: -1px;\n top: -1px;\n}\n\n.headerForeground {\n position: absolute;\n padding: 4.5em 0em 1em 1em;\n left: 0px;\n top: 0px;\n}\n\n.siteTitle {\n font-size: 3em;\n}\n\n.siteSubtitle {\n font-size: 1.2em;\n}\n\n#mainMenu {\n position: absolute;\n left: 0;\n width: 10em;\n text-align: right;\n line-height: 1.6em;\n padding: 1.5em 0.5em 0.5em 0.5em;\n font-size: 1.1em;\n}\n\n#sidebar {\n position: absolute;\n right: 3px;\n width: 16em;\n font-size: .9em;\n}\n\n#sidebarOptions {\n padding-top: 0.3em;\n}\n\n#sidebarOptions a {\n margin: 0em 0.2em;\n padding: 0.2em 0.3em;\n display: block;\n}\n\n#sidebarOptions input {\n margin: 0.4em 0.5em;\n}\n\n#sidebarOptions .sliderPanel {\n margin-left: 1em;\n padding: 0.5em;\n font-size: .85em;\n}\n\n#sidebarOptions .sliderPanel a {\n font-weight: bold;\n display: inline;\n padding: 0;\n}\n\n#sidebarOptions .sliderPanel input {\n margin: 0 0 .3em 0;\n}\n\n#sidebarTabs .tabContents {\n width: 15em;\n overflow: hidden;\n}\n\n.wizard {\n padding: 0.1em 0em 0em 2em;\n}\n\n.wizard h1 {\n font-size: 2em;\n font-weight: bold;\n background: none;\n padding: 0em 0em 0em 0em;\n margin: 0.4em 0em 0.2em 0em;\n}\n\n.wizard h2 {\n font-size: 1.2em;\n font-weight: bold;\n background: none;\n padding: 0em 0em 0em 0em;\n margin: 0.2em 0em 0.2em 0em;\n}\n\n.wizardStep {\n padding: 1em 1em 1em 1em;\n}\n\n.wizard .button {\n margin: 0.5em 0em 0em 0em;\n font-size: 1.2em;\n}\n\n#messageArea {\nposition:absolute; top:0; right:0; margin: 0.5em; padding: 0.5em;\n}\n\n*[id='messageArea'] {\nposition:fixed !important; z-index:99;}\n\n.messageToolbar {\ndisplay: block;\ntext-align: right;\n}\n\n#messageArea a{\n text-decoration: underline;\n}\n\n.popup {\n font-size: .9em;\n padding: 0.2em;\n list-style: none;\n margin: 0;\n}\n\n.popup hr {\n display: block;\n height: 1px;\n width: auto;\n padding: 0;\n margin: 0.2em 0em;\n}\n\n.listBreak {\n font-size: 1px;\n line-height: 1px;\n}\n\n.listBreak div {\n margin: 2px 0;\n}\n\n.popup li.disabled {\n padding: 0.2em;\n}\n\n.popup li a{\n display: block;\n padding: 0.2em;\n}\n\n.tabset {\n padding: 1em 0em 0em 0.5em;\n}\n\n.tab {\n margin: 0em 0em 0em 0.25em;\n padding: 2px;\n}\n\n.tabContents {\n padding: 0.5em;\n}\n\n.tabContents ul, .tabContents ol {\n margin: 0;\n padding: 0;\n}\n\n.txtMainTab .tabContents li {\n list-style: none;\n}\n\n.tabContents li.listLink {\n margin-left: .75em;\n}\n\n#displayArea {\n margin: 1em 17em 0em 14em;\n}\n\n\n.toolbar {\n text-align: right;\n font-size: .9em;\n visibility: hidden;\n}\n\n.selected .toolbar {\n visibility: visible;\n}\n\n.tiddler {\n padding: 1em 1em 0em 1em;\n}\n\n.missing .viewer,.missing .title {\n font-style: italic;\n}\n\n.title {\n font-size: 1.6em;\n font-weight: bold;\n}\n\n.missing .subtitle {\n display: none;\n}\n\n.subtitle {\n font-size: 1.1em;\n}\n\n.tiddler .button {\n padding: 0.2em 0.4em;\n}\n\n.tagging {\nmargin: 0.5em 0.5em 0.5em 0;\nfloat: left;\ndisplay: none;\n}\n\n.isTag .tagging {\ndisplay: block;\n}\n\n.tagged {\nmargin: 0.5em;\nfloat: right;\n}\n\n.tagging, .tagged {\nfont-size: 0.9em;\npadding: 0.25em;\n}\n\n.tagging ul, .tagged ul {\nlist-style: none;margin: 0.25em;\npadding: 0;\n}\n\n.tagClear {\nclear: both;\n}\n\n.footer {\n font-size: .9em;\n}\n\n.footer li {\ndisplay: inline;\n}\n\n* html .viewer pre {\n width: 99%;\n padding: 0 0 1em 0;\n}\n\n.viewer {\n line-height: 1.4em;\n padding-top: 0.5em;\n}\n\n.viewer .button {\n margin: 0em 0.25em;\n padding: 0em 0.25em;\n}\n\n.viewer blockquote {\n line-height: 1.5em;\n padding-left: 0.8em;\n margin-left: 2.5em;\n}\n\n.viewer ul, .viewer ol{\n margin-left: 0.5em;\n padding-left: 1.5em;\n}\n\n.viewer table {\n border-collapse: collapse;\n margin: 0.8em 1.0em;\n}\n\n.viewer th, .viewer td, .viewer tr,.viewer caption{\n padding: 3px;\n}\n\n.viewer table.listView {\n font-size: 0.85em;\n margin: 0.8em 1.0em;\n}\n\n.viewer table.listView th, .viewer table.listView td, .viewer table.listView tr {\n padding: 0px 3px 0px 3px;\n}\n\n.viewer pre {\n padding: 0.5em;\n margin-left: 0.5em;\n font-size: 1.2em;\n line-height: 1.4em;\n overflow: auto;\n}\n\n.viewer code {\n font-size: 1.2em;\n line-height: 1.4em;\n}\n\n.editor {\nfont-size: 1.1em;\n}\n\n.editor input, .editor textarea {\n display: block;\n width: 100%;\n font: inherit;\n}\n\n.editorFooter {\n padding: 0.25em 0em;\n font-size: .9em;\n}\n\n.editorFooter .button {\npadding-top: 0px; padding-bottom: 0px;}\n\n.fieldsetFix {border: 0;\npadding: 0;\nmargin: 1px 0px 1px 0px;\n}\n\n.sparkline {\n line-height: 1em;\n}\n\n.sparktick {\n outline: 0;\n}\n\n.zoomer {\n font-size: 1.1em;\n position: absolute;\n padding: 1em;\n}\n\n.cascade {\n font-size: 1.1em;\n position: absolute;\n overflow: hidden;\n}\n/*}}}*/",
- StyleSheetPrint: "/*{{{*/\n@media print {\n#mainMenu, #sidebar, #messageArea, .toolbar {display: none ! important;}\n#displayArea {margin: 1em 1em 0em 1em;}\n/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */\nnoscript {display:none;}\n}\n/*}}}*/",
- PageTemplate: "<!--{{{-->\n<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>\n<div class='headerShadow'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;\n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n<div class='headerForeground'>\n<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;\n<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>\n</div>\n</div>\n<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>\n<div id='sidebar'>\n<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>\n<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>\n</div>\n<div id='displayArea'>\n<div id='messageArea'></div>\n<div id='tiddlerDisplay'></div>\n</div>\n<!--}}}-->",
- ViewTemplate: "<!--{{{-->\n<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date [[DD MMM YYYY]]'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date [[DD MMM YYYY]]'></span>)</div>\n<div class='tagging' macro='tagging'></div>\n<div class='tagged' macro='tags'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div>\n<!--}}}-->",
- EditTemplate: "<!--{{{-->\n<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>\n<div class='title' macro='view title'></div>\n<div class='editor' macro='edit title'></div>\n<div class='editor' macro='edit text'></div>\n<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>\n<!--}}}-->",
- MarkupPreHead: "<!--{{{-->\n<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>\n<!--}}}-->",
- MarkupPostHead: "",
- MarkupPreBody: "",
- MarkupPostBody: ""
- };
-
-// ---------------------------------------------------------------------------------
-// Translateable strings
-// ---------------------------------------------------------------------------------
-
-// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone
-
-merge(config.options,{
- txtUserName: "YourName"});
-
-merge(config.messages,{
- customConfigError: "Problems were encountered loading plugins. See PluginManager for details",
- pluginError: "Error: %0",
- pluginDisabled: "Not executed because disabled via 'systemConfigDisable' tag",
- pluginForced: "Executed because forced via 'systemConfigForce' tag",
- pluginVersionError: "Not executed because this plugin needs a newer version of TiddlyWiki",
- nothingSelected: "Nothing is selected. You must select one or more items first",
- savedSnapshotError: "It appears that this TiddlyWiki has been incorrectly saved. Please see http://www.tiddlywiki.com/#DownloadSoftware for details",
- subtitleUnknown: "(unknown)",
- undefinedTiddlerToolTip: "The tiddler '%0' doesn't yet exist",
- shadowedTiddlerToolTip: "The tiddler '%0' doesn't yet exist, but has a pre-defined shadow value",
- tiddlerLinkTooltip: "%0 - %1, %2",
- externalLinkTooltip: "External link to %0",
- noTags: "There are no tagged tiddlers",
- notFileUrlError: "You need to save this TiddlyWiki to a file before you can save changes",
- cantSaveError: "It's not possible to save changes. This could be because your browser doesn't support saving (instead, use FireFox if you can), or because the pathname to your TiddlyWiki file contains illegal characters",
- invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
- backupSaved: "Backup saved",
- backupFailed: "Failed to save backup file",
- rssSaved: "RSS feed saved",
- rssFailed: "Failed to save RSS feed file",
- emptySaved: "Empty template saved",
- emptyFailed: "Failed to save empty template file",
- mainSaved: "Main TiddlyWiki file saved",
- mainFailed: "Failed to save main TiddlyWiki file. Your changes have not been saved",
- macroError: "Error in macro <<%0>>",
- macroErrorDetails: "Error while executing macro <<%0>>:\n%1",
- missingMacro: "No such macro",
- overwriteWarning: "A tiddler named '%0' already exists. Choose OK to overwrite it",
- unsavedChangesWarning: "WARNING! There are unsaved changes in TiddlyWiki\n\nChoose OK to save\nChoose CANCEL to discard",
- confirmExit: "--------------------------------\n\nThere are unsaved changes in TiddlyWiki. If you continue you will lose those changes\n\n--------------------------------",
- saveInstructions: "SaveChanges",
- unsupportedTWFormat: "Unsupported TiddlyWiki format '%0'",
- tiddlerSaveError: "Error when saving tiddler '%0'",
- tiddlerLoadError: "Error when loading tiddler '%0'",
- wrongSaveFormat: "Cannot save with storage format '%0'. Using standard format for save.",
- invalidFieldName: "Invalid field name %0",
- fieldCannotBeChanged: "Field '%0' cannot be changed"});
-
-merge(config.messages.messageClose,{
- text: "close",
- tooltip: "close this message area"});
-
-config.messages.dates.months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November","December"];
-config.messages.dates.days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
-config.messages.dates.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
-config.messages.dates.shortDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
-
-merge(config.views.wikified.tag,{
- labelNoTags: "no tags",
- labelTags: "tags: ",
- openTag: "Open tag '%0'",
- tooltip: "Show tiddlers tagged with '%0'",
- openAllText: "Open all",
- openAllTooltip: "Open all of these tiddlers",
- popupNone: "No other tiddlers tagged with '%0'"});
-
-merge(config.views.wikified,{
- defaultText: "The tiddler '%0' doesn't yet exist. Double-click to create it",
- defaultModifier: "(missing)",
- shadowModifier: "(built-in shadow tiddler)",
- createdPrompt: "created"});
-
-merge(config.views.editor,{
- tagPrompt: "Type tags separated with spaces, [[use double square brackets]] if necessary, or add existing",
- defaultText: "Type the text for '%0'"});
-
-merge(config.views.editor.tagChooser,{
- text: "tags",
- tooltip: "Choose existing tags to add to this tiddler",
- popupNone: "There are no tags defined",
- tagTooltip: "Add the tag '%0'"});
-
-merge(config.macros.search,{
- label: "search",
- prompt: "Search this TiddlyWiki",
- accessKey: "F",
- successMsg: "%0 tiddlers found matching %1",
- failureMsg: "No tiddlers found matching %0"});
-
-merge(config.macros.tagging,{
- label: "tagging: ",
- labelNotTag: "not tagging",
- tooltip: "List of tiddlers tagged with '%0'"});
-
-merge(config.macros.timeline,{
- dateFormat: "DD MMM YYYY"});
-
-merge(config.macros.allTags,{
- tooltip: "Show tiddlers tagged with '%0'",
- noTags: "There are no tagged tiddlers"});
-
-config.macros.list.all.prompt = "All tiddlers in alphabetical order";
-config.macros.list.missing.prompt = "Tiddlers that have links to them but are not defined";
-config.macros.list.orphans.prompt = "Tiddlers that are not linked to from any other tiddlers";
-config.macros.list.shadowed.prompt = "Tiddlers shadowed with default contents";
-
-merge(config.macros.closeAll,{
- label: "close all",
- prompt: "Close all displayed tiddlers (except any that are being edited)"});
-
-merge(config.macros.permaview,{
- label: "permaview",
- prompt: "Link to an URL that retrieves all the currently displayed tiddlers"});
-
-merge(config.macros.saveChanges,{
- label: "save changes",
- prompt: "Save all tiddlers to create a new TiddlyWiki",
- accessKey: "S"});
-
-merge(config.macros.newTiddler,{
- label: "new tiddler",
- prompt: "Create a new tiddler",
- title: "New Tiddler",
- accessKey: "N"});
-
-merge(config.macros.newJournal,{
- label: "new journal",
- prompt: "Create a new tiddler from the current date and time",
- accessKey: "J"});
-
-merge(config.macros.plugins,{
- skippedText: "(This plugin has not been executed because it was added since startup)",
- noPluginText: "There are no plugins installed",
- confirmDeleteText: "Are you sure you want to delete these tiddlers:\n\n%0",
- listViewTemplate : {
- columns: [
- {name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
- {name: 'Title', field: 'title', tiddlerLink: 'title', title: "Title", type: 'TiddlerLink'},
- {name: 'Forced', field: 'forced', title: "Forced", tag: 'systemConfigForce', type: 'TagCheckbox'},
- {name: 'Disabled', field: 'disabled', title: "Disabled", tag: 'systemConfigDisable', type: 'TagCheckbox'},
- {name: 'Executed', field: 'executed', title: "Loaded", type: 'Boolean', trueText: "Yes", falseText: "No"},
- {name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Error", falseText: "OK"},
- {name: 'Log', field: 'log', title: "Log", type: 'StringList'}
- ],
- rowClasses: [
- {className: 'error', field: 'error'},
- {className: 'warning', field: 'warning'}
- ],
- actions: [
- {caption: "More actions...", name: ''},
- {caption: "Remove systemConfig tag", name: 'remove'},
- {caption: "Delete these tiddlers forever", name: 'delete'}
- ]}
- });
-
-merge(config.macros.refreshDisplay,{
- label: "refresh",
- prompt: "Redraw the entire TiddlyWiki display"
- });
-
-merge(config.macros.importTiddlers,{
- readOnlyWarning: "You cannot import tiddlers into a read-only TiddlyWiki. Try opening the TiddlyWiki file from a file:// URL",
- defaultPath: "http://www.tiddlywiki.com/index.html",
- fetchLabel: "fetch",
- fetchPrompt: "Fetch the tiddlywiki file",
- fetchError: "There were problems fetching the tiddlywiki file",
- confirmOverwriteText: "Are you sure you want to overwrite these tiddlers:\n\n%0",
- wizardTitle: "Import tiddlers from another TiddlyWiki file",
- step1: "Step 1: Locate the TiddlyWiki file",
- step1prompt: "Enter the URL or pathname here: ",
- step1promptFile: "...or browse for a file: ",
- step1promptFeeds: "...or select a pre-defined feed: ",
- step1feedPrompt: "Choose...",
- step2: "Step 2: Loading TiddlyWiki file",
- step2Text: "Please wait while the file is loaded from: %0",
- step3: "Step 3: Choose the tiddlers to import",
- step4: "%0 tiddler(s) imported",
- step5: "Done",
- listViewTemplate: {
- columns: [
- {name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
- {name: 'Title', field: 'title', title: "Title", type: 'String'},
- {name: 'Snippet', field: 'text', title: "Snippet", type: 'String'},
- {name: 'Tags', field: 'tags', title: "Tags", type: 'Tags'}
- ],
- rowClasses: [
- ],
- actions: [
- {caption: "More actions...", name: ''},
- {caption: "Import these tiddlers", name: 'import'}
- ]}
- });
-
-merge(config.commands.closeTiddler,{
- text: "close",
- tooltip: "Close this tiddler"});
-
-merge(config.commands.closeOthers,{
- text: "close others",
- tooltip: "Close all other tiddlers"});
-
-merge(config.commands.editTiddler,{
- text: "edit",
- tooltip: "Edit this tiddler",
- readOnlyText: "view",
- readOnlyTooltip: "View the source of this tiddler"});
-
-merge(config.commands.saveTiddler,{
- text: "done",
- tooltip: "Save changes to this tiddler"});
-
-merge(config.commands.cancelTiddler,{
- text: "cancel",
- tooltip: "Undo changes to this tiddler",
- warning: "Are you sure you want to abandon your changes to '%0'?",
- readOnlyText: "done",
- readOnlyTooltip: "View this tiddler normally"});
-
-merge(config.commands.deleteTiddler,{
- text: "delete",
- tooltip: "Delete this tiddler",
- warning: "Are you sure you want to delete '%0'?"});
-
-merge(config.commands.permalink,{
- text: "permalink",
- tooltip: "Permalink for this tiddler"});
-
-merge(config.commands.references,{
- text: "references",
- tooltip: "Show tiddlers that link to this one",
- popupNone: "No references"});
-
-merge(config.commands.jump,{
- text: "jump",
- tooltip: "Jump to another open tiddler"});
-
-merge(config.shadowTiddlers,{
- DefaultTiddlers: "GettingStarted",
- MainMenu: "GettingStarted",
- SiteTitle: "My TiddlyWiki",
- SiteSubtitle: "a reusable non-linear personal web notebook",
- SiteUrl: "http://www.tiddlywiki.com/",
- GettingStarted: "To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:\n* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)\n* MainMenu: The menu (usually on the left)\n* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened\nYou'll also need to enter your username for signing your edits: <<option txtUserName>>",
- SideBarOptions: "<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>",
- OptionsPanel: "These InterfaceOptions for customising TiddlyWiki are saved in your browser\n\nYour username for signing your edits. Write it as a WikiWord (eg JoeBloggs)\n\n<<option txtUserName>>\n<<option chkSaveBackups>> SaveBackups\n<<option chkAutoSave>> AutoSave\n<<option chkRegExpSearch>> RegExpSearch\n<<option chkCaseSensitiveSearch>> CaseSensitiveSearch\n<<option chkAnimate>> EnableAnimations\n\n----\nAdvancedOptions\nPluginManager\nImportTiddlers",
- AdvancedOptions: "<<option chkGenerateAnRssFeed>> GenerateAnRssFeed\n<<option chkOpenInNewWindow>> OpenLinksInNewWindow\n<<option chkSaveEmptyTemplate>> SaveEmptyTemplate\n<<option chkToggleLinks>> Clicking on links to tiddlers that are already open causes them to close\n^^(override with Control or other modifier key)^^\n<<option chkHttpReadOnly>> HideEditingFeatures when viewed over HTTP\n<<option chkForceMinorUpdate>> Treat edits as MinorChanges by preserving date and time\n^^(override with Shift key when clicking 'done' or by pressing Ctrl-Shift-Enter^^\n<<option chkConfirmDelete>> ConfirmBeforeDeleting\nMaximum number of lines in a tiddler edit box: <<option txtMaxEditRows>>\nFolder name for backup files: <<option txtBackupFolder>>\n<<option chkInsertTabs>> Use tab key to insert tab characters instead of jumping to next field",
- SideBarTabs: "<<tabs txtMainTab Timeline Timeline TabTimeline All 'All tiddlers' TabAll Tags 'All tags' TabTags More 'More lists' TabMore>>",
- TabTimeline: "<<timeline>>",
- TabAll: "<<list all>>",
- TabTags: "<<allTags>>",
- TabMore: "<<tabs txtMoreTab Missing 'Missing tiddlers' TabMoreMissing Orphans 'Orphaned tiddlers' TabMoreOrphans Shadowed 'Shadowed tiddlers' TabMoreShadowed>>",
- TabMoreMissing: "<<list missing>>",
- TabMoreOrphans: "<<list orphans>>",
- TabMoreShadowed: "<<list shadowed>>",
- PluginManager: "<<plugins>>",
- ImportTiddlers: "<<importTiddlers>>"});
-
-// ---------------------------------------------------------------------------------
-// Main
-// ---------------------------------------------------------------------------------
-
-var params = null; // Command line parameters
-var store = null; // TiddlyWiki storage
-var story = null; // Main story
-var formatter = null; // Default formatters for the wikifier
-config.parsers = {}; // Hashmap of alternative parsers for the wikifier
-var anim = new Animator(); // Animation engine
-var readOnly = false; // Whether we're in readonly mode
-var highlightHack = null; // Embarrassing hack department...
-var hadConfirmExit = false; // Don't warn more than once
-var safeMode = false; // Disable all plugins and cookies
-var installedPlugins = []; // Information filled in when plugins are executed
-var startingUp = false; // Whether we're in the process of starting up
-var pluginInfo,tiddler; // Used to pass information to plugins in loadPlugins()
-
-// Whether to use the JavaSaver applet
-var useJavaSaver = config.browser.isSafari || config.browser.isOpera;
-
-// Starting up
-function main()
-{
- var now, then = new Date();
- startingUp = true;
- window.onbeforeunload = function(e) {if(window.confirmExit) return confirmExit();};
- params = getParameters();
- if(params)
- params = params.parseParams("open",null,false);
- store = new TiddlyWiki();
- invokeParamifier(params,"oninit");
- story = new Story("tiddlerDisplay","tiddler");
- addEvent(document,"click",Popup.onDocumentClick);
- saveTest();
- loadOptionsCookie();
- for(var s=0; s<config.notifyTiddlers.length; s++)
- store.addNotification(config.notifyTiddlers[s].name,config.notifyTiddlers[s].notify);
- store.loadFromDiv("storeArea","store",true);
- invokeParamifier(params,"onload");
- var pluginProblem = loadPlugins();
- formatter = new Formatter(config.formatters);
- readOnly = (window.location.protocol == "file:") ? false : config.options.chkHttpReadOnly;
- invokeParamifier(params,"onconfig");
- store.notifyAll();
- restart();
- if(pluginProblem)
- {
- story.displayTiddler(null,"PluginManager");
- displayMessage(config.messages.customConfigError);
- }
- now = new Date();
- if(config.displayStartupTime)
- displayMessage("TiddlyWiki startup in " + (now-then)/1000 + " seconds");
- startingUp = false;
-}
-
-// Restarting
-function restart()
-{
- invokeParamifier(params,"onstart");
- if(story.isEmpty())
- {
- var defaultParams = store.getTiddlerText("DefaultTiddlers").parseParams("open",null,false);
- invokeParamifier(defaultParams,"onstart");
- }
- window.scrollTo(0,0);
-}
-
-function saveTest()
-{
- var saveTest = document.getElementById("saveTest");
- if(saveTest.hasChildNodes())
- alert(config.messages.savedSnapshotError);
- saveTest.appendChild(document.createTextNode("savetest"));
-}
-
-function loadPlugins()
-{
- if(safeMode)
- return false;
- var configTiddlers = store.getTaggedTiddlers("systemConfig");
- installedPlugins = [];
- var hadProblem = false;
- for(var t=0; t<configTiddlers.length; t++)
- {
- tiddler = configTiddlers[t];
- pluginInfo = getPluginInfo(tiddler);
- if(isPluginExecutable(pluginInfo))
- {
- pluginInfo.executed = true;
- pluginInfo.error = false;
- try
- {
- if(tiddler.text && tiddler.text != "")
- window.eval(tiddler.text);
- }
- catch(e)
- {
- pluginInfo.log.push(config.messages.pluginError.format([exceptionText(e)]));
- pluginInfo.error = true;
- hadProblem = true;
- }
- }
- else
- pluginInfo.warning = true;
- installedPlugins.push(pluginInfo);
- }
- return hadProblem;
-}
-
-function getPluginInfo(tiddler)
-{
- var p = store.getTiddlerSlices(tiddler.title,["Name","Description","Version","CoreVersion","Date","Source","Author","License","Browsers"]);
- p.tiddler = tiddler;
- p.title = tiddler.title;
- p.log = [];
- return p;
-}
-
-// Check that a particular plugin is valid for execution
-function isPluginExecutable(plugin)
-{
- if(plugin.tiddler.isTagged("systemConfigDisable"))
- return verifyTail(plugin,false,config.messages.pluginDisabled);
- if(plugin.tiddler.isTagged("systemConfigForce"))
- return verifyTail(plugin,true,config.messages.pluginForced);
- if(plugin["CoreVersion"])
- {
- var coreVersion = plugin["CoreVersion"].split(".");
- var w = parseInt(coreVersion[0]) - version.major;
- if(w == 0 && coreVersion[1])
- w = parseInt(coreVersion[1]) - version.minor;
- if(w == 0 && coreVersion[2])
- w = parseInt(coreVersion[2]) - version.revision;
- if(w > 0)
- return verifyTail(plugin,false,config.messages.pluginVersionError);
- }
- return true;
-}
-
-function verifyTail(plugin,result,message)
-{
- plugin.log.push(message);
- return result;
-}
-
-function invokeMacro(place,macro,params,wikifier,tiddler)
-{
- try
- {
- var m = config.macros[macro];
- if(m && m.handler)
- m.handler(place,macro,params.readMacroParams(),wikifier,params,tiddler);
- else
- createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,config.messages.missingMacro]));
- }
- catch(ex)
- {
- createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,ex.toString()]));
- }
-}
-
-// ---------------------------------------------------------------------------------
-// Paramifiers
-// ---------------------------------------------------------------------------------
-
-function getParameters()
-{
- var p = null;
- if(window.location.hash)
- {
- p = decodeURI(window.location.hash.substr(1));
- if(config.browser.firefoxDate != null && config.browser.firefoxDate[1] < "20051111")
- p = convertUTF8ToUnicode(p);
- }
- return p;
-}
-
-function invokeParamifier(params,handler)
-{
- if(!params || params.length == undefined || params.length <= 1)
- return;
- for(var t=1; t<params.length; t++)
- {
- var p = config.paramifiers[params[t].name];
- if(p && p[handler] instanceof Function)
- p[handler](params[t].value);
- }
-}
-
-config.paramifiers = {};
-
-config.paramifiers.start = {
- oninit: function(v) {
- safeMode = v.toLowerCase() == "safe";
- }
-};
-
-config.paramifiers.open = {
- onstart: function(v) {
- story.displayTiddler("bottom",v,null,false,false);
- }
-};
-
-config.paramifiers.story = {
- onstart: function(v) {
- var list = store.getTiddlerText(v,"").parseParams("open",null,false);
- invokeParamifier(list,"onstart");
- }
-};
-
-config.paramifiers.search = {
- onstart: function(v) {
- story.search(v,false,false);
- }
-};
-
-config.paramifiers.searchRegExp = {
- onstart: function(v) {
- story.prototype.search(v,false,true);
- }
-};
-
-config.paramifiers.tag = {
- onstart: function(v) {
- var tagged = store.getTaggedTiddlers(v,"title");
- for(var t=0; t<tagged.length; t++)
- story.displayTiddler("bottom",tagged[t].title,null,false,false);
- }
-};
-
-config.paramifiers.newTiddler = {
- onstart: function(v) {
- if(!readOnly)
- {
- story.displayTiddler(null,v,DEFAULT_EDIT_TEMPLATE);
- story.focusTiddler(v,"text");
- }
- }
-};
-
-config.paramifiers.newJournal = {
- onstart: function(v) {
- if(!readOnly)
- {
- var now = new Date();
- var title = now.formatString(v.trim());
- story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
- story.focusTiddler(title,"text");
- }
- }
-};
-
-// ---------------------------------------------------------------------------------
-// Formatter helpers
-// ---------------------------------------------------------------------------------
-
-function Formatter(formatters)
-{
- this.formatters = [];
- var pattern = [];
- for(var n=0; n<formatters.length; n++)
- {
- pattern.push("(" + formatters[n].match + ")");
- this.formatters.push(formatters[n]);
- }
- this.formatterRegExp = new RegExp(pattern.join("|"),"mg");
-}
-
-config.formatterHelpers = {
-
- createElementAndWikify: function(w)
- {
- w.subWikifyTerm(createTiddlyElement(w.output,this.element),this.termRegExp);
- },
-
- inlineCssHelper: function(w)
- {
- var styles = [];
- config.textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
- var lookaheadMatch = config.textPrimitives.cssLookaheadRegExp.exec(w.source);
- while(lookaheadMatch && lookaheadMatch.index == w.nextMatch)
- {
- var s,v;
- if(lookaheadMatch[1])
- {
- s = lookaheadMatch[1].unDash();
- v = lookaheadMatch[2];
- }
- else
- {
- s = lookaheadMatch[3].unDash();
- v = lookaheadMatch[4];
- }
- if (s=="bgcolor")
- s = "backgroundColor";
- styles.push({style: s, value: v});
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- config.textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
- lookaheadMatch = config.textPrimitives.cssLookaheadRegExp.exec(w.source);
- }
- return styles;
- },
-
- applyCssHelper: function(e,styles)
- {
- for(var t=0; t< styles.length; t++)
- {
- try
- {
- e.style[styles[t].style] = styles[t].value;
- }
- catch (ex)
- {
- }
- }
- },
-
- enclosedTextHelper: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
- {
- var text = lookaheadMatch[1];
- if(config.browser.isIE)
- text = text.replace(/\n/g,"\r");
- createTiddlyElement(w.output,this.element,null,null,text);
- w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
- }
- },
-
- isExternalLink: function(link)
- {
- if(store.tiddlerExists(link) || store.isShadowTiddler(link))
- {
- //# Definitely not an external link
- return false;
- }
- var urlRegExp = new RegExp(config.textPrimitives.urlPattern,"mg");
- if(urlRegExp.exec(link))
- {
- // Definitely an external link
- return true;
- }
- if (link.indexOf(".")!=-1 || link.indexOf("\\")!=-1 || link.indexOf("/")!=-1)
- {
- //# Link contains . / or \ so is probably an external link
- return true;
- }
- //# Otherwise assume it is not an external link
- return false;
- }
-
-};
-
-// ---------------------------------------------------------------------------------
-// Standard formatters
-// ---------------------------------------------------------------------------------
-
-config.formatters = [
-{
- name: "table",
- match: "^\\|(?:[^\\n]*)\\|(?:[fhck]?)$",
- lookaheadRegExp: /^\|([^\n]*)\|([fhck]?)$/mg,
- rowTermRegExp: /(\|(?:[fhck]?)$\n?)/mg,
- cellRegExp: /(?:\|([^\n\|]*)\|)|(\|[fhck]?$\n?)/mg,
- cellTermRegExp: /((?:\x20*)\|)/mg,
- rowTypes: {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
-
- handler: function(w)
- {
- var table = createTiddlyElement(w.output,"table");
- var prevColumns = [];
- var currRowType = null;
- var rowContainer;
- var rowCount = 0;
- w.nextMatch = w.matchStart;
- this.lookaheadRegExp.lastIndex = w.nextMatch;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- while(lookaheadMatch && lookaheadMatch.index == w.nextMatch)
- {
- var nextRowType = lookaheadMatch[2];
- if(nextRowType == "k")
- {
- table.className = lookaheadMatch[1];
- w.nextMatch += lookaheadMatch[0].length+1;
- }
- else
- {
- if(nextRowType != currRowType)
- {
- rowContainer = createTiddlyElement(table,this.rowTypes[nextRowType]);
- currRowType = nextRowType;
- }
- if(currRowType == "c")
- {
- // Caption
- w.nextMatch++;
- if(rowContainer != table.firstChild)
- table.insertBefore(rowContainer,table.firstChild);
- rowContainer.setAttribute("align",rowCount == 0?"top":"bottom");
- w.subWikifyTerm(rowContainer,this.rowTermRegExp);
- }
- else
- {
- this.rowHandler(w,createTiddlyElement(rowContainer,"tr",null,(rowCount&1)?"oddRow":"evenRow"),prevColumns);
- rowCount++;
- }
- }
- this.lookaheadRegExp.lastIndex = w.nextMatch;
- lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- }
- },
- rowHandler: function(w,e,prevColumns)
- {
- var col = 0;
- var colSpanCount = 1;
- var prevCell = null;
- this.cellRegExp.lastIndex = w.nextMatch;
- var cellMatch = this.cellRegExp.exec(w.source);
- while(cellMatch && cellMatch.index == w.nextMatch)
- {
- if(cellMatch[1] == "~")
- {
- // Rowspan
- var last = prevColumns[col];
- if(last)
- {
- last.rowSpanCount++;
- last.element.setAttribute("rowspan",last.rowSpanCount);
- last.element.setAttribute("rowSpan",last.rowSpanCount); // Needed for IE
- last.element.valign = "center";
- }
- w.nextMatch = this.cellRegExp.lastIndex-1;
- }
- else if(cellMatch[1] == ">")
- {
- // Colspan
- colSpanCount++;
- w.nextMatch = this.cellRegExp.lastIndex-1;
- }
- else if(cellMatch[2])
- {
- // End of row
- if(prevCell && colSpanCount > 1)
- {
- prevCell.setAttribute("colspan",colSpanCount);
- prevCell.setAttribute("colSpan",colSpanCount); // Needed for IE
- }
- w.nextMatch = this.cellRegExp.lastIndex;
- break;
- }
- else
- {
- // Cell
- w.nextMatch++;
- var styles = config.formatterHelpers.inlineCssHelper(w);
- var spaceLeft = false;
- var chr = w.source.substr(w.nextMatch,1);
- while(chr == " ")
- {
- spaceLeft = true;
- w.nextMatch++;
- chr = w.source.substr(w.nextMatch,1);
- }
- var cell;
- if(chr == "!")
- {
- cell = createTiddlyElement(e,"th");
- w.nextMatch++;
- }
- else
- cell = createTiddlyElement(e,"td");
- prevCell = cell;
- prevColumns[col] = {rowSpanCount:1, element:cell};
- if(colSpanCount > 1)
- {
- cell.setAttribute("colspan",colSpanCount);
- cell.setAttribute("colSpan",colSpanCount); // Needed for IE
- colSpanCount = 1;
- }
- config.formatterHelpers.applyCssHelper(cell,styles);
- w.subWikifyTerm(cell,this.cellTermRegExp);
- if(w.matchText.substr(w.matchText.length-2,1) == " ") // spaceRight
- cell.align = spaceLeft ? "center" : "left";
- else if(spaceLeft)
- cell.align = "right";
- w.nextMatch--;
- }
- col++;
- this.cellRegExp.lastIndex = w.nextMatch;
- cellMatch = this.cellRegExp.exec(w.source);
- }
- }
-},
-
-{
- name: "heading",
- match: "^!{1,5}",
- termRegExp: /(\n)/mg,
- handler: function(w)
- {
- w.subWikifyTerm(createTiddlyElement(w.output,"h" + w.matchLength),this.termRegExp);
- }
-},
-
-{
- name: "list",
- match: "^(?:(?:(?:\\*)|(?:#)|(?:;)|(?::))+)",
- lookaheadRegExp: /^(?:(?:(\*)|(#)|(;)|(:))+)/mg,
- termRegExp: /(\n)/mg,
- handler: function(w)
- {
- var placeStack = [w.output];
- var currLevel = 0, currType = null;
- var listLevel, listType, itemType;
- w.nextMatch = w.matchStart;
- this.lookaheadRegExp.lastIndex = w.nextMatch;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- while(lookaheadMatch && lookaheadMatch.index == w.nextMatch)
- {
- if(lookaheadMatch[1])
- {
- listType = "ul";
- itemType = "li";
- }
- else if(lookaheadMatch[2])
- {
- listType = "ol";
- itemType = "li";
- }
- else if(lookaheadMatch[3])
- {
- listType = "dl";
- itemType = "dt";
- }
- else if(lookaheadMatch[4])
- {
- listType = "dl";
- itemType = "dd";
- }
- listLevel = lookaheadMatch[0].length;
- w.nextMatch += lookaheadMatch[0].length;
- if(listLevel > currLevel)
- {
- for(var t=currLevel; t<listLevel; t++)
- placeStack.push(createTiddlyElement(placeStack[placeStack.length-1],listType));
- }
- else if(listLevel < currLevel)
- {
- for(var t=currLevel; t>listLevel; t--)
- placeStack.pop();
- }
- else if(listLevel == currLevel && listType != currType)
- {
- placeStack.pop();
- placeStack.push(createTiddlyElement(placeStack[placeStack.length-1],listType));
- }
- currLevel = listLevel;
- currType = listType;
- var e = createTiddlyElement(placeStack[placeStack.length-1],itemType);
- w.subWikifyTerm(e,this.termRegExp);
- this.lookaheadRegExp.lastIndex = w.nextMatch;
- lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- }
- }
-},
-
-{
- name: "quoteByBlock",
- match: "^<<<\\n",
- termRegExp: /(^<<<(\n|$))/mg,
- element: "blockquote",
- handler: config.formatterHelpers.createElementAndWikify
-},
-
-{
- name: "quoteByLine",
- match: "^>+",
- lookaheadRegExp: /^>+/mg,
- termRegExp: /(\n)/mg,
- element: "blockquote",
- handler: function(w)
- {
- var placeStack = [w.output];
- var currLevel = 0;
- var newLevel = w.matchLength;
- var t;
- do {
- if(newLevel > currLevel)
- {
- for(t=currLevel; t<newLevel; t++)
- placeStack.push(createTiddlyElement(placeStack[placeStack.length-1],this.element));
- }
- else if(newLevel < currLevel)
- {
- for(t=currLevel; t>newLevel; t--)
- placeStack.pop();
- }
- currLevel = newLevel;
- w.subWikifyTerm(placeStack[placeStack.length-1],this.termRegExp);
- createTiddlyElement(placeStack[placeStack.length-1],"br");
- this.lookaheadRegExp.lastIndex = w.nextMatch;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
- if(matched)
- {
- newLevel = lookaheadMatch[0].length;
- w.nextMatch += lookaheadMatch[0].length;
- }
- } while(matched);
- }
-},
-
-{
- name: "rule",
- match: "^----+$\\n?",
- handler: function(w)
- {
- createTiddlyElement(w.output,"hr");
- }
-},
-
-{
- name: "monospacedByLine",
- match: "^\\{\\{\\{\\n",
- lookaheadRegExp: /^\{\{\{\n((?:^[^\n]*\n)+?)(^\}\}\}$\n?)/mg,
- element: "pre",
- handler: config.formatterHelpers.enclosedTextHelper
-},
-
-{
- name: "monospacedByLineForCSS",
- match: "^/\\*[\\{]{3}\\*/\\n",
- lookaheadRegExp: /\/\*[\{]{3}\*\/\n*((?:^[^\n]*\n)+?)(\n*^\/\*[\}]{3}\*\/$\n?)/mg,
- element: "pre",
- handler: config.formatterHelpers.enclosedTextHelper
-},
-
-{
- name: "monospacedByLineForPlugin",
- match: "^//\\{\\{\\{\\n",
- lookaheadRegExp: /^\/\/\{\{\{\n\n*((?:^[^\n]*\n)+?)(\n*^\/\/\}\}\}$\n?)/mg,
- element: "pre",
- handler: config.formatterHelpers.enclosedTextHelper
-},
-
-{
- name: "monospacedByLineForTemplate",
- match: "^<!--[\\{]{3}-->\\n",
- lookaheadRegExp: /<!--[\{]{3}-->\n*((?:^[^\n]*\n)+?)(\n*^<!--[\}]{3}-->$\n?)/mg,
- element: "pre",
- handler: config.formatterHelpers.enclosedTextHelper
-},
-
-{
- name: "wikifyCommentForPlugin",
- match: "^/\\*\\*\\*\\n",
- termRegExp: /(^\*\*\*\/\n)/mg,
- handler: function(w)
- {
- w.subWikifyTerm(w.output,this.termRegExp);
- }
-},
-
-{
- name: "wikifyCommentForTemplate",
- match: "^<!---\\n",
- termRegExp: /(^--->\n)/mg,
- handler: function(w)
- {
- w.subWikifyTerm(w.output,this.termRegExp);
- }
-},
-
-{
- name: "macro",
- match: "<<",
- lookaheadRegExp: /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
- handler: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1])
- {
- w.nextMatch = this.lookaheadRegExp.lastIndex;
- invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
- }
- }
-},
-
-{
- name: "prettyLink",
- match: "\\[\\[",
- lookaheadRegExp: /\[\[(.*?)(?:\|(~)?(.*?))?\]\]/mg,
- handler: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
- {
- var e;
- var text = lookaheadMatch[1];
- if(lookaheadMatch[3])
- {
- // Pretty bracketted link
- var link = lookaheadMatch[3];
- e = (!lookaheadMatch[2] && config.formatterHelpers.isExternalLink(link))
- ? createExternalLink(w.output,link)
- : createTiddlyLink(w.output,link,false,null,w.isStatic);
- }
- else
- {
- // Simple bracketted link
- e = createTiddlyLink(w.output,text,false,null,w.isStatic);
- }
- createTiddlyText(e,text);
- w.nextMatch = this.lookaheadRegExp.lastIndex;
- }
- }
-},
-
-{
- name: "unWikiLink",
- match: config.textPrimitives.unWikiLink+config.textPrimitives.wikiLink,
- handler: function(w)
- {
- w.outputText(w.output,w.matchStart+1,w.nextMatch);
- }
-},
-
-{
- name: "wikiLink",
- match: config.textPrimitives.wikiLink,
- handler: function(w)
- {
- if(w.matchStart > 0)
- {
- var preRegExp = new RegExp(config.textPrimitives.anyLetterStrict,"mg");
- preRegExp.lastIndex = w.matchStart-1;
- var preMatch = preRegExp.exec(w.source);
- if(preMatch.index == w.matchStart-1)
- {
- w.outputText(w.output,w.matchStart,w.nextMatch);
- return;
- }
- }
- if(w.autoLinkWikiWords == true || store.isShadowTiddler(w.matchText))
- {
- var link = createTiddlyLink(w.output,w.matchText,false,null,w.isStatic);
- w.outputText(link,w.matchStart,w.nextMatch);
- }
- else
- {
- w.outputText(w.output,w.matchStart,w.nextMatch);
- }
- }
-},
-
-{
- name: "urlLink",
- match: config.textPrimitives.urlPattern,
- handler: function(w)
- {
- w.outputText(createExternalLink(w.output,w.matchText),w.matchStart,w.nextMatch);
- }
-},
-
-{
- name: "image",
- match: "\\[[<>]?[Ii][Mm][Gg]\\[",
- lookaheadRegExp: /\[(<?)(>?)[Ii][Mm][Gg]\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg,
- handler: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart) // Simple bracketted link
- {
- var e = w.output;
- if(lookaheadMatch[5])
- {
- var link = lookaheadMatch[5];
- e = config.formatterHelpers.isExternalLink(link) ? createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic);
- addClass(e,"imageLink");
- }
- var img = createTiddlyElement(e,"img");
- if(lookaheadMatch[1])
- img.align = "left";
- else if(lookaheadMatch[2])
- img.align = "right";
- if(lookaheadMatch[3])
- img.title = lookaheadMatch[3];
- img.src = lookaheadMatch[4];
- w.nextMatch = this.lookaheadRegExp.lastIndex;
- }
- }
-},
-
-{
- name: "html",
- match: "<[Hh][Tt][Mm][Ll]>",
- lookaheadRegExp: /<[Hh][Tt][Mm][Ll]>((?:.|\n)*?)<\/[Hh][Tt][Mm][Ll]>/mg,
- handler: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
- {
- createTiddlyElement(w.output,"span").innerHTML = lookaheadMatch[1];
- w.nextMatch = this.lookaheadRegExp.lastIndex;
- }
- }
-},
-
-{
- name: "commentByBlock",
- match: "/%",
- lookaheadRegExp: /\/%((?:.|\n)*?)%\//mg,
- handler: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
- w.nextMatch = this.lookaheadRegExp.lastIndex;
- }
-},
-
-{
- name: "boldByChar",
- match: "''",
- termRegExp: /('')/mg,
- element: "strong",
- handler: config.formatterHelpers.createElementAndWikify
-},
-
-{
- name: "italicByChar",
- match: "//",
- termRegExp: /(\/\/)/mg,
- element: "em",
- handler: config.formatterHelpers.createElementAndWikify
-},
-
-{
- name: "underlineByChar",
- match: "__",
- termRegExp: /(__)/mg,
- element: "u",
- handler: config.formatterHelpers.createElementAndWikify
-},
-
-{
- name: "strikeByChar",
- match: "--(?!\\s|$)",
- termRegExp: /((?!\s)--|(?=\n\n))/mg,
- element: "strike",
- handler: config.formatterHelpers.createElementAndWikify
-},
-
-{
- name: "superscriptByChar",
- match: "\\^\\^",
- termRegExp: /(\^\^)/mg,
- element: "sup",
- handler: config.formatterHelpers.createElementAndWikify
-},
-
-{
- name: "subscriptByChar",
- match: "~~",
- termRegExp: /(~~)/mg,
- element: "sub",
- handler: config.formatterHelpers.createElementAndWikify
-},
-
-{
- name: "monospacedByChar",
- match: "\\{\\{\\{",
- lookaheadRegExp: /\{\{\{((?:.|\n)*?)\}\}\}/mg,
- handler: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
- {
- createTiddlyElement(w.output,"code",null,null,lookaheadMatch[1]);
- w.nextMatch = this.lookaheadRegExp.lastIndex;
- }
- }
-},
-
-{
- name: "styleByChar",
- match: "@@",
- termRegExp: /(@@)/mg,
- handler: function(w)
- {
- var e = createTiddlyElement(w.output,"span");
- var styles = config.formatterHelpers.inlineCssHelper(w);
- if(styles.length == 0)
- e.className = "marked";
- else
- config.formatterHelpers.applyCssHelper(e,styles);
- w.subWikifyTerm(e,this.termRegExp);
- }
-},
-
-{
- name: "lineBreak",
- match: "\\n|<br ?/?>",
- handler: function(w)
- {
- createTiddlyElement(w.output,"br");
- }
-},
-
-{
- name: "rawText",
- match: "\\\"{3}|<nowiki>",
- lookaheadRegExp: /(?:\"{3}|<nowiki>)((?:.|\n)*?)(?:\"{3}|<\/nowiki>)/mg,
- handler: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
- {
- createTiddlyElement(w.output,"span",null,null,lookaheadMatch[1]);
- w.nextMatch = this.lookaheadRegExp.lastIndex;
- }
- }
-},
-
-{
- name: "mdash",
- match: "--",
- handler: function(w)
- {
- createTiddlyElement(w.output,"span").innerHTML = "&mdash;";
- }
-},
-
-{
- name: "htmlEntitiesEncoding",
- match: "(?:(?:&#?[a-zA-Z0-9]{2,8};|.)(?:&#?(?:x0*(?:3[0-6][0-9a-fA-F]|1D[c-fC-F][0-9a-fA-F]|20[d-fD-F][0-9a-fA-F]|FE2[0-9a-fA-F])|0*(?:76[89]|7[7-9][0-9]|8[0-7][0-9]|761[6-9]|76[2-7][0-9]|84[0-3][0-9]|844[0-7]|6505[6-9]|6506[0-9]|6507[0-1]));)+|&#?[a-zA-Z0-9]{2,8};)",
- handler: function(w)
- {
- createTiddlyElement(w.output,"span").innerHTML = w.matchText;
- }
-},
-
-{
- name: "customClasses",
- match: "\\{\\{",
- termRegExp: /(\}\}\})/mg,
- lookaheadRegExp: /\{\{[\s]*([\w]+[\s\w]*)[\s]*\{(\n?)/mg,
- handler: function(w)
- {
- this.lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
- if(lookaheadMatch)
- {
- var e = createTiddlyElement(w.output,lookaheadMatch[2] == "\n" ? "div" : "span",null,lookaheadMatch[1]);
- w.nextMatch = this.lookaheadRegExp.lastIndex;
- w.subWikifyTerm(e,this.termRegExp);
- }
- }
-}
-
-];
-
-// ---------------------------------------------------------------------------------
-// Wikifier
-// ---------------------------------------------------------------------------------
-
-function getParser(tiddler)
-{
- var f = formatter;
- if(tiddler!=null)
- {
- for(var i in config.parsers)
- {
- if(tiddler.isTagged(config.parsers[i].formatTag))
- {
- f = config.parsers[i];
- break;
- }
- }
- }
- return f;
-}
-
-function wikify(source,output,highlightRegExp,tiddler)
-{
- if(source && source != "")
- {
- var wikifier = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
- wikifier.subWikifyUnterm(output);
- }
-}
-
-function wikifyStatic(source,highlightRegExp,tiddler)
-{
- var e = createTiddlyElement(document.body,"div");
- e.style.display = "none";
- var html = "";
- if(source && source != "")
- {
- var wikifier = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
- wikifier.isStatic = true;
- wikifier.subWikifyUnterm(e);
- html = e.innerHTML;
- e.parentNode.removeChild(e);
- }
- return html;
-}
-
-// Wikify a named tiddler to plain text
-function wikifyPlain(title)
-{
- if(store.tiddlerExists(title) || store.isShadowTiddler(title))
- {
- var wikifier = new Wikifier(store.getTiddlerText(title),formatter,null,store.getTiddler(title));
- return wikifier.wikifyPlain();
- }
- else
- return "";
-}
-
-// Highlight plain text into an element
-function highlightify(source,output,highlightRegExp)
-{
- if(source && source != "")
- {
- var wikifier = new Wikifier(source,formatter,highlightRegExp);
- wikifier.outputText(output,0,source.length);
- }
-}
-
-// Construct a wikifier object
-// source - source string that's going to be wikified
-// formatter - Formatter() object containing the list of formatters to be used
-// highlightRegExp - regular expression of the text string to highlight
-// tiddler - reference to the tiddler that's taken to be the container for this wikification
-function Wikifier(source,formatter,highlightRegExp,tiddler)
-{
- this.source = source;
- this.output = null;
- this.formatter = formatter;
- this.nextMatch = 0;
- this.autoLinkWikiWords = tiddler && tiddler.autoLinkWikiWords() == false ? false : true;
- this.highlightRegExp = highlightRegExp;
- this.highlightMatch = null;
- this.isStatic = false;
- if(highlightRegExp)
- {
- highlightRegExp.lastIndex = 0;
- this.highlightMatch = highlightRegExp.exec(source);
- }
- this.tiddler = tiddler;
-}
-
-Wikifier.prototype.wikifyPlain = function()
-{
- var e = createTiddlyElement(document.body,"div");
- e.style.display = "none";
- this.subWikify(e);
- var text = getPlainText(e);
- e.parentNode.removeChild(e);
- return text;
-}
-
-Wikifier.prototype.subWikify = function(output,terminator)
-{
- // Handle the terminated and unterminated cases separately
- if (terminator)
- this.subWikifyTerm(output,new RegExp("(" + terminator + ")","mg"));
- else
- this.subWikifyUnterm(output);
-}
-
-Wikifier.prototype.subWikifyUnterm = function(output)
-{
- // subWikify() can be indirectly recursive, so we need to save the old output pointer
- var oldOutput = this.output;
- this.output = output;
- // Get the first match
- this.formatter.formatterRegExp.lastIndex = this.nextMatch;
- var formatterMatch = this.formatter.formatterRegExp.exec(this.source);
- while(formatterMatch)
- {
- // Output any text before the match
- if(formatterMatch.index > this.nextMatch)
- this.outputText(this.output,this.nextMatch,formatterMatch.index);
- // Set the match parameters for the handler
- this.matchStart = formatterMatch.index;
- this.matchLength = formatterMatch[0].length;
- this.matchText = formatterMatch[0];
- this.nextMatch = this.formatter.formatterRegExp.lastIndex;
- // Figure out which formatter matched and call its handler
- for(var t=1; t<formatterMatch.length; t++)
- {
- if(formatterMatch[t])
- {
- this.formatter.formatters[t-1].handler(this);
- this.formatter.formatterRegExp.lastIndex = this.nextMatch;
- break;
- }
- }
- // Get the next match
- formatterMatch = this.formatter.formatterRegExp.exec(this.source);
- }
- // Output any text after the last match
- if(this.nextMatch < this.source.length)
- {
- this.outputText(this.output,this.nextMatch,this.source.length);
- this.nextMatch = this.source.length;
- }
- // Restore the output pointer
- this.output = oldOutput;
-}
-
-Wikifier.prototype.subWikifyTerm = function(output,terminatorRegExp)
-{
- // subWikify() can be indirectly recursive, so we need to save the old output pointer
- var oldOutput = this.output;
- this.output = output;
- // Get the first matches for the formatter and terminator RegExps
- terminatorRegExp.lastIndex = this.nextMatch;
- var terminatorMatch = terminatorRegExp.exec(this.source);
- this.formatter.formatterRegExp.lastIndex = this.nextMatch;
- var formatterMatch = this.formatter.formatterRegExp.exec(terminatorMatch ? this.source.substr(0,terminatorMatch.index) : this.source);
- while(terminatorMatch || formatterMatch)
- {
- // Check for a terminator match before the next formatter match
- if(terminatorMatch && (!formatterMatch || terminatorMatch.index <= formatterMatch.index))
- {
- // Output any text before the match
- if(terminatorMatch.index > this.nextMatch)
- this.outputText(this.output,this.nextMatch,terminatorMatch.index);
- // Set the match parameters
- this.matchText = terminatorMatch[1];
- this.matchLength = terminatorMatch[1].length;
- this.matchStart = terminatorMatch.index;
- this.nextMatch = this.matchStart + this.matchLength;
- // Restore the output pointer
- this.output = oldOutput;
- return;
- }
- // It must be a formatter match; output any text before the match
- if(formatterMatch.index > this.nextMatch)
- this.outputText(this.output,this.nextMatch,formatterMatch.index);
- // Set the match parameters
- this.matchStart = formatterMatch.index;
- this.matchLength = formatterMatch[0].length;
- this.matchText = formatterMatch[0];
- this.nextMatch = this.formatter.formatterRegExp.lastIndex;
- // Figure out which formatter matched and call its handler
- for(var t=1; t<formatterMatch.length; t++)
- {
- if(formatterMatch[t])
- {
- this.formatter.formatters[t-1].handler(this);
- this.formatter.formatterRegExp.lastIndex = this.nextMatch;
- break;
- }
- }
- // Get the next match
- terminatorRegExp.lastIndex = this.nextMatch;
- terminatorMatch = terminatorRegExp.exec(this.source);
- formatterMatch = this.formatter.formatterRegExp.exec(terminatorMatch ? this.source.substr(0,terminatorMatch.index) : this.source);
- }
- // Output any text after the last match
- if(this.nextMatch < this.source.length)
- {
- this.outputText(this.output,this.nextMatch,this.source.length);
- this.nextMatch = this.source.length;
- }
- // Restore the output pointer
- this.output = oldOutput;
-}
-
-Wikifier.prototype.outputText = function(place,startPos,endPos)
-{
- // Check for highlights
- while(this.highlightMatch && (this.highlightRegExp.lastIndex > startPos) && (this.highlightMatch.index < endPos) && (startPos < endPos))
- {
- // Deal with any plain text before the highlight
- if(this.highlightMatch.index > startPos)
- {
- createTiddlyText(place,this.source.substring(startPos,this.highlightMatch.index));
- startPos = this.highlightMatch.index;
- }
- // Deal with the highlight
- var highlightEnd = Math.min(this.highlightRegExp.lastIndex,endPos);
- var theHighlight = createTiddlyElement(place,"span",null,"highlight",this.source.substring(startPos,highlightEnd));
- startPos = highlightEnd;
- // Nudge along to the next highlight if we're done with this one
- if(startPos >= this.highlightRegExp.lastIndex)
- this.highlightMatch = this.highlightRegExp.exec(this.source);
- }
- // Do the unhighlighted text left over
- if(startPos < endPos)
- {
- createTiddlyText(place,this.source.substring(startPos,endPos));
- }
-}
-
-// ---------------------------------------------------------------------------------
-// Macro definitions
-// ---------------------------------------------------------------------------------
-
-config.macros.today.handler = function(place,macroName,params)
-{
- var now = new Date();
- var text;
- if(params[0])
- text = now.formatString(params[0].trim());
- else
- text = now.toLocaleString();
- createTiddlyElement(place,"span",null,null,text);
-}
-
-config.macros.version.handler = function(place)
-{
- createTiddlyElement(place,"span",null,null,version.major + "." + version.minor + "." + version.revision + (version.beta ? " (beta " + version.beta + ")" : ""));
-}
-
-config.macros.list.handler = function(place,macroName,params)
-{
- var type = params[0] ? params[0] : "all";
- var theList = document.createElement("ul");
- place.appendChild(theList);
- if(this[type].prompt)
- createTiddlyElement(theList,"li",null,"listTitle",this[type].prompt);
- var results;
- if(this[type].handler)
- results = this[type].handler(params);
- for(var t = 0; t < results.length; t++)
- {
- var theListItem = document.createElement("li")
- theList.appendChild(theListItem);
- if(typeof results[t] == "string")
- createTiddlyLink(theListItem,results[t],true);
- else
- createTiddlyLink(theListItem,results[t].title,true);
- }
-}
-
-config.macros.list.all.handler = function(params)
-{
- return store.reverseLookup("tags","excludeLists",false,"title");
-}
-
-config.macros.list.missing.handler = function(params)
-{
- return store.getMissingLinks();
-}
-
-config.macros.list.orphans.handler = function(params)
-{
- return store.getOrphans();
-}
-
-config.macros.list.shadowed.handler = function(params)
-{
- return store.getShadowed();
-}
-
-config.macros.allTags.handler = function(place,macroName,params)
-{
- var tags = store.getTags();
- var theDateList = createTiddlyElement(place,"ul");
- if(tags.length == 0)
- createTiddlyElement(theDateList,"li",null,"listTitle",this.noTags);
- for(var t=0; t<tags.length; t++)
- {
- var theListItem =createTiddlyElement(theDateList,"li");
- var theTag = createTiddlyButton(theListItem,tags[t][0] + " (" + tags[t][1] + ")",this.tooltip.format([tags[t][0]]),onClickTag);
- theTag.setAttribute("tag",tags[t][0]);
- }
-}
-
-config.macros.timeline.handler = function(place,macroName,params)
-{
- var field = params[0] ? params[0] : "modified";
- var tiddlers = store.reverseLookup("tags","excludeLists",false,field);
- var lastDay = "";
- var last = params[1] ? tiddlers.length-Math.min(tiddlers.length,parseInt(params[1])) : 0;
- for(var t=tiddlers.length-1; t>=last; t--)
- {
- var tiddler = tiddlers[t];
- var theDay = tiddler[field].convertToLocalYYYYMMDDHHMM().substr(0,8);
- if(theDay != lastDay)
- {
- var theDateList = document.createElement("ul");
- place.appendChild(theDateList);
- createTiddlyElement(theDateList,"li",null,"listTitle",tiddler[field].formatString(this.dateFormat));
- lastDay = theDay;
- }
- var theDateListItem = createTiddlyElement(theDateList,"li",null,"listLink");
- theDateListItem.appendChild(createTiddlyLink(place,tiddler.title,true));
- }
-}
-
-config.macros.search.handler = function(place,macroName,params)
-{
- var searchTimeout = null;
- var btn = createTiddlyButton(place,this.label,this.prompt,this.onClick);
- var txt = createTiddlyElement(place,"input",null,"txtOptionInput");
- if(params[0])
- txt.value = params[0];
- txt.onkeyup = this.onKeyPress;
- txt.onfocus = this.onFocus;
- txt.setAttribute("size",this.sizeTextbox);
- txt.setAttribute("accessKey",this.accessKey);
- txt.setAttribute("autocomplete","off");
- txt.setAttribute("lastSearchText","");
- if(config.browser.isSafari)
- {
- txt.setAttribute("type","search");
- txt.setAttribute("results","5");
- }
- else
- txt.setAttribute("type","text");
-}
-
-// Global because there's only ever one outstanding incremental search timer
-config.macros.search.timeout = null;
-
-config.macros.search.doSearch = function(txt)
-{
- if(txt.value.length > 0)
- {
- story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);
- txt.setAttribute("lastSearchText",txt.value);
- }
-}
-
-config.macros.search.onClick = function(e)
-{
- config.macros.search.doSearch(this.nextSibling);
- return false;
-}
-
-config.macros.search.onKeyPress = function(e)
-{
- if(!e) var e = window.event;
- switch(e.keyCode)
- {
- case 13: // Ctrl-Enter
- case 10: // Ctrl-Enter on IE PC
- config.macros.search.doSearch(this);
- break;
- case 27: // Escape
- this.value = "";
- clearMessage();
- break;
- }
- if(this.value.length > 2)
- {
- if(this.value != this.getAttribute("lastSearchText"))
- {
- if(config.macros.search.timeout)
- clearTimeout(config.macros.search.timeout);
- var txt = this;
- config.macros.search.timeout = setTimeout(function() {config.macros.search.doSearch(txt);},500);
- }
- }
- else
- {
- if(config.macros.search.timeout)
- clearTimeout(config.macros.search.timeout);
- }
-}
-
-config.macros.search.onFocus = function(e)
-{
- this.select();
-}
-
-config.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- params = paramString.parseParams("name",null,true,false,true);
- var names = params[0]["name"];
- var tiddlerName = names[0];
- var className = names[1] ? names[1] : null;
- var args = params[0]["with"];
- var wrapper = createTiddlyElement(place,"span",null,className);
- if(!args)
- {
- wrapper.setAttribute("refresh","content");
- wrapper.setAttribute("tiddler",tiddlerName);
- }
- var text = store.getTiddlerText(tiddlerName);
- if(text)
- {
- var stack = config.macros.tiddler.tiddlerStack;
- if(stack.indexOf(tiddlerName) !== -1)
- return;
- stack.push(tiddlerName);
- try
- {
- var n = args ? Math.min(args.length,9) : 0;
- for(var i=0; i<n; i++)
- {
- var placeholderRE = new RegExp("\\$" + (i + 1),"mg");
- text = text.replace(placeholderRE,args[i]);
- }
- config.macros.tiddler.renderText(wrapper,text,tiddlerName,params);
- }
- finally
- {
- stack.pop();
- }
- }
-}
-
-config.macros.tiddler.renderText = function(place,text,tiddlerName,params)
-{
- wikify(text,place,null,store.getTiddler(tiddlerName));
-}
-
-config.macros.tiddler.tiddlerStack = [];
-
-config.macros.tag.handler = function(place,macroName,params)
-{
- createTagButton(place,params[0]);
-}
-
-config.macros.tags.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- params = paramString.parseParams("anon",null,true,false,false);
- var theList = createTiddlyElement(place,"ul");
- var title = getParam(params,"anon","");
- if(title && store.tiddlerExists(title))
- tiddler = store.getTiddler(title);
- var sep = getParam(params,"sep"," ");
- var lingo = config.views.wikified.tag;
- var prompt = tiddler.tags.length == 0 ? lingo.labelNoTags : lingo.labelTags;
- createTiddlyElement(theList,"li",null,"listTitle",prompt.format([tiddler.title]));
- for(var t=0; t<tiddler.tags.length; t++)
- {
- createTagButton(createTiddlyElement(theList,"li"),tiddler.tags[t],tiddler.title);
- if(t<tiddler.tags.length-1)
- createTiddlyText(theList,sep);
- }
-}
-
-config.macros.tagging.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- params = paramString.parseParams("anon",null,true,false,false);
- var theList = createTiddlyElement(place,"ul");
- var title = getParam(params,"anon","");
- if(title == "" && tiddler instanceof Tiddler)
- title = tiddler.title;
- var sep = getParam(params,"sep"," ");
- theList.setAttribute("title",this.tooltip.format([title]));
- var tagged = store.getTaggedTiddlers(title);
- var prompt = tagged.length == 0 ? this.labelNotTag : this.label;
- createTiddlyElement(theList,"li",null,"listTitle",prompt.format([title,tagged.length]));
- for(var t=0; t<tagged.length; t++)
- {
- createTiddlyLink(createTiddlyElement(theList,"li"),tagged[t].title,true);
- if(t<tagged.length-1)
- createTiddlyText(theList,sep);
- }
-}
-
-config.macros.closeAll.handler = function(place)
-{
- createTiddlyButton(place,this.label,this.prompt,this.onClick);
-}
-
-config.macros.closeAll.onClick = function(e)
-{
- story.closeAllTiddlers();
- return false;
-}
-
-config.macros.permaview.handler = function(place)
-{
- createTiddlyButton(place,this.label,this.prompt,this.onClick);
-}
-
-config.macros.permaview.onClick = function(e)
-{
- story.permaView();
- return false;
-}
-
-config.macros.saveChanges.handler = function(place)
-{
- if(!readOnly)
- createTiddlyButton(place,this.label,this.prompt,this.onClick,null,null,this.accessKey);
-}
-
-config.macros.saveChanges.onClick = function(e)
-{
- saveChanges();
- return false;
-}
-
-config.macros.slider.onClickSlider = function(e)
-{
- if(!e) var e = window.event;
- var n = this.nextSibling;
- var cookie = n.getAttribute("cookie");
- var isOpen = n.style.display != "none";
- if(anim && config.options.chkAnimate)
- anim.startAnimating(new Slider(n,!isOpen,e.shiftKey || e.altKey,"none"));
- else
- n.style.display = isOpen ? "none" : "block";
- config.options[cookie] = !isOpen;
- saveOptionCookie(cookie);
- return false;
-}
-
-config.macros.slider.createSlider = function(place,cookie,title,tooltip)
-{
- var cookie = cookie ? cookie : "";
- var btn = createTiddlyButton(place,title,tooltip,this.onClickSlider);
- var panel = createTiddlyElement(null,"div",null,"sliderPanel");
- panel.setAttribute("cookie",cookie);
- panel.style.display = config.options[cookie] ? "block" : "none";
- place.appendChild(panel);
- return panel;
-}
-
-config.macros.slider.handler = function(place,macroName,params)
-{
- var panel = this.createSlider(place,params[0],params[2],params[3]);
- var text = store.getTiddlerText(params[1]);
- panel.setAttribute("refresh", "content");
- panel.setAttribute("tiddler", params[1]);
- if(text)
- wikify(text,panel,null,store.getTiddler(params[1]));
-}
-
-config.macros.option.onChangeOption = function(e)
-{
- var opt = this.getAttribute("option");
- var elementType,valueField;
- if(opt)
- {
- switch(opt.substr(0,3))
- {
- case "txt":
- elementType = "input";
- valueField = "value";
- break;
- case "chk":
- elementType = "input";
- valueField = "checked";
- break;
- }
- config.options[opt] = this[valueField];
- saveOptionCookie(opt);
- var nodes = document.getElementsByTagName(elementType);
- for(var t=0; t<nodes.length; t++)
- {
- var optNode = nodes[t].getAttribute("option");
- if(opt == optNode)
- nodes[t][valueField] = this[valueField];
- }
- }
- return(true);
-}
-
-config.macros.option.handler = function(place,macroName,params)
-{
- var opt = params[0];
- if(config.options[opt] == undefined)
- return;
- var c;
- switch(opt.substr(0,3))
- {
- case "txt":
- c = document.createElement("input");
- c.onkeyup = this.onChangeOption;
- c.setAttribute("option",opt);
- c.className = "txtOptionInput";
- place.appendChild(c);
- c.value = config.options[opt];
- break;
- case "chk":
- c = document.createElement("input");
- c.setAttribute("type","checkbox");
- c.onclick = this.onChangeOption;
- c.setAttribute("option",opt);
- c.className = "chkOptionInput";
- place.appendChild(c);
- c.checked = config.options[opt];
- break;
- }
-}
-
-
-
-config.macros.newTiddler.createNewTiddlerButton = function(place,title,params,label,prompt,accessKey,newFocus,isJournal)
-{
- var tags = [];
- for(var t=1; t<params.length; t++)
- if((params[t].name == "anon" && t != 1) || (params[t].name == "tag"))
- tags.push(params[t].value);
- label = getParam(params,"label",label);
- prompt = getParam(params,"prompt",prompt);
- accessKey = getParam(params,"accessKey",accessKey);
- newFocus = getParam(params,"focus",newFocus);
- var btn = createTiddlyButton(place,label,prompt,this.onClickNewTiddler,null,null,accessKey);
- btn.setAttribute("newTitle",title);
- btn.setAttribute("isJournal",isJournal);
- btn.setAttribute("params",tags.join("|"));
- btn.setAttribute("newFocus",newFocus);
- btn.setAttribute("newTemplate",getParam(params,"template",DEFAULT_EDIT_TEMPLATE));
- var text = getParam(params,"text");
- if(text !== undefined)
- btn.setAttribute("newText",text);
- return btn;
-}
-
-config.macros.newTiddler.onClickNewTiddler = function()
-{
- var title = this.getAttribute("newTitle");
- if(this.getAttribute("isJournal"))
- {
- var now = new Date();
- title = now.formatString(title.trim());
- }
- var params = this.getAttribute("params").split("|");
- var focus = this.getAttribute("newFocus");
- var template = this.getAttribute("newTemplate");
- story.displayTiddler(null,title,template);
- var text = this.getAttribute("newText");
- if(typeof text == "string")
- story.getTiddlerField(title,"text").value = text.format([title]);
- for(var t=0;t<params.length;t++)
- story.setTiddlerTag(title,params[t],+1);
- story.focusTiddler(title,focus);
- return false;
-}
-
-config.macros.newTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- if(!readOnly)
- {
- params = paramString.parseParams("anon",null,true,false,false);
- var title = params[1] && params[1].name == "anon" ? params[1].value : this.title;
- title = getParam(params,"title",title);
- this.createNewTiddlerButton(place,title,params,this.label,this.prompt,this.accessKey,"title",false);
- }
-}
-
-config.macros.newJournal.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- if(!readOnly)
- {
- params = paramString.parseParams("anon",null,true,false,false);
- var title = params[1] && params[1].name == "anon" ? params[1].value : "";
- title = getParam(params,"title",title);
- config.macros.newTiddler.createNewTiddlerButton(place,title,params,this.label,this.prompt,this.accessKey,"text",true);
- }
-}
-
-config.macros.sparkline.handler = function(place,macroName,params)
-{
- var data = [];
- var min = 0;
- var max = 0;
- for(var t=0; t<params.length; t++)
- {
- var v = parseInt(params[t]);
- if(v < min)
- min = v;
- if(v > max)
- max = v;
- data.push(v);
- }
- if(data.length < 1)
- return;
- var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
- box.title = data.join(",");
- var w = box.offsetWidth;
- var h = box.offsetHeight;
- box.style.paddingRight = (data.length * 2 - w) + "px";
- box.style.position = "relative";
- for(var d=0; d<data.length; d++)
- {
- var tick = document.createElement("img");
- tick.border = 0;
- tick.className = "sparktick";
- tick.style.position = "absolute";
- tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
- tick.style.left = d*2 + "px";
- tick.style.width = "2px";
- var v = Math.floor(((data[d] - min)/(max-min)) * h);
- tick.style.top = (h-v) + "px";
- tick.style.height = v + "px";
- box.appendChild(tick);
- }
-}
-
-config.macros.tabs.handler = function(place,macroName,params)
-{
- var cookie = params[0];
- var numTabs = (params.length-1)/3;
- var wrapper = createTiddlyElement(null,"div",null,cookie);
- var tabset = createTiddlyElement(wrapper,"div",null,"tabset");
- tabset.setAttribute("cookie",cookie);
- var validTab = false;
- for(var t=0; t<numTabs; t++)
- {
- var label = params[t*3+1];
- var prompt = params[t*3+2];
- var content = params[t*3+3];
- var tab = createTiddlyButton(tabset,label,prompt,this.onClickTab,"tab tabUnselected");
- tab.setAttribute("tab",label);
- tab.setAttribute("content",content);
- tab.title = prompt;
- if(config.options[cookie] == label)
- validTab = true;
- }
- if(!validTab)
- config.options[cookie] = params[1];
- place.appendChild(wrapper);
- this.switchTab(tabset,config.options[cookie]);
-}
-
-config.macros.tabs.onClickTab = function(e)
-{
- config.macros.tabs.switchTab(this.parentNode,this.getAttribute("tab"));
- return false;
-}
-
-config.macros.tabs.switchTab = function(tabset,tab)
-{
- var cookie = tabset.getAttribute("cookie");
- var theTab = null
- var nodes = tabset.childNodes;
- for(var t=0; t<nodes.length; t++)
- if(nodes[t].getAttribute && nodes[t].getAttribute("tab") == tab)
- {
- theTab = nodes[t];
- theTab.className = "tab tabSelected";
- }
- else
- nodes[t].className = "tab tabUnselected"
- if(theTab)
- {
- if(tabset.nextSibling && tabset.nextSibling.className == "tabContents")
- tabset.parentNode.removeChild(tabset.nextSibling);
- var tabContent = createTiddlyElement(null,"div",null,"tabContents");
- tabset.parentNode.insertBefore(tabContent,tabset.nextSibling);
- var contentTitle = theTab.getAttribute("content");
- wikify(store.getTiddlerText(contentTitle),tabContent,null,store.getTiddler(contentTitle));
- if(cookie)
- {
- config.options[cookie] = tab;
- saveOptionCookie(cookie);
- }
- }
-}
-
-// <<gradient [[tiddler name]] vert|horiz rgb rgb rgb rgb... >>
-config.macros.gradient.handler = function(place,macroName,params,wikifier)
-{
- var terminator = ">>";
- var panel;
- if(wikifier)
- panel = createTiddlyElement(place,"div",null,"gradient");
- else
- panel = place;
- panel.style.position = "relative";
- panel.style.overflow = "hidden";
- panel.style.zIndex = "0";
- var t;
- if(wikifier)
- {
- var styles = config.formatterHelpers.inlineCssHelper(wikifier);
- config.formatterHelpers.applyCssHelper(panel,styles);
- }
- var colours = [];
- for(t=1; t<params.length; t++)
- {
- var c = new RGB(params[t]);
- if(c)
- colours.push(c);
- }
- drawGradient(panel,params[0] != "vert",colours);
- if(wikifier)
- wikifier.subWikify(panel,terminator);
- if(document.all)
- {
- panel.style.height = "100%";
- panel.style.width = "100%";
- }
-}
-
-config.macros.message.handler = function(place,macroName,params)
-{
- if(params[0])
- {
- var m = config;
- var p = params[0].split(".");
- for(var t=0; t<p.length; t++)
- {
- if(p[t] in m)
- m = m[p[t]];
- else
- break;
- }
- createTiddlyText(place,m.toString().format(params.splice(1)));
- }
-}
-
-config.macros.view.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- if((tiddler instanceof Tiddler) && params[0])
- {
- var value = store.getValue(tiddler,params[0]);
- if(value != undefined)
- switch(params[1])
- {
- case undefined:
- highlightify(value,place,highlightHack);
- break;
- case "link":
- createTiddlyLink(place,value,true);
- break;
- case "wikified":
- wikify(value,place,highlightHack,tiddler);
- break;
- case "date":
- value = Date.convertFromYYYYMMDDHHMM(value);
- if(params[2])
- createTiddlyText(place,value.formatString(params[2]));
- else
- createTiddlyText(place,value);
- break;
- }
- }
-}
-
-config.macros.edit.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- var field = params[0];
- if((tiddler instanceof Tiddler) && field)
- {
- story.setDirty(tiddler.title,true);
- if(field != "text")
- {
- var e = createTiddlyElement(null,"input");
- if(tiddler.isReadOnly())
- e.setAttribute("readOnly","readOnly");
- e.setAttribute("edit",field);
- e.setAttribute("type","text");
- var v = store.getValue(tiddler,field);
- if(!v)
- v = "";
- e.value = v;
- e.setAttribute("size","40");
- e.setAttribute("autocomplete","off");
- place.appendChild(e);
- }
- else
- {
- var wrapper1 = createTiddlyElement(null,"fieldset",null,"fieldsetFix");
- var wrapper2 = createTiddlyElement(wrapper1,"div");
- var e = createTiddlyElement(wrapper2,"textarea");
- if(tiddler.isReadOnly())
- e.setAttribute("readOnly","readOnly");
- var v = store.getValue(tiddler,field);
- if(!v)
- v = "";
- e.value = v;
- var rows = 10;
- var lines = v.match(/\n/mg);
- var maxLines = Math.max(parseInt(config.options.txtMaxEditRows),5);
- if(lines != null && lines.length > rows)
- rows = lines.length + 5;
- rows = Math.min(rows,maxLines);
- e.setAttribute("rows",rows);
- e.setAttribute("edit",field);
- place.appendChild(wrapper1);
- }
- }
-}
-
-config.macros.tagChooser.onClick = function(e)
-{
- if(!e) var e = window.event;
- var lingo = config.views.editor.tagChooser;
- var popup = Popup.create(this);
- var tags = store.getTags();
- if(tags.length == 0)
- createTiddlyText(createTiddlyElement(popup,"li"),lingo.popupNone);
- for(var t=0; t<tags.length; t++)
- {
- var theTag = createTiddlyButton(createTiddlyElement(popup,"li"),tags[t][0],lingo.tagTooltip.format([tags[t][0]]),config.macros.tagChooser.onTagClick);
- theTag.setAttribute("tag",tags[t][0]);
- theTag.setAttribute("tiddler", this.getAttribute("tiddler"));
- }
- Popup.show(popup,false);
- e.cancelBubble = true;
- if(e.stopPropagation) e.stopPropagation();
- return(false);
-}
-
-config.macros.tagChooser.onTagClick = function(e)
-{
- if(!e) var e = window.event;
- var tag = this.getAttribute("tag");
- var title = this.getAttribute("tiddler");
- if(!readOnly)
- story.setTiddlerTag(title,tag,0);
- return(false);
-}
-
-config.macros.tagChooser.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- if(tiddler instanceof Tiddler)
- {
- var title = tiddler.title;
- var lingo = config.views.editor.tagChooser;
- var btn = createTiddlyButton(place,lingo.text,lingo.tooltip,this.onClick);
- btn.setAttribute("tiddler", title);
- }
-}
-
-// Create a toolbar command button
-// place - parent DOM element
-// command - reference to config.commands[] member -or- name of member
-// tiddler - reference to tiddler that toolbar applies to
-// theClass - the class to give the button
-config.macros.toolbar.createCommand = function(place,commandName,tiddler,theClass)
-{
- if(typeof commandName != "string")
- {
- var c = null;
- for(var t in config.commands)
- if(config.commands[t] == commandName)
- c = t;
- commandName = c;
- }
- if((tiddler instanceof Tiddler) && (typeof commandName == "string"))
- {
- var title = tiddler.title;
- var command = config.commands[commandName];
- var ro = tiddler.isReadOnly();
- var shadow = store.isShadowTiddler(title) && !store.tiddlerExists(title);
- var text = ro && command.readOnlyText ? command.readOnlyText : command.text;
- var tooltip = ro && command.readOnlyTooltip ? command.readOnlyTooltip : command.tooltip;
- if((!ro || (ro && !command.hideReadOnly)) && !(shadow && command.hideShadow))
-
- {
- var btn = createTiddlyButton(null,text,tooltip,this.onClickCommand);
- btn.setAttribute("commandName", commandName);
- btn.setAttribute("tiddler", title);
- if(theClass)
- addClass(btn,theClass);
- place.appendChild(btn);
- }
- }
-}
-
-config.macros.toolbar.onClickCommand = function(e)
-{
- if(!e) var e = window.event;
- var command = config.commands[this.getAttribute("commandName")];
- return command.handler(e,this,this.getAttribute("tiddler"));
-}
-
-// Invoke the first command encountered from a given place that is tagged with a specified class
-config.macros.toolbar.invokeCommand = function(place,theClass,event)
-{
- var children = place.getElementsByTagName("a")
- for(var t=0; t<children.length; t++)
- {
- var c = children[t];
- if(hasClass(c,theClass) && c.getAttribute && c.getAttribute("commandName"))
- {
- if(c.onclick instanceof Function)
- c.onclick.call(c,event);
- break;
- }
- }
-}
-
-config.macros.toolbar.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- for(var t=0; t<params.length; t++)
- {
- var c = params[t];
- var theClass = "";
- switch(c.substr(0,1))
- {
- case "+":
- theClass = "defaultCommand";
- c = c.substr(1);
- break;
- case "-":
- theClass = "cancelCommand";
- c = c.substr(1);
- break;
- }
- if(c in config.commands)
- this.createCommand(place,c,tiddler,theClass);
- }
-}
-
-config.macros.plugins.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- var e = createTiddlyElement(place,"div");
- e.setAttribute("refresh","macro");
- e.setAttribute("macroName","plugins");
- e.setAttribute("params",paramString);
- this.refresh(e,paramString);
-}
-
-config.macros.plugins.refresh = function(place,params)
-{
- var selectedRows = [];
- ListView.forEachSelector(place,function(e,rowName) {
- if(e.checked)
- selectedRows.push(e.getAttribute("rowName"));
- });
- removeChildren(place);
- params = params.parseParams("anon");
- var plugins = installedPlugins.slice(0);
- var t,tiddler,p;
- var configTiddlers = store.getTaggedTiddlers("systemConfig");
- for(t=0; t<configTiddlers.length; t++)
- {
- tiddler = configTiddlers[t];
- if(plugins.findByField("title",tiddler.title) == null)
- {
- p = getPluginInfo(tiddler);
- p.executed = false;
- p.log.splice(0,0,this.skippedText);
- plugins.push(p);
- }
- }
- for(t=0; t<plugins.length; t++)
- {
- var p = plugins[t];
- p.forced = p.tiddler.isTagged("systemConfigForce");
- p.disabled = p.tiddler.isTagged("systemConfigDisable");
- p.Selected = selectedRows.indexOf(plugins[t].title) != -1;
- }
- if(plugins.length == 0)
- createTiddlyElement(place,"em",null,null,this.noPluginText);
- else
- ListView.create(place,plugins,this.listViewTemplate,this.onSelectCommand);
-}
-
-config.macros.plugins.onSelectCommand = function(command,rowNames)
-{
- var t;
- switch(command)
- {
- case "remove":
- for(t=0; t<rowNames.length; t++)
- store.setTiddlerTag(rowNames[t],false,"systemConfig");
- break;
- case "delete":
- if(rowNames.length > 0 && confirm(config.macros.plugins.confirmDeleteText.format([rowNames.join(", ")])))
- {
- for(t=0; t<rowNames.length; t++)
- {
- store.removeTiddler(rowNames[t]);
- story.closeTiddler(rowNames[t],true,false);
- }
- }
- break;
- }
- if(config.options.chkAutoSave)
- saveChanges(true);
-}
-
-config.macros.refreshDisplay.handler = function(place)
-{
- createTiddlyButton(place,this.label,this.prompt,this.onClick);
-}
-
-config.macros.refreshDisplay.onClick = function(e)
-{
- refreshAll();
- return false;
-}
-
-config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler)
-{
- if(readOnly)
- {
- createTiddlyElement(place,"div",null,"marked",this.readOnlyWarning);
- return;
- }
- var importer = createTiddlyElement(null,"div",null,"importTiddler wizard");
- createTiddlyElement(importer,"h1",null,null,this.wizardTitle);
- createTiddlyElement(importer,"h2",null,"step1",this.step1);
- var step = createTiddlyElement(importer,"div",null,"wizardStep");
- createTiddlyText(step,this.step1prompt);
- var input = createTiddlyElement(null,"input",null,"txtOptionInput");
- input.type = "text";
- input.size = 50;
- step.appendChild(input);
- importer.inputBox = input;
- createTiddlyElement(step,"br");
- createTiddlyText(step,this.step1promptFile);
- var fileInput = createTiddlyElement(null,"input",null,"txtOptionInput");
- fileInput.type = "file";
- fileInput.size = 50;
- fileInput.onchange = this.onBrowseChange;
- fileInput.onkeyup = this.onBrowseChange;
- step.appendChild(fileInput);
- createTiddlyElement(step,"br");
- createTiddlyText(step,this.step1promptFeeds);
- var feeds = this.getFeeds([{caption: this.step1feedPrompt, name: ""}]);
- createTiddlyDropDown(step,this.onFeedChange,feeds);
- createTiddlyElement(step,"br");
- createTiddlyButton(step,this.fetchLabel,this.fetchPrompt,this.onFetch,null,null,null);
- place.appendChild(importer);
-}
-
-config.macros.importTiddlers.getFeeds = function(feeds)
-{
- var tagged = store.getTaggedTiddlers("contentPublisher","title");
- for(var t=0; t<tagged.length; t++)
- feeds.push({caption: tagged[t].title, name: store.getTiddlerSlice(tagged[t].title,"URL")});
- return feeds;
-}
-
-config.macros.importTiddlers.onFeedChange = function(e)
-{
- var importer = findRelated(this,"importTiddler","className","parentNode");
- importer.inputBox.value = this.value;
- this.selectedIndex = 0;
-}
-
-config.macros.importTiddlers.onBrowseChange = function(e)
-{
- var importer = findRelated(this,"importTiddler","className","parentNode");
- importer.inputBox.value = "file://" + this.value;
-}
-
-config.macros.importTiddlers.onFetch = function(e)
-{
- var importer = findRelated(this,"importTiddler","className","parentNode");
- var url = importer.inputBox.value;
- var cutoff = findRelated(importer.firstChild,"step2","className","nextSibling");
- while(cutoff)
- {
- var temp = cutoff.nextSibling;
- cutoff.parentNode.removeChild(cutoff);
- cutoff = temp;
- }
- createTiddlyElement(importer,"h2",null,"step2",config.macros.importTiddlers.step2);
- var step = createTiddlyElement(importer,"div",null,"wizardStep",config.macros.importTiddlers.step2Text.format([url]));
- loadRemoteFile(url,config.macros.importTiddlers.onLoad,importer);
-}
-
-config.macros.importTiddlers.onLoad = function(status,params,responseText,url,xhr)
-{
- if(!status)
- {
- displayMessage(this.fetchError);
- return;
- }
- var importer = params;
- // Check that the tiddler we're in hasn't been closed - doesn't work on IE
-// var p = importer;
-// while(p.parentNode)
-// p = p.parentNode;
-// if(!(p instanceof HTMLDocument))
-// return;
- // Crack out the content - (should be refactored)
- var posOpeningDiv = responseText.indexOf(startSaveArea);
- var limitClosingDiv = responseText.indexOf("<!--POST-BODY-START--"+">");
- var posClosingDiv = responseText.lastIndexOf(endSaveArea,limitClosingDiv == -1 ? responseText.length : limitClosingDiv);
- if((posOpeningDiv == -1) || (posClosingDiv == -1))
- {
- alert(config.messages.invalidFileError.format([url]));
- return;
- }
- var content = "<html><body>" + responseText.substring(posOpeningDiv,posClosingDiv + endSaveArea.length) + "</body></html>";
- // Create the iframe
- var iframe = document.createElement("iframe");
- iframe.style.display = "none";
- importer.insertBefore(iframe,importer.firstChild);
- var doc = iframe.document;
- if(iframe.contentDocument)
- doc = iframe.contentDocument; // For NS6
- else if(iframe.contentWindow)
- doc = iframe.contentWindow.document; // For IE5.5 and IE6
- // Put the content in the iframe
- doc.open();
- doc.writeln(content);
- doc.close();
- // Load the content into a TiddlyWiki() object
- var storeArea = doc.getElementById("storeArea");
- var importStore = new TiddlyWiki();
- importStore.loadFromDiv(storeArea,"store");
- // Get rid of the iframe
- iframe.parentNode.removeChild(iframe);
- // Extract data for the listview
- var tiddlers = [];
- importStore.forEachTiddler(function(title,tiddler)
- {
- var t = {};
- t.title = title;
- t.modified = tiddler.modified;
- t.modifier = tiddler.modifier;
- t.text = tiddler.text.substr(0,50);
- t.tags = tiddler.tags;
- tiddlers.push(t);
- });
- // Display the listview
- createTiddlyElement(importer,"h2",null,"step3",config.macros.importTiddlers.step3);
- var step = createTiddlyElement(importer,"div",null,"wizardStep");
- ListView.create(step,tiddlers,config.macros.importTiddlers.listViewTemplate,config.macros.importTiddlers.onSelectCommand);
- // Save the importer
- importer.store = importStore;
-}
-
-config.macros.importTiddlers.onSelectCommand = function(listView,command,rowNames)
-{
- var importer = findRelated(listView,"importTiddler","className","parentNode");
- switch(command)
- {
- case "import":
- config.macros.importTiddlers.doImport(importer,rowNames);
- break;
- }
- if(config.options.chkAutoSave)
- saveChanges(true);
-}
-
-config.macros.importTiddlers.doImport = function(importer,rowNames)
-{
- var theStore = importer.store;
- var overwrite = new Array();
- var t;
- for(t=0; t<rowNames.length; t++)
- {
- if(store.tiddlerExists(rowNames[t]))
- overwrite.push(rowNames[t]);
- }
- if(overwrite.length > 0)
- if(!confirm(this.confirmOverwriteText.format([overwrite.join(", ")])))
- return;
- for(t=0; t<rowNames.length; t++)
- {
- var inbound = theStore.fetchTiddler(rowNames[t]);
- store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags);
- store.fetchTiddler(inbound.title).created = inbound.created;
- store.notify(rowNames[t],false);
- }
- store.notifyAll();
- store.setDirty(true);
- createTiddlyElement(importer,"h2",null,"step4",this.step4.format([rowNames.length]));
- var step = createTiddlyElement(importer,"div",null,"wizardStep");
- for(t=0; t<rowNames.length; t++)
- {
- createTiddlyLink(step,rowNames[t],true);
- createTiddlyElement(step,"br");
- }
- createTiddlyElement(importer,"h2",null,"step5",this.step5);
-}
-// ---------------------------------------------------------------------------------
-// Menu and toolbar commands
-// ---------------------------------------------------------------------------------
-
-config.commands.closeTiddler.handler = function(event,src,title)
-{
- story.closeTiddler(title,true,event.shiftKey || event.altKey);
- return false;
-}
-
-config.commands.closeOthers.handler = function(event,src,title)
-{
- story.closeAllTiddlers(title);
- return false;
-}
-
-config.commands.editTiddler.handler = function(event,src,title)
-{
- clearMessage();
- story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
- story.focusTiddler(title,"text");
- return false;
-}
-
-config.commands.saveTiddler.handler = function(event,src,title)
-{
- var newTitle = story.saveTiddler(title,event.shiftKey);
- if(newTitle)
- story.displayTiddler(null,newTitle);
- return false;
-}
-
-config.commands.cancelTiddler.handler = function(event,src,title)
-{
- if(story.hasChanges(title) && !readOnly)
- if(!confirm(this.warning.format([title])))
- return false;
- story.setDirty(title,false);
- story.displayTiddler(null,title);
- return false;
-}
-
-config.commands.deleteTiddler.handler = function(event,src,title)
-{
- var deleteIt = true;
- if (config.options.chkConfirmDelete)
- deleteIt = confirm(this.warning.format([title]));
- if (deleteIt)
- {
- store.removeTiddler(title);
- story.closeTiddler(title,true,event.shiftKey || event.altKey);
- if(config.options.chkAutoSave)
- saveChanges();
- }
- return false;
-}
-
-config.commands.permalink.handler = function(event,src,title)
-{
- var t = encodeURIComponent(String.encodeTiddlyLink(title));
- if(window.location.hash != t)
- window.location.hash = t;
- return false;
-}
-
-config.commands.references.handler = function(event,src,title)
-{
- var popup = Popup.create(src);
- if(popup)
- {
- var references = store.getReferringTiddlers(title);
- var c = false;
- for(var r=0; r<references.length; r++)
- if(references[r].title != title && !references[r].isTagged("excludeLists"))
- {
- createTiddlyLink(createTiddlyElement(popup,"li"),references[r].title,true);
- c = true;
- }
- if(!c)
- createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),this.popupNone);
- }
- Popup.show(popup,false);
- event.cancelBubble = true;
- if (event.stopPropagation) event.stopPropagation();
- return false;
-}
-
-config.commands.jump.handler = function(event,src,title)
-{
- var popup = Popup.create(src);
- if(popup)
- {
- story.forEachTiddler(function(title,element) {
- createTiddlyLink(createTiddlyElement(popup,"li"),title,true);
- });
- }
- Popup.show(popup,false);
- event.cancelBubble = true;
- if (event.stopPropagation) event.stopPropagation();
- return false;
-}
-
-// ---------------------------------------------------------------------------------
-// Tiddler() object
-// ---------------------------------------------------------------------------------
-
-function Tiddler()
-{
- this.title = null;
- this.text = null;
- this.modifier = null;
- this.modified = new Date();
- this.created = new Date();
- this.links = [];
- this.linksUpdated = false;
- this.tags = [];
- return this;
-}
-
-Tiddler.prototype.getLinks = function()
-{
- if(this.linksUpdated==false)
- this.changed();
- return this.links;
-}
-
-// Format the text for storage in an RSS item
-Tiddler.prototype.saveToRss = function(url)
-{
- var s = [];
- s.push("<item>");
- s.push("<title" + ">" + this.title.htmlEncode() + "</title" + ">");
- s.push("<description>" + wikifyStatic(this.text,null,this).htmlEncode() + "</description>");
- for(var t=0; t<this.tags.length; t++)
- s.push("<category>" + this.tags[t] + "</category>");
- s.push("<link>" + url + "#" + encodeURIComponent(String.encodeTiddlyLink(this.title)) + "</link>");
- s.push("<pubDate>" + this.modified.toGMTString() + "</pubDate>");
- s.push("</item>");
- return(s.join("\n"));
-}
-
-// Change the text and other attributes of a tiddler
-Tiddler.prototype.set = function(title,text,modifier,modified,tags,created,fields)
-{
- this.assign(title,text,modifier,modified,tags,created,fields);
- this.changed();
- return this;
-}
-
-// Change the text and other attributes of a tiddler without triggered a tiddler.changed() call
-Tiddler.prototype.assign = function(title,text,modifier,modified,tags,created,fields)
-{
- if(title != undefined)
- this.title = title;
- if(text != undefined)
- this.text = text;
- if(modifier != undefined)
- this.modifier = modifier;
- if(modified != undefined)
- this.modified = modified;
- if(created != undefined)
- this.created = created;
- if(fields != undefined)
- this.fields = fields;
- if(tags != undefined)
- this.tags = (typeof tags == "string") ? tags.readBracketedList() : tags;
- else if(this.tags == undefined)
- this.tags = [];
- return this;
-}
-
-// Get the tags for a tiddler as a string (space delimited, using [[brackets]] for tags containing spaces)
-Tiddler.prototype.getTags = function()
-{
- return String.encodeTiddlyLinkList(this.tags);
-}
-
-// Test if a tiddler carries a tag
-Tiddler.prototype.isTagged = function(tag)
-{
- return this.tags.indexOf(tag) != -1;
-}
-
-// Static method to convert "\n" to newlines, "\s" to "\"
-Tiddler.unescapeLineBreaks = function(text)
-{
- return text ? text.unescapeLineBreaks() : "";
-}
-
-// Convert newlines to "\n", "\" to "\s"
-Tiddler.prototype.escapeLineBreaks = function()
-{
- return this.text.escapeLineBreaks();
-}
-
-// Updates the secondary information (like links[] array) after a change to a tiddler
-Tiddler.prototype.changed = function()
-{
- this.links = [];
- var t = this.autoLinkWikiWords() ? 0 : 1;
- var tiddlerLinkRegExp = t==0 ? config.textPrimitives.tiddlerAnyLinkRegExp : config.textPrimitives.tiddlerForcedLinkRegExp;
- tiddlerLinkRegExp.lastIndex = 0;
- var formatMatch = tiddlerLinkRegExp.exec(this.text);
- while(formatMatch)
- {
- if(t==0 && formatMatch[1] && formatMatch[1] != this.title) // wikiWordLink
- {
- if(formatMatch.index > 0)
- {
- var preRegExp = new RegExp(config.textPrimitives.unWikiLink+"|"+config.textPrimitives.anyLetter,"mg");
- preRegExp.lastIndex = formatMatch.index-1;
- var preMatch = preRegExp.exec(this.text);
- if(preMatch.index != formatMatch.index-1)
- this.links.pushUnique(formatMatch[1]);
- }
- else
- this.links.pushUnique(formatMatch[1]);
- }
- else if(formatMatch[2-t] && (store.tiddlerExists(formatMatch[3-t]) || store.isShadowTiddler(formatMatch[3-t]))) // titledBrackettedLink
- this.links.pushUnique(formatMatch[3-t]);
- else if(formatMatch[4-t] && formatMatch[4-t] != this.title) // brackettedLink
- this.links.pushUnique(formatMatch[4-t]);
- // Do not add link if match urlPattern (formatMatch[5-t])
- formatMatch = tiddlerLinkRegExp.exec(this.text);
- }
- this.linksUpdated = true;
- return;
-}
-
-Tiddler.prototype.getSubtitle = function()
-{
- var theModifier = this.modifier;
- if(!theModifier)
- theModifier = config.messages.subtitleUnknown;
- var theModified = this.modified;
- if(theModified)
- theModified = theModified.toLocaleString();
- else
- theModified = config.messages.subtitleUnknown;
- return(config.messages.tiddlerLinkTooltip.format([this.title,theModifier,theModified]));
-}
-
-Tiddler.prototype.isReadOnly = function()
-{
- return readOnly;
-}
-
-Tiddler.prototype.autoLinkWikiWords = function()
-{
- return !(this.isTagged("systemConfig") || this.isTagged("excludeMissing"));
-}
-
-Tiddler.prototype.generateFingerprint = function()
-{
- return "0x" + Crypto.hexSha1Str(this.text);
-}
-
-// ---------------------------------------------------------------------------------
-// TiddlyWiki() object contains Tiddler()s
-// ---------------------------------------------------------------------------------
-
-function TiddlyWiki()
-{
- var tiddlers = {}; // Hashmap by name of tiddlers
- this.tiddlersUpdated = false;
- this.namedNotifications = []; // Array of {name:,notify:} of notification functions
- this.notificationLevel = 0;
- this.slices = {}; // map tiddlerName->(map sliceName->sliceValue). Lazy.
- this.clear = function() {
- tiddlers = {};
- this.setDirty(false);
- };
- this.fetchTiddler = function(title) {
- return tiddlers[title];
- };
- this.deleteTiddler = function(title) {
- delete this.slices[title];
- delete tiddlers[title];
- };
- this.addTiddler = function(tiddler) {
- delete this.slices[tiddler.title];
- tiddlers[tiddler.title] = tiddler;
- };
- this.forEachTiddler = function(callback) {
- for(var t in tiddlers)
- {
- var tiddler = tiddlers[t];
- if(tiddler instanceof Tiddler)
- callback.call(this,t,tiddler);
- }
- };
-}
-
-// Set the dirty flag
-TiddlyWiki.prototype.setDirty = function(dirty)
-{
- this.dirty = dirty;
-}
-
-TiddlyWiki.prototype.isDirty = function()
-{
- return this.dirty;
-}
-
-TiddlyWiki.prototype.suspendNotifications = function()
-{
- this.notificationLevel--;
-}
-
-TiddlyWiki.prototype.resumeNotifications = function()
-{
- this.notificationLevel++;
-}
-
-// Invoke the notification handlers for a particular tiddler
-TiddlyWiki.prototype.notify = function(title,doBlanket)
-{
- if(!this.notificationLevel)
- for(var t=0; t<this.namedNotifications.length; t++)
- {
- var n = this.namedNotifications[t];
- if((n.name == null && doBlanket) || (n.name == title))
- n.notify(title);
- }
-}
-
-// Invoke the notification handlers for all tiddlers
-TiddlyWiki.prototype.notifyAll = function()
-{
- if(!this.notificationLevel)
- for(var t=0; t<this.namedNotifications.length; t++)
- {
- var n = this.namedNotifications[t];
- if(n.name)
- n.notify(n.name);
- }
-}
-
-// Add a notification handler to a tiddler
-TiddlyWiki.prototype.addNotification = function(title,fn)
-{
- for (var i=0; i<this.namedNotifications.length; i++)
- if((this.namedNotifications[i].name == title) && (this.namedNotifications[i].notify == fn))
- return this;
- this.namedNotifications.push({name: title, notify: fn});
- return this;
-}
-
-TiddlyWiki.prototype.removeTiddler = function(title)
-{
- var tiddler = this.fetchTiddler(title);
- if(tiddler)
- {
- this.deleteTiddler(title);
- this.notify(title,true);
- this.setDirty(true);
- }
-}
-
-TiddlyWiki.prototype.tiddlerExists = function(title)
-{
- var t = this.fetchTiddler(title);
- return (t != undefined);
-}
-
-TiddlyWiki.prototype.isShadowTiddler = function(title)
-{
- return typeof config.shadowTiddlers[title] == "string";
-}
-
-TiddlyWiki.prototype.getTiddler = function(title)
-{
- var t = this.fetchTiddler(title);
- if(t != undefined)
- return t;
- else
- return null;
-}
-
-TiddlyWiki.prototype.getTiddlerText = function(title,defaultText)
-{
- var tiddler = this.fetchTiddler(title);
- if(tiddler)
- return tiddler.text;
- if(!title)
- return defaultText;
- var pos = title.indexOf(config.textPrimitives.sliceSeparator);
- if(pos != -1)
- {
- var slice = this.getTiddlerSlice(title.substr(0,pos),title.substr(pos + config.textPrimitives.sliceSeparator.length));
- if(slice)
- return slice;
- }
- if(this.isShadowTiddler(title))
- return config.shadowTiddlers[title];
- if(defaultText != undefined)
- return defaultText;
- return null;
-}
-
-TiddlyWiki.prototype.slicesRE = /(?:[\'\/]*~?(\w+)[\'\/]*\:[\'\/]*\s*(.*?)\s*$)|(?:\|[\'\/]*~?(\w+)\:?[\'\/]*\|\s*(.*?)\s*\|)/gm
-
-// @internal
-TiddlyWiki.prototype.calcAllSlices = function(title)
-{
- var slices = {};
- var text = this.getTiddlerText(title,"");
- this.slicesRE.lastIndex = 0;
- do
- {
- var m = this.slicesRE.exec(text);
- if (m)
- {
- if (m[1])
- slices[m[1]] = m[2];
- else
- slices[m[3]] = m[4];
- }
- }
- while(m);
- return slices;
-}
-
-// Returns the slice of text of the given name
-//#
-//# A text slice is a substring in the tiddler's text that is defined
-//# either like this
-//# aName: textSlice
-//# or
-//# |aName:| textSlice |
-//# or
-//# |aName| textSlice |
-//#
-//# In the text the name (or name:) may be decorated with '' or //. I.e.
-//# this would also a possible text slice:
-//#
-//# |''aName:''| textSlice |
-//#
-//# @param name should only contain "word characters" (i.e. "a-ZA-Z_0-9")
-//# @return [may be undefined] the (trimmed) text of the specified slice.
-TiddlyWiki.prototype.getTiddlerSlice = function(title,sliceName)
-{
- var slices = this.slices[title];
- if (!slices) {
- slices = this.calcAllSlices(title);
- this.slices[title] = slices;
- }
- return slices[sliceName];
-}
-
-// Build an hashmap of the specified named slices of a tiddler
-TiddlyWiki.prototype.getTiddlerSlices = function(title,sliceNames)
-{
- var r = {};
- for(var t=0; t<sliceNames.length; t++)
- {
- var slice = this.getTiddlerSlice(title,sliceNames[t]);
- if(slice)
- r[sliceNames[t]] = slice;
- }
- return r;
-}
-
-TiddlyWiki.prototype.getRecursiveTiddlerText = function(title,defaultText,depth)
-{
- var bracketRegExp = new RegExp("(?:\\[\\[([^\\]]+)\\]\\])","mg");
- var text = this.getTiddlerText(title,null);
- if(text == null)
- return defaultText;
- var textOut = [];
- var lastPos = 0;
- do {
- var match = bracketRegExp.exec(text);
- if(match)
- {
- textOut.push(text.substr(lastPos,match.index-lastPos));
- if(match[1])
- {
- if(depth <= 0)
- textOut.push(match[1]);
- else
- textOut.push(this.getRecursiveTiddlerText(match[1],"[[" + match[1] + "]]",depth-1));
- }
- lastPos = match.index + match[0].length;
- }
- else
- textOut.push(text.substr(lastPos));
- } while(match);
- return(textOut.join(""));
-}
-
-TiddlyWiki.prototype.setTiddlerTag = function(title,status,tag)
-{
- var tiddler = this.fetchTiddler(title);
- if(tiddler)
- {
- var t = tiddler.tags.indexOf(tag);
- if(t != -1)
- tiddler.tags.splice(t,1);
- if(status)
- tiddler.tags.push(tag);
- tiddler.changed();
- this.notify(title,true);
- this.setDirty(true);
- }
-}
-
-TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields)
-{
- var tiddler = this.fetchTiddler(title);
- var created;
- if(tiddler)
- {
- created = tiddler.created; // Preserve created date
- this.deleteTiddler(title);
- }
- else
- {
- tiddler = new Tiddler();
- created = modified;
- }
- tiddler.set(newTitle,newBody,modifier,modified,tags,created,fields);
- this.addTiddler(tiddler);
- if(title != newTitle)
- this.notify(title,true);
- this.notify(newTitle,true);
- this.setDirty(true);
- return tiddler;
-}
-
-TiddlyWiki.prototype.createTiddler = function(title)
-{
- var tiddler = this.fetchTiddler(title);
- if(!tiddler)
- {
- tiddler = new Tiddler();
- tiddler.title = title;
- this.addTiddler(tiddler);
- this.setDirty(true);
- }
- return tiddler;
-}
-
-// Load contents of a tiddlywiki from an HTML DIV
-TiddlyWiki.prototype.loadFromDiv = function(src,idPrefix,noUpdate)
-{
- this.idPrefix = idPrefix;
- var storeElem = (typeof src == "string") ? document.getElementById(src) : src;
- var tiddlers = this.getLoader().loadTiddlers(this,storeElem.childNodes);
- this.setDirty(false);
- if(!noUpdate)
- {
- for(var i = 0;i<tiddlers.length; i++)
- tiddlers[i].changed();
- }
-}
-
-TiddlyWiki.prototype.updateTiddlers = function()
-{
- this.tiddlersUpdated = true;
- this.forEachTiddler(function(title,tiddler) {
- tiddler.changed();
- });
-}
-
-// Return all tiddlers formatted as an HTML string
-TiddlyWiki.prototype.allTiddlersAsHtml = function()
-{
- return store.getSaver().externalize(store);
-}
-
-// Return an array of tiddlers matching a search regular expression
-TiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag)
-{
- var candidates = this.reverseLookup("tags",excludeTag,false);
- var results = [];
- for(var t=0; t<candidates.length; t++)
- {
- if((candidates[t].title.search(searchRegExp) != -1) || (candidates[t].text.search(searchRegExp) != -1))
- results.push(candidates[t]);
- }
- if(!sortField)
- sortField = "title";
- results.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});
- return results;
-}
-
-// Return an array of all the tags in use. Each member of the array is another array where [0] is the name of the tag and [1] is the number of occurances
-TiddlyWiki.prototype.getTags = function()
-{
- var results = [];
- this.forEachTiddler(function(title,tiddler) {
- for(var g=0; g<tiddler.tags.length; g++)
- {
- var tag = tiddler.tags[g];
- var f = false;
- for(var c=0; c<results.length; c++)
- if(results[c][0] == tag)
- {
- f = true;
- results[c][1]++;
- }
- if(!f)
- results.push([tag,1]);
- }
- });
- results.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
- return results;
-}
-
-// Return an array of the tiddlers that are tagged with a given tag
-TiddlyWiki.prototype.getTaggedTiddlers = function(tag,sortField)
-{
- return this.reverseLookup("tags",tag,true,sortField);
-}
-
-// Return an array of the tiddlers that link to a given tiddler
-TiddlyWiki.prototype.getReferringTiddlers = function(title,unusedParameter,sortField)
-{
- if(!this.tiddlersUpdated)
- this.updateTiddlers();
- return this.reverseLookup("links",title,true,sortField);
-}
-
-// Return an array of the tiddlers that do or do not have a specified entry in the specified storage array (ie, "links" or "tags")
-// lookupMatch == true to match tiddlers, false to exclude tiddlers
-TiddlyWiki.prototype.reverseLookup = function(lookupField,lookupValue,lookupMatch,sortField)
-{
- var results = [];
- this.forEachTiddler(function(title,tiddler) {
- var f = !lookupMatch;
- for(var lookup=0; lookup<tiddler[lookupField].length; lookup++)
- if(tiddler[lookupField][lookup] == lookupValue)
- f = lookupMatch;
- if(f)
- results.push(tiddler);
- });
- if(!sortField)
- sortField = "title";
- results.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});
- return results;
-}
-
-// Return the tiddlers as a sorted array
-TiddlyWiki.prototype.getTiddlers = function(field,excludeTag)
-{
- var results = [];
- this.forEachTiddler(function(title,tiddler) {
- if(excludeTag == undefined || !tiddler.isTagged(excludeTag))
- results.push(tiddler);
- });
- if(field)
- results.sort(function(a,b) {return a[field] < b[field] ? -1 : (a[field] == b[field] ? 0 : +1);});
- return results;
-}
-
-// Return array of names of tiddlers that are referred to but not defined
-TiddlyWiki.prototype.getMissingLinks = function(sortField)
-{
- if(!this.tiddlersUpdated)
- this.updateTiddlers();
- var results = [];
- this.forEachTiddler(function (title,tiddler) {
- for(var n=0; n<tiddler.links.length;n++)
- {
- var link = tiddler.links[n];
- if(this.fetchTiddler(link) == null && !this.isShadowTiddler(link))
- results.pushUnique(link);
- }
- });
- results.sort();
- return results;
-}
-
-// Return an array of names of tiddlers that are defined but not referred to
-TiddlyWiki.prototype.getOrphans = function()
-{
- var results = [];
- this.forEachTiddler(function (title,tiddler) {
- if(this.getReferringTiddlers(title).length == 0 && !tiddler.isTagged("excludeLists"))
- results.push(title);
- });
- results.sort();
- return results;
-}
-
-// Return an array of names of all the shadow tiddlers
-TiddlyWiki.prototype.getShadowed = function()
-{
- var results = [];
- for(var t in config.shadowTiddlers)
- if(typeof config.shadowTiddlers[t] == "string")
- results.push(t);
- results.sort();
- return results;
-}
-
-// Resolves a Tiddler reference or tiddler title into a Tiddler object, or null if it doesn't exist
-TiddlyWiki.prototype.resolveTiddler = function(tiddler)
-{
- var t = (typeof tiddler == 'string') ? this.getTiddler(tiddler) : tiddler;
- return t instanceof Tiddler ? t : null;
-}
-
-TiddlyWiki.prototype.getLoader = function()
-{
- if (!this.loader)
- this.loader = new TW21Loader();
- return this.loader;
-}
-
-TiddlyWiki.prototype.getSaver = function()
-{
- if (!this.saver)
- this.saver = new TW21Saver();
- return this.saver;
-}
-
-// Returns true if path is a valid field name (path),
-// i.e. a sequence of identifiers, separated by '.'
-TiddlyWiki.isValidFieldName = function (name) {
- var match = /[a-zA-Z_]\w*(\.[a-zA-Z_]\w*)*/.exec(name);
- return match && (match[0] == name);
-}
-
-// Throws an exception when name is not a valid field name.
-TiddlyWiki.checkFieldName = function(name) {
- if (!TiddlyWiki.isValidFieldName(name))
- throw config.messages.invalidFieldName.format([name]);
-}
-
-function StringFieldAccess(n, readOnly) {
- this.set = readOnly
- ? function(t,v) {if (v != t[n]) throw config.messages.fieldCannotBeChanged.format([n]);}
- : function(t,v) {if (v != t[n]) {t[n] = v; return true;}};
- this.get = function(t) {return t[n];};
-}
-
-function DateFieldAccess(n) {
- this.set = function(t,v) {
- var d = v instanceof Date ? v : Date.convertFromYYYYMMDDHHMM(v);
- if (d != t[n]) {
- t[n] = d; return true;
- }
- };
- this.get = function(t) {return t[n].convertToYYYYMMDDHHMM();}
-}
-
-function LinksFieldAccess(n) {
- this.set = function(t,v) {
- var s = (typeof v == "string") ? v.readBracketedList() : v;
- if (s.toString() != t[n].toString()) {
- t[n] = s; return true;
- }
- };
- this.get = function(t) {return String.encodeTiddlyLinkList(t[n]);}
-}
-
-TiddlyWiki.standardFieldAccess = {
- // The set functions return true when setting the data has changed the value.
-
- "title": new StringFieldAccess("title", true),
- // Handle the "tiddler" field name as the title
- "tiddler": new StringFieldAccess("title", true),
-
- "text": new StringFieldAccess("text"),
- "modifier": new StringFieldAccess("modifier"),
- "modified": new DateFieldAccess("modified"),
- "created": new DateFieldAccess("created"),
- "tags": new LinksFieldAccess("tags")
-};
-
-TiddlyWiki.isStandardField = function(name) {
- return TiddlyWiki.standardFieldAccess[name] != undefined;
-}
-
-// Sets the value of the given field of the tiddler to the value.
-// Setting an ExtendedField's value to null or undefined removes the field.
-// Setting a namespace to undefined removes all fields of that namespace.
-// The fieldName is case-insensitive.
-// All values will be converted to a string value.
-TiddlyWiki.prototype.setValue = function(tiddler, fieldName, value) {
- TiddlyWiki.checkFieldName(fieldName);
- var t = this.resolveTiddler(tiddler);
- if (!t)
- return;
-
- fieldName = fieldName.toLowerCase();
-
- var isRemove = (value === undefined) || (value === null);
-
- if (!t.fields)
- t.fields = {};
-
- var accessor = TiddlyWiki.standardFieldAccess[fieldName];
- if (accessor) {
- if (isRemove)
- // don't remove StandardFields
- return;
- var h = TiddlyWiki.standardFieldAccess[fieldName];
- if (!h.set(t, value))
- return;
-
- } else {
- var oldValue = t.fields[fieldName];
-
- if (isRemove) {
- if (oldValue !== undefined) {
- // deletes a single field
- delete t.fields[fieldName];
- } else {
- // no concrete value is defined for the fieldName
- // so we guess this is a namespace path.
-
- // delete all fields in a namespace
- var re = new RegExp('^'+fieldName+'\\.');
- var dirty = false;
- for (var n in t.fields) {
- if (n.match(re)) {
- delete t.fields[n];
- dirty = true;
- }
- }
- if (!dirty)
- return
- }
-
- } else {
- // the "normal" set case. value is defined (not null/undefined)
- // For convenience provide a nicer conversion Date->String
- value = value instanceof Date
- ? value.convertToYYYYMMDDHHMMSSMMM()
- : String(value);
- if (oldValue == value)
- return;
- t.fields[fieldName] = value;
- }
- }
-
- // When we are here the tiddler/store really was changed.
- this.notify(t.title,true);
- if (!fieldName.match(/^temp\./))
- this.setDirty(true);
-}
-
-// Returns the value of the given field of the tiddler.
-// The fieldName is case-insensitive.
-// Will only return String values (or undefined).
-TiddlyWiki.prototype.getValue = function(tiddler, fieldName) {
- var t = this.resolveTiddler(tiddler);
- if (!t)
- return undefined;
-
- fieldName = fieldName.toLowerCase();
-
- var accessor = TiddlyWiki.standardFieldAccess[fieldName];
- if (accessor) {
- return accessor.get(t);
- }
-
- return t.fields ? t.fields[fieldName] : undefined;
-}
-
-// Calls the callback function for every field in the tiddler.
-//
-// When callback function returns a non-false value the iteration stops
-// and that value is returned.
-//
-// The order of the fields is not defined.
-//
-// @param callback a function(tiddler, fieldName, value).
-//
-TiddlyWiki.prototype.forEachField = function(tiddler, callback, onlyExtendedFields) {
- var t = this.resolveTiddler(tiddler);
- if (!t)
- return undefined;
-
- if (t.fields) {
- for (var n in t.fields) {
- var result = callback(t, n, t.fields[n]);
- if (result)
- return result;
- }
- }
-
- if (onlyExtendedFields)
- return undefined;
-
- for (var n in TiddlyWiki.standardFieldAccess) {
- if (n == "tiddler")
- // even though the "title" field can also be referenced through the name "tiddler"
- // we only visit this field once.
- continue;
-
- var result = callback(t, n, TiddlyWiki.standardFieldAccess[n].get(t));
- if (result)
- return result;
- }
-
- return undefined;
-};
-// ---------------------------------------------------------------------------------
-// Story functions
-// ---------------------------------------------------------------------------------
-
-// A story is a HTML div containing a sequence of tiddlers that can be manipulated
-// container - id of containing element
-// idPrefix - string prefix prepended to title to make ids for tiddlers in this story
-function Story(container,idPrefix)
-{
- this.container = container;
- this.idPrefix = idPrefix;
- this.highlightRegExp = null;
-}
-
-// Iterate through all the tiddlers in a story
-// fn - callback function to be called for each tiddler. Arguments are:
-// tiddler - reference to Tiddler object
-// element - reference to tiddler display element
-Story.prototype.forEachTiddler = function(fn)
-{
- var place = document.getElementById(this.container);
- if(!place)
- return;
- var e = place.firstChild;
- while(e)
- {
- var n = e.nextSibling;
- var title = e.getAttribute("tiddler");
- fn.call(this,title,e);
- e = n;
- }
-}
-
-// Display several tiddlers given their titles in an array. Parameters same as displayTiddler(), except:
-// titles - array of string titles
-Story.prototype.displayTiddlers = function(srcElement,titles,template,animate,slowly)
-{
- for(var t = titles.length-1;t>=0;t--)
- this.displayTiddler(srcElement,titles[t],template,animate,slowly);
-}
-
-// Display a given tiddler with a given template. If the tiddler is already displayed but with a different
-// template, it is switched to the specified template
-// srcElement - reference to element from which this one is being opened -or-
-// special positions "top", "bottom"
-// title - title of tiddler to display
-// template - the name of the tiddler containing the template -or-
-// one of the constants DEFAULT_VIEW_TEMPLATE and DEFAULT_EDIT_TEMPLATE -or-
-// null or undefined to indicate the current template if there is one, DEFAULT_VIEW_TEMPLATE if not
-// animate - whether to perform animations
-// slowly - whether to perform animations in slomo
-Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly)
-{
- var place = document.getElementById(this.container);
- var tiddlerElem = document.getElementById(this.idPrefix + title);
- if(tiddlerElem)
- this.refreshTiddler(title,template);
- else
- {
- var before = this.positionTiddler(srcElement);
- tiddlerElem = this.createTiddler(place,before,title,template);
- }
- if(srcElement && typeof srcElement !== "string")
- {
- if(anim && config.options.chkAnimate && (animate == undefined || animate == true))
- anim.startAnimating(new Cascade(title,srcElement,tiddlerElem,slowly),new Scroller(tiddlerElem,slowly));
- else
- window.scrollTo(0,ensureVisible(tiddlerElem));
- }
-}
-
-// Figure out the appropriate position for a newly opened tiddler
-// srcElement - reference to the element containing the link to the tiddler -or-
-// special positions "top", "bottom"
-// returns - reference to the tiddler that the new one should appear before (null for the bottom of the story)
-Story.prototype.positionTiddler = function(srcElement)
-{
- var place = document.getElementById(this.container);
- var before;
- if(typeof srcElement == "string")
- {
- switch(srcElement)
- {
- case "top":
- before = place.firstChild;
- break;
- case "bottom":
- before = null;
- break;
- }
- }
- else
- {
- var after = this.findContainingTiddler(srcElement);
- if(after == null)
- before = place.firstChild;
- else if(after.nextSibling)
- before = after.nextSibling;
- else
- before = null;
- }
- return before;
-}
-
-// Create a tiddler frame at the appropriate place in a story column
-// place - reference to parent element
-// before - null, or reference to element before which to insert new tiddler
-// title - title of new tiddler
-// template - the name of the tiddler containing the template or one of the constants DEFAULT_VIEW_TEMPLATE and DEFAULT_EDIT_TEMPLATE
-Story.prototype.createTiddler = function(place,before,title,template)
-{
- var tiddlerElem = createTiddlyElement(null,"div",this.idPrefix + title,"tiddler");
- tiddlerElem.setAttribute("refresh","tiddler");
- place.insertBefore(tiddlerElem,before);
- this.refreshTiddler(title,template);
- return tiddlerElem;
-}
-
-// Overridable for choosing the name of the template to apply for a tiddler
-Story.prototype.chooseTemplateForTiddler = function(title,template)
-{
- if(!template)
- template = DEFAULT_VIEW_TEMPLATE;
- if(template == DEFAULT_VIEW_TEMPLATE || template == DEFAULT_EDIT_TEMPLATE)
- template = config.tiddlerTemplates[template];
- return template;
-}
-
-// Overridable for extracting the text of a template from a tiddler
-Story.prototype.getTemplateForTiddler = function(title,template,tiddler)
-{
- return store.getRecursiveTiddlerText(template,null,10);
-}
-
-// Apply a template to an existing tiddler if it is not already displayed using that template
-// title - title of tiddler to update
-// template - the name of the tiddler containing the template or one of the constants DEFAULT_VIEW_TEMPLATE and DEFAULT_EDIT_TEMPLATE
-// force - if true, forces the refresh even if the template hasn't changedd
-Story.prototype.refreshTiddler = function(title,template,force)
-{
- var tiddlerElem = document.getElementById(this.idPrefix + title);
- if(tiddlerElem)
- {
- if(tiddlerElem.getAttribute("dirty") == "true" && !force)
- return tiddlerElem;
- template = this.chooseTemplateForTiddler(title,template);
- var currTemplate = tiddlerElem.getAttribute("template");
- if((template != currTemplate) || force)
- {
- var tiddler = store.getTiddler(title);
- if(!tiddler)
- {
- tiddler = new Tiddler();
- if(store.isShadowTiddler(title))
- tiddler.set(title,store.getTiddlerText(title),config.views.wikified.shadowModifier,version.date,[],version.date);
- else
- {
- var text = template=="EditTemplate"
- ? config.views.editor.defaultText.format([title])
- : config.views.wikified.defaultText.format([title]);
- tiddler.set(title,text,config.views.wikified.defaultModifier,version.date,[],version.date);
- }
- }
- tiddlerElem.setAttribute("tags",tiddler.tags.join(" "));
- tiddlerElem.setAttribute("tiddler",title);
- tiddlerElem.setAttribute("template",template);
- var me = this;
- tiddlerElem.onmouseover = this.onTiddlerMouseOver;
- tiddlerElem.onmouseout = this.onTiddlerMouseOut;
- tiddlerElem.ondblclick = this.onTiddlerDblClick;
- tiddlerElem[window.event?"onkeydown":"onkeypress"] = this.onTiddlerKeyPress;
- var html = this.getTemplateForTiddler(title,template,tiddler);
- tiddlerElem.innerHTML = html;
- applyHtmlMacros(tiddlerElem,tiddler);
- if(store.getTaggedTiddlers(title).length > 0)
- addClass(tiddlerElem,"isTag");
- else
- removeClass(tiddlerElem,"isTag");
- if(!store.tiddlerExists(title))
- {
- if(store.isShadowTiddler(title))
- addClass(tiddlerElem,"shadow");
- else
- addClass(tiddlerElem,"missing");
- }
- else
- {
- removeClass(tiddlerElem,"shadow");
- removeClass(tiddlerElem,"missing");
- }
- }
- }
- return tiddlerElem;
-}
-
-// Refresh all tiddlers in the Story
-Story.prototype.refreshAllTiddlers = function()
-{
- var place = document.getElementById(this.container);
- var e = place.firstChild;
- if(!e)
- return;
- this.refreshTiddler(e.getAttribute("tiddler"),e.getAttribute("template"),true);
- while((e = e.nextSibling) != null)
- this.refreshTiddler(e.getAttribute("tiddler"),e.getAttribute("template"),true);
-}
-
-// Default tiddler onmouseover/out event handlers
-Story.prototype.onTiddlerMouseOver = function(e)
-{
- if(window.addClass instanceof Function)
- addClass(this,"selected");
-}
-
-Story.prototype.onTiddlerMouseOut = function(e)
-{
- if(window.removeClass instanceof Function)
- removeClass(this,"selected");
-}
-
-// Default tiddler ondblclick event handler
-Story.prototype.onTiddlerDblClick = function(e)
-{
- if(!e) var e = window.event;
- var theTarget = resolveTarget(e);
- if(theTarget && theTarget.nodeName.toLowerCase() != "input" && theTarget.nodeName.toLowerCase() != "textarea")
- {
- if(document.selection && document.selection.empty)
- document.selection.empty();
- config.macros.toolbar.invokeCommand(this,"defaultCommand",e);
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- return true;
- }
- else
- return false;
-}
-
-Story.prototype.onTiddlerKeyPress = function(e)
-{
- if(!e) var e = window.event;
- clearMessage();
- var consume = false;
- var title = this.getAttribute("tiddler");
- var target = resolveTarget(e);
- switch(e.keyCode)
- {
- case 9: // Tab
- if(config.options.chkInsertTabs && target.tagName.toLowerCase() == "textarea")
- {
- replaceSelection(target,String.fromCharCode(9));
- consume = true;
- }
- if(config.isOpera)
- {
- target.onblur = function()
- {
- this.focus();
- this.onblur = null;
- }
- }
- break;
- case 13: // Ctrl-Enter
- case 10: // Ctrl-Enter on IE PC
- case 77: // Ctrl-Enter is "M" on some platforms
- if(e.ctrlKey)
- {
- blurElement(this);
- config.macros.toolbar.invokeCommand(this,"defaultCommand",e);
- consume = true;
- }
- break;
- case 27: // Escape
- blurElement(this);
- config.macros.toolbar.invokeCommand(this,"cancelCommand",e);
- consume = true;
- break;
- }
- e.cancelBubble = consume;
- if(consume)
- {
- if(e.stopPropagation) e.stopPropagation(); // Stop Propagation
- e.returnValue = true; // Cancel The Event in IE
- if(e.preventDefault ) e.preventDefault(); // Cancel The Event in Moz
- }
- return(!consume);
-};
-
-// Returns the specified field (input or textarea element) in a tiddler, otherwise the first edit field it finds
-// or null if it found no edit field at all
-Story.prototype.getTiddlerField = function(title,field)
-{
- var tiddlerElem = document.getElementById(this.idPrefix + title);
- var e = null;
- if(tiddlerElem != null)
- {
- var children = tiddlerElem.getElementsByTagName("*");
- for (var t=0; t<children.length; t++)
- {
- var c = children[t];
- if(c.tagName.toLowerCase() == "input" || c.tagName.toLowerCase() == "textarea")
- {
- if(!e)
- e = c;
- if(c.getAttribute("edit") == field)
- e = c;
- }
- }
- }
- return e;
-}
-
-// Focus a specified tiddler. Attempts to focus the specified field, otherwise the first edit field it finds
-Story.prototype.focusTiddler = function(title,field)
-{
- var e = this.getTiddlerField(title,field);
- if(e)
- {
- e.focus();
- e.select();
- }
-}
-
-// Ensures that a specified tiddler does not have the focus
-Story.prototype.blurTiddler = function(title)
-{
- var tiddlerElem = document.getElementById(this.idPrefix + title);
- if(tiddlerElem != null && tiddlerElem.focus && tiddlerElem.blur)
- {
- tiddlerElem.focus();
- tiddlerElem.blur();
- }
-}
-
-// Adds a specified value to the edit controls (if any) of a particular
-// array-formatted field of a particular tiddler (eg "tags")
-// title - name of tiddler
-// tag - value of field, without any [[brackets]]
-// mode - +1 to add the tag, -1 to remove it, 0 to toggle it
-// field - name of field (eg "tags")
-Story.prototype.setTiddlerField = function(title,tag,mode,field)
-{
- var c = story.getTiddlerField(title,field);
-
- var tags = c.value.readBracketedList();
- tags.setItem(tag,mode);
- c.value = String.encodeTiddlyLinkList(tags);
-}
-
-// The same as setTiddlerField but preset to the "tags" field
-Story.prototype.setTiddlerTag = function(title,tag,mode)
-{
- Story.prototype.setTiddlerField(title,tag,mode,"tags");
-}
-
-// Close a specified tiddler
-// title - name of tiddler to close
-// animate - whether to perform animations
-// slowly - whether to perform animations in slomo
-Story.prototype.closeTiddler = function(title,animate,slowly)
-{
- var tiddlerElem = document.getElementById(this.idPrefix + title);
- if(tiddlerElem != null)
- {
- clearMessage();
- this.scrubTiddler(tiddlerElem);
- if(anim && config.options.chkAnimate && animate)
- anim.startAnimating(new Slider(tiddlerElem,false,slowly,"all"));
- else
- tiddlerElem.parentNode.removeChild(tiddlerElem);
- }
-}
-
-// Scrub IDs from a tiddler. This is so that the 'ghost' of a tiddler while it is being closed
-// does not interfere with things
-// tiddler - reference to the tiddler element
-Story.prototype.scrubTiddler = function(tiddlerElem)
-{
- tiddlerElem.id = null;
-}
-
-// Set the 'dirty' flag of a tiddler
-// title - title of tiddler to change
-// dirty - new boolean status of flag
-Story.prototype.setDirty = function(title,dirty)
-{
- var tiddlerElem = document.getElementById(this.idPrefix + title);
- if(tiddlerElem != null)
- tiddlerElem.setAttribute("dirty",dirty ? "true" : "false");
-}
-
-// Is a particular tiddler dirty (with unsaved changes)?
-Story.prototype.isDirty = function(title)
-{
- var tiddlerElem = document.getElementById(this.idPrefix + title);
- if(tiddlerElem != null)
- return tiddlerElem.getAttribute("dirty") == "true";
- return null;
-}
-
-// Determine whether any open tiddler are dirty
-Story.prototype.areAnyDirty = function()
-{
- var r = false;
- this.forEachTiddler(function(title,element) {
- if(this.isDirty(title))
- r = true;
- });
- return r;
-}
-
-// Close all tiddlers in the story
-Story.prototype.closeAllTiddlers = function(exclude)
-{
- clearMessage();
- this.forEachTiddler(function(title,element) {
- if((title != exclude) && element.getAttribute("dirty") != "true")
- this.closeTiddler(title);
- });
- window.scrollTo(0,0);
-}
-
-// Check if there are any tiddlers in the story
-Story.prototype.isEmpty = function()
-{
- var place = document.getElementById(this.container);
- return(place && place.firstChild == null);
-}
-
-// Perform a search and display the result
-// text - text to search for
-// useCaseSensitive - true for case sensitive matching
-// useRegExp - true to interpret text as a RegExp
-Story.prototype.search = function(text,useCaseSensitive,useRegExp)
-{
- this.closeAllTiddlers();
- highlightHack = new RegExp(useRegExp ? text : text.escapeRegExp(),useCaseSensitive ? "mg" : "img");
- var matches = store.search(highlightHack,"title","excludeSearch");
- var titles = [];
- for(var t=matches.length-1; t>=0; t--)
- titles.push(matches[t].title);
- this.displayTiddlers(null,titles);
- highlightHack = null;
- var q = useRegExp ? "/" : "'";
- if(matches.length > 0)
- displayMessage(config.macros.search.successMsg.format([titles.length.toString(),q + text + q]));
- else
- displayMessage(config.macros.search.failureMsg.format([q + text + q]));
-}
-
-// Determine if the specified element is within a tiddler in this story
-// e - reference to an element
-// returns: reference to a tiddler element or null if none
-Story.prototype.findContainingTiddler = function(e)
-{
- while(e && !hasClass(e,"tiddler"))
- e = e.parentNode;
- return(e);
-}
-
-// Gather any saveable fields from a tiddler element
-// e - reference to an element to scan recursively
-// fields - object to contain gathered field values
-Story.prototype.gatherSaveFields = function(e,fields)
-{
- if(e && e.getAttribute)
- {
- var f = e.getAttribute("edit");
- if(f)
- fields[f] = e.value.replace(/\r/mg,"");;
- if(e.hasChildNodes())
- {
- var c = e.childNodes;
- for(var t=0; t<c.length; t++)
- this.gatherSaveFields(c[t],fields)
- }
- }
-}
-
-// Determine whether a tiddler has any edit fields, and if so if their values have been changed
-// title - name of tiddler
-Story.prototype.hasChanges = function(title)
-{
- var e = document.getElementById(this.idPrefix + title);
- if(e != null)
- {
- var fields = {};
- this.gatherSaveFields(e,fields);
- var tiddler = store.fetchTiddler(title);
- if (!tiddler)
- return false;
- for(var n in fields)
- if (store.getValue(title,n) != fields[n])
- return true;
- }
- return false;
-}
-
-// Save any open edit fields of a tiddler and updates the display as necessary
-// title - name of tiddler
-// minorUpdate - true if the modified date shouldn't be updated
-// returns: title of saved tiddler, or null if not saved
-Story.prototype.saveTiddler = function(title,minorUpdate)
-{
- var tiddlerElem = document.getElementById(this.idPrefix + title);
- if(tiddlerElem != null)
- {
- var fields = {};
- this.gatherSaveFields(tiddlerElem,fields);
- var newTitle = fields.title ? fields.title : title;
- if(store.tiddlerExists(newTitle) && newTitle != title)
- {
- if(confirm(config.messages.overwriteWarning.format([newTitle.toString()])))
- this.closeTiddler(newTitle,false,false);
- else
- return null;
- }
- tiddlerElem.id = this.idPrefix + newTitle;
- tiddlerElem.setAttribute("tiddler",newTitle);
- tiddlerElem.setAttribute("template",DEFAULT_VIEW_TEMPLATE);
- tiddlerElem.setAttribute("dirty","false");
- if(config.options.chkForceMinorUpdate)
- minorUpdate = !minorUpdate;
- var newDate = new Date();
- store.saveTiddler(title,newTitle,fields.text,config.options.txtUserName,minorUpdate ? undefined : newDate,fields.tags);
- for (var n in fields)
- if (!TiddlyWiki.isStandardField(n))
- store.setValue(newTitle,n,fields[n]);
- if(config.options.chkAutoSave)
- saveChanges();
- return newTitle;
- }
- return null;
-}
-
-Story.prototype.permaView = function()
-{
- var links = [];
- this.forEachTiddler(function(title,element) {
- links.push(String.encodeTiddlyLink(title));
- });
- var t = encodeURIComponent(links.join(" "));
- if(t == "")
- t = "#";
- if(window.location.hash != t)
- window.location.hash = t;
-}
-
-// ---------------------------------------------------------------------------------
-// Message area
-// ---------------------------------------------------------------------------------
-
-function getMessageDiv()
-{
- var msgArea = document.getElementById("messageArea");
- if(!msgArea)
- return null;
- if(!msgArea.hasChildNodes())
- createTiddlyButton(createTiddlyElement(msgArea,"div",null,"messageToolbar"),
- config.messages.messageClose.text,
- config.messages.messageClose.tooltip,
- clearMessage);
- msgArea.style.display = "block";
- return createTiddlyElement(msgArea,"div");
-}
-
-function displayMessage(text,linkText)
-{
- var e = getMessageDiv();
- if(!e)
- {
- alert(text);
- return;
- }
- if(linkText)
- {
- var link = createTiddlyElement(e,"a",null,null,text);
- link.href = linkText;
- link.target = "_blank";
- }
- else
- e.appendChild(document.createTextNode(text));
-}
-
-function clearMessage()
-{
- var msgArea = document.getElementById("messageArea");
- if(msgArea)
- {
- removeChildren(msgArea);
- msgArea.style.display = "none";
- }
- return false;
-}
-
-// ---------------------------------------------------------------------------------
-// Refresh mechanism
-// ---------------------------------------------------------------------------------
-
-config.refreshers = {
- link: function(e,changeList)
- {
- var title = e.getAttribute("tiddlyLink");
- refreshTiddlyLink(e,title);
- return true;
- },
-
- tiddler: function(e,changeList)
- {
- var title = e.getAttribute("tiddler");
- var template = e.getAttribute("template");
- if(changeList && changeList.indexOf(title) != -1 && !story.isDirty(title))
- story.refreshTiddler(title,template,true);
- else
- refreshElements(e,changeList);
- return true;
- },
-
- content: function(e,changeList)
- {
- var title = e.getAttribute("tiddler");
- var force = e.getAttribute("force");
- if(force != null || changeList == null || changeList.indexOf(title) != -1)
- {
- removeChildren(e);
- wikify(store.getTiddlerText(title,title),e);
- return true;
- }
- else
- return false;
- },
-
- macro: function(e,changeList)
- {
- var macro = e.getAttribute("macroName");
- var params = e.getAttribute("params");
- if(macro)
- macro = config.macros[macro];
- if(macro && macro.refresh)
- macro.refresh(e,params);
- return true;
- }
-};
-
-function refreshElements(root,changeList)
-{
- var nodes = root.childNodes;
- for(var c=0; c<nodes.length; c++)
- {
- var e = nodes[c],type;
- if(e.getAttribute)
- type = e.getAttribute("refresh");
- else
- type = null;
- var refresher = config.refreshers[type];
- var refreshed = false;
- if(refresher != undefined)
- refreshed = refresher(e,changeList);
- if(e.hasChildNodes() && !refreshed)
- refreshElements(e,changeList);
- }
-}
-
-function applyHtmlMacros(root,tiddler)
-{
- var e = root.firstChild;
- while(e)
- {
- var nextChild = e.nextSibling;
- if(e.getAttribute)
- {
- var macro = e.getAttribute("macro");
- if(macro)
- {
- var params = "";
- var p = macro.indexOf(" ");
- if(p != -1)
- {
- params = macro.substr(p+1);
- macro = macro.substr(0,p);
- }
- invokeMacro(e,macro,params,null,tiddler);
- }
- }
- if(e.hasChildNodes())
- applyHtmlMacros(e,tiddler);
- e = nextChild;
- }
-}
-
-function refreshPageTemplate(title)
-{
- var stash = createTiddlyElement(document.body,"div");
- stash.style.display = "none";
- var display = document.getElementById("tiddlerDisplay");
- var nodes,t;
- if(display)
- {
- nodes = display.childNodes;
- for(t=nodes.length-1; t>=0; t--)
- stash.appendChild(nodes[t]);
- }
- var wrapper = document.getElementById("contentWrapper");
- if(!title)
- title = "PageTemplate";
- var html = store.getRecursiveTiddlerText(title,null,10);
- wrapper.innerHTML = html;
- applyHtmlMacros(wrapper);
- refreshElements(wrapper);
- display = document.getElementById("tiddlerDisplay");
- removeChildren(display);
- if(!display)
- display = createTiddlyElement(wrapper,"div","tiddlerDisplay");
- nodes = stash.childNodes;
- for(t=nodes.length-1; t>=0; t--)
- display.appendChild(nodes[t]);
- stash.parentNode.removeChild(stash);
-}
-
-function refreshDisplay(hint)
-{
- var e = document.getElementById("contentWrapper");
- if(typeof hint == "string")
- hint = [hint];
- refreshElements(e,hint);
-}
-
-function refreshPageTitle()
-{
- document.title = wikifyPlain("SiteTitle") + " - " + wikifyPlain("SiteSubtitle");
-}
-
-function refreshStyles(title)
-{
- setStylesheet(title == null ? "" : store.getRecursiveTiddlerText(title,"",10),title);
-}
-
-function refreshColorPalette(title)
-{
- if(!startingUp)
- refreshAll();
-}
-
-function refreshAll()
-{
- refreshPageTemplate();
- refreshDisplay();
- refreshStyles("StyleSheetLayout");
- refreshStyles("StyleSheetColors");
- refreshStyles("StyleSheet");
- refreshStyles("StyleSheetPrint");
-}
-
-// ---------------------------------------------------------------------------------
-// Options cookie stuff
-// ---------------------------------------------------------------------------------
-
-function loadOptionsCookie()
-{
- if(safeMode)
- return;
- var cookies = document.cookie.split(";");
- for(var c=0; c<cookies.length; c++)
- {
- var p = cookies[c].indexOf("=");
- if(p != -1)
- {
- var name = cookies[c].substr(0,p).trim();
- var value = cookies[c].substr(p+1).trim();
- switch(name.substr(0,3))
- {
- case "txt":
- config.options[name] = unescape(value);
- break;
- case "chk":
- config.options[name] = value == "true";
- break;
- }
- }
- }
-}
-
-function saveOptionCookie(name)
-{
- if(safeMode)
- return;
- var c = name + "=";
- switch(name.substr(0,3))
- {
- case "txt":
- c += escape(config.options[name].toString());
- break;
- case "chk":
- c += config.options[name] ? "true" : "false";
- break;
- }
- c += "; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/";
- document.cookie = c;
-}
-
-// ---------------------------------------------------------------------------------
-// Saving
-// ---------------------------------------------------------------------------------
-
-var saveUsingSafari = false;
-
-var startSaveArea = '<div id="' + 'storeArea">'; // Split up into two so that indexOf() of this source doesn't find it
-var endSaveArea = '</d' + 'iv>';
-
-// If there are unsaved changes, force the user to confirm before exitting
-function confirmExit()
-{
- hadConfirmExit = true;
- if((store && store.isDirty && store.isDirty()) || (story && story.areAnyDirty && story.areAnyDirty()))
- return config.messages.confirmExit;
-}
-
-// Give the user a chance to save changes before exitting
-function checkUnsavedChanges()
-{
- if(store && store.isDirty && store.isDirty() && window.hadConfirmExit === false)
- {
- if(confirm(config.messages.unsavedChangesWarning))
- saveChanges();
- }
-}
-
-function updateMarkupBlock(s,blockName,tiddlerName)
-{
- return s.replaceChunk(
- "<!--%0-START-->".format([blockName]),
- "<!--%0-END-->".format([blockName]),
- "\n" + store.getRecursiveTiddlerText(tiddlerName,"") + "\n");
-}
-
-// Save this tiddlywiki with the pending changes
-function saveChanges(onlyIfDirty)
-{
- if(onlyIfDirty && !store.isDirty())
- return;
- clearMessage();
- // Get the URL of the document
- var originalPath = document.location.toString();
- // Check we were loaded from a file URL
- if(originalPath.substr(0,5) != "file:")
- {
- alert(config.messages.notFileUrlError);
- if(store.tiddlerExists(config.messages.saveInstructions))
- story.displayTiddler(null,config.messages.saveInstructions);
- return;
- }
- var localPath = getLocalPath(originalPath);
- // Load the original file
- var original = loadFile(localPath);
- if(original == null)
- {
- alert(config.messages.cantSaveError);
- if(store.tiddlerExists(config.messages.saveInstructions))
- story.displayTiddler(null,config.messages.saveInstructions);
- return;
- }
- // Locate the storeArea div's
- var posOpeningDiv = original.indexOf(startSaveArea);
- var limitClosingDiv = original.indexOf("<!--POST-BODY-START--"+">");
- var posClosingDiv = original.lastIndexOf(endSaveArea,limitClosingDiv == -1 ? original.length : limitClosingDiv);
- if((posOpeningDiv == -1) || (posClosingDiv == -1))
- {
- alert(config.messages.invalidFileError.format([localPath]));
- return;
- }
- // Save the backup
- if(config.options.chkSaveBackups)
- {
- var backupPath = getBackupPath(localPath);
- var backup = saveFile(backupPath,original);
- if(backup)
- displayMessage(config.messages.backupSaved,"file://" + backupPath);
- else
- alert(config.messages.backupFailed);
- }
- // Save Rss
- if(config.options.chkGenerateAnRssFeed)
- {
- var rssPath = localPath.substr(0,localPath.lastIndexOf(".")) + ".xml";
- var rssSave = saveFile(rssPath,convertUnicodeToUTF8(generateRss()));
- if(rssSave)
- displayMessage(config.messages.rssSaved,"file://" + rssPath);
- else
- alert(config.messages.rssFailed);
- }
- // Save empty template
- if(config.options.chkSaveEmptyTemplate)
- {
- var emptyPath,p;
- if((p = localPath.lastIndexOf("/")) != -1)
- emptyPath = localPath.substr(0,p) + "/empty.html";
- else if((p = localPath.lastIndexOf("\\")) != -1)
- emptyPath = localPath.substr(0,p) + "\\empty.html";
- else
- emptyPath = localPath + ".empty.html";
- var empty = original.substr(0,posOpeningDiv + startSaveArea.length) + original.substr(posClosingDiv);
- var emptySave = saveFile(emptyPath,empty);
- if(emptySave)
- displayMessage(config.messages.emptySaved,"file://" + emptyPath);
- else
- alert(config.messages.emptyFailed);
- }
- var save;
- try
- {
- // Save new file
- var revised = original.substr(0,posOpeningDiv + startSaveArea.length) + "\n" +
- convertUnicodeToUTF8(store.allTiddlersAsHtml()) + "\n" +
- original.substr(posClosingDiv);
- var newSiteTitle = convertUnicodeToUTF8((wikifyPlain("SiteTitle") + " - " + wikifyPlain("SiteSubtitle")).htmlEncode());
- revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
- revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
- revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
- revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
- revised = updateMarkupBlock(revised,"POST-BODY","MarkupPostBody");
- save = saveFile(localPath,revised);
- }
- catch (e)
- {
- showException(e);
- }
- if(save)
- {
- displayMessage(config.messages.mainSaved,"file://" + localPath);
- store.setDirty(false);
- }
- else
- alert(config.messages.mainFailed);
-}
-
-function getLocalPath(originalPath)
-{
- // Remove any location or query part of the URL
- var argPos = originalPath.indexOf("?");
- if(argPos != -1)
- originalPath = originalPath.substr(0,argPos);
- var hashPos = originalPath.indexOf("#");
- if(hashPos != -1)
- originalPath = originalPath.substr(0,hashPos);
- // Convert file://localhost/ to file:///
- if(originalPath.indexOf("file://localhost/") == 0)
- originalPath = "file://" + originalPath.substr(16);
- // Convert to a native file format assuming
- // "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
- // "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
- // "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
- // "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
- var localPath;
- if(originalPath.charAt(9) == ":") // pc local file
- localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
- else if(originalPath.indexOf("file://///") == 0) // FireFox pc network file
- localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
- else if(originalPath.indexOf("file:///") == 0) // mac/unix local file
- localPath = unescape(originalPath.substr(7));
- else if(originalPath.indexOf("file:/") == 0) // mac/unix local file
- localPath = unescape(originalPath.substr(5));
- else // pc network file
- localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");
- return localPath;
-}
-
-function getBackupPath(localPath)
-{
- var backSlash = true;
- var dirPathPos = localPath.lastIndexOf("\\");
- if(dirPathPos == -1)
- {
- dirPathPos = localPath.lastIndexOf("/");
- backSlash = false;
- }
- var backupFolder = config.options.txtBackupFolder;
- if(!backupFolder || backupFolder == "")
- backupFolder = ".";
- var backupPath = localPath.substr(0,dirPathPos) + (backSlash ? "\\" : "/") + backupFolder + localPath.substr(dirPathPos);
- backupPath = backupPath.substr(0,backupPath.lastIndexOf(".")) + "." + (new Date()).convertToYYYYMMDDHHMMSSMMM() + ".html";
- return backupPath;
-}
-
-function generateRss()
-{
- var s = [];
- var d = new Date();
- var u = store.getTiddlerText("SiteUrl");
- // Assemble the header
- s.push("<" + "?xml version=\"1.0\"?" + ">");
- s.push("<rss version=\"2.0\">");
- s.push("<channel>");
- s.push("<title" + ">" + wikifyPlain("SiteTitle").htmlEncode() + "</title" + ">");
- if(u)
- s.push("<link>" + u.htmlEncode() + "</link>");
- s.push("<description>" + wikifyPlain("SiteSubtitle").htmlEncode() + "</description>");
- s.push("<language>en-us</language>");
- s.push("<copyright>Copyright " + d.getFullYear() + " " + config.options.txtUserName.htmlEncode() + "</copyright>");
- s.push("<pubDate>" + d.toGMTString() + "</pubDate>");
- s.push("<lastBuildDate>" + d.toGMTString() + "</lastBuildDate>");
- s.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
- s.push("<generator>TiddlyWiki " + version.major + "." + version.minor + "." + version.revision + "</generator>");
- // The body
- var tiddlers = store.getTiddlers("modified","excludeLists");
- var n = config.numRssItems > tiddlers.length ? 0 : tiddlers.length-config.numRssItems;
- for (var t=tiddlers.length-1; t>=n; t--)
- s.push(tiddlers[t].saveToRss(u));
- // And footer
- s.push("</channel>");
- s.push("</rss>");
- // Save it all
- return s.join("\n");
-}
-
-
-// UTF-8 encoding rules:
-// 0x0000 - 0x007F: 0xxxxxxx
-// 0x0080 - 0x07FF: 110xxxxx 10xxxxxx
-// 0x0800 - 0xFFFF: 1110xxxx 10xxxxxx 10xxxxxx
-
-function convertUTF8ToUnicode(u)
-{
- if(window.netscape == undefined)
- return manualConvertUTF8ToUnicode(u);
- else
- return mozConvertUTF8ToUnicode(u);
-}
-
-function manualConvertUTF8ToUnicode(utf)
-{
- var uni = utf;
- var src = 0;
- var dst = 0;
- var b1, b2, b3;
- var c;
- while(src < utf.length)
- {
- b1 = utf.charCodeAt(src++);
- if(b1 < 0x80)
- dst++;
- else if(b1 < 0xE0)
- {
- b2 = utf.charCodeAt(src++);
- c = String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F));
- uni = uni.substring(0,dst++).concat(c,utf.substr(src));
- }
- else
- {
- b2 = utf.charCodeAt(src++);
- b3 = utf.charCodeAt(src++);
- c = String.fromCharCode(((b1 & 0xF) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F));
- uni = uni.substring(0,dst++).concat(c,utf.substr(src));
- }
- }
- return(uni);
-}
-
-function mozConvertUTF8ToUnicode(u)
-{
- try
- {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
- var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
- converter.charset = "UTF-8";
- }
- catch(e)
- {
- return manualConvertUTF8ToUnicode(u);
- } // fallback
- var s = converter.ConvertToUnicode(u);
- var fin = converter.Finish();
- return (fin.length > 0) ? s+fin : s;
-}
-
-function convertUnicodeToUTF8(s)
-{
- if(window.netscape == undefined)
- return manualConvertUnicodeToUTF8(s);
- else
- return mozConvertUnicodeToUTF8(s);
-}
-
-function manualConvertUnicodeToUTF8(s)
-{
- var re = /[^\u0000-\u007F]/g ;
- return s.replace(re, function($0) {return("&#" + $0.charCodeAt(0).toString() + ";");})
-}
-
-function mozConvertUnicodeToUTF8(s)
-{
- try
- {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
- var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
- converter.charset = "UTF-8";
- }
- catch(e)
- {
- return manualConvertUnicodeToUTF8(s);
- } // fallback
- var u = converter.ConvertFromUnicode(s);
- var fin = converter.Finish();
- if(fin.length > 0)
- return u + fin;
- else
- return u;
-}
-
-function saveFile(fileUrl, content)
-{
- var r = null;
- if((r == null) || (r == false))
- r = mozillaSaveFile(fileUrl, content);
- if((r == null) || (r == false))
- r = ieSaveFile(fileUrl, content);
- if((r == null) || (r == false))
- r = javaSaveFile(fileUrl, content);
- return(r);
-}
-
-function loadFile(fileUrl)
-{
- var r = null;
- if((r == null) || (r == false))
- r = mozillaLoadFile(fileUrl);
- if((r == null) || (r == false))
- r = ieLoadFile(fileUrl);
- if((r == null) || (r == false))
- r = javaLoadFile(fileUrl);
- return(r);
-}
-
-// Returns null if it can't do it, false if there's an error, true if it saved OK
-function ieSaveFile(filePath, content)
-{
- try
- {
- var fso = new ActiveXObject("Scripting.FileSystemObject");
- }
- catch(e)
- {
- //alert("Exception while attempting to save\n\n" + e.toString());
- return(null);
- }
- var file = fso.OpenTextFile(filePath,2,-1,0);
- file.Write(content);
- file.Close();
- return(true);
-}
-
-// Returns null if it can't do it, false if there's an error, or a string of the content if successful
-function ieLoadFile(filePath)
-{
- try
- {
- var fso = new ActiveXObject("Scripting.FileSystemObject");
- var file = fso.OpenTextFile(filePath,1);
- var content = file.ReadAll();
- file.Close();
- }
- catch(e)
- {
- //alert("Exception while attempting to load\n\n" + e.toString());
- return(null);
- }
- return(content);
-}
-
-// Returns null if it can't do it, false if there's an error, true if it saved OK
-function mozillaSaveFile(filePath, content)
-{
- if(window.Components)
- try
- {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
- var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(filePath);
- if (!file.exists())
- file.create(0, 0664);
- var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
- out.init(file, 0x20 | 0x02, 00004,null);
- out.write(content, content.length);
- out.flush();
- out.close();
- return(true);
- }
- catch(e)
- {
- //alert("Exception while attempting to save\n\n" + e);
- return(false);
- }
- return(null);
-}
-
-// Returns null if it can't do it, false if there's an error, or a string of the content if successful
-function mozillaLoadFile(filePath)
-{
- if(window.Components)
- try
- {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
- var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
- file.initWithPath(filePath);
- if (!file.exists())
- return(null);
- var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
- inputStream.init(file, 0x01, 00004, null);
- var sInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
- sInputStream.init(inputStream);
- return(sInputStream.read(sInputStream.available()));
- }
- catch(e)
- {
- //alert("Exception while attempting to load\n\n" + e);
- return(false);
- }
- return(null);
-}
-
-function javaUrlToFilename(url)
-{
- var f = "//localhost";
- if(url.indexOf(f) == 0)
- return url.substring(f.length);
- var i = url.indexOf(":");
- if(i > 0)
- return url.substring(i-1);
- return url;
-}
-
-function javaSaveFile(filePath, content)
-{
- try
- {
- if(document.applets["TiddlySaver"])
- return document.applets["TiddlySaver"].saveFile(javaUrlToFilename(filePath),"UTF-8",content);
- }
- catch(e)
- {
- }
- try
- {
- var s = new java.io.PrintStream(new java.io.FileOutputStream(javaUrlToFilename(filePath)));
- s.print(content);
- s.close();
- }
- catch(e)
- {
- return null;
- }
- return true;
-}
-
-function javaLoadFile(filePath)
-{
- try
- {
- if(document.applets["TiddlySaver"])
- return String(document.applets["TiddlySaver"].loadFile(javaUrlToFilename(filePath),"UTF-8"));
- }
- catch(e)
- {
- }
- var content = [];
- try
- {
- var r = new java.io.BufferedReader(new java.io.FileReader(javaUrlToFilename(filePath)));
- var line;
- while ((line = r.readLine()) != null)
- content.push(new String(line));
- r.close();
- }
- catch(e)
- {
- return null;
- }
- return content.join("\n");
-}
-
-
-// ---------------------------------------------------------------------------------
-// Remote HTTP requests
-// ---------------------------------------------------------------------------------
-
-// Load a file over http
-// url - the source url
-// callback - function to call when there's a response
-// params - parameter object that gets passed to the callback for storing it's state
-// Return value is the underlying XMLHttpRequest object, or 'null' if there was an error
-// Callback function is called like this:
-// callback(status,params,responseText,xhr)
-// status - true if OK, false if error
-// params - the parameter object provided to loadRemoteFile()
-// responseText - the text of the file
-// xhr - the underlying XMLHttpRequest object
-function loadRemoteFile(url,callback,params)
-{
- // Get an xhr object
- var x;
- try
- {
- x = new XMLHttpRequest(); // Modern
- }
- catch(e)
- {
- try
- {
- x = new ActiveXObject("Msxml2.XMLHTTP"); // IE 6
- }
- catch (e)
- {
- return null;
- }
- }
- // Install callback
- x.onreadystatechange = function()
- {
- if (x.readyState == 4)
- {
- if ((x.status == 0 || x.status == 200) && callback)
- {
- callback(true,params,x.responseText,url,x);
- }
- else
- callback(false,params,null,url,x);
- }
- }
- // Send request
- if(window.netscape && window.netscape.security && document.location.protocol.indexOf("http") == -1)
- window.netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
- try
- {
- url = url + (url.indexOf("?") < 0 ? "?" : "&") + "nocache=" + Math.random();
- x.open("GET",url,true);
- if (x.overrideMimeType)
- x.overrideMimeType("text/html");
- x.send(null);
- }
- catch (e)
- {
- alert("Error in send " + e);
- return null;
- }
- return x;
-}
-// ---------------------------------------------------------------------------------
-// TiddlyWiki-specific utility functions
-// ---------------------------------------------------------------------------------
-
-function createTiddlyButton(theParent,theText,theTooltip,theAction,theClass,theId,theAccessKey)
-{
- var theButton = document.createElement("a");
- if(theAction)
- {
- theButton.onclick = theAction;
- theButton.setAttribute("href","javascript:;");
- }
- if(theTooltip)
- theButton.setAttribute("title",theTooltip);
- if(theText)
- theButton.appendChild(document.createTextNode(theText));
- if(theClass)
- theButton.className = theClass;
- else
- theButton.className = "button";
- if(theId)
- theButton.id = theId;
- if(theParent)
- theParent.appendChild(theButton);
- if(theAccessKey)
- theButton.setAttribute("accessKey",theAccessKey);
- return(theButton);
-}
-
-function createTiddlyLink(place,title,includeText,theClass,isStatic)
-{
- var text = includeText ? title : null;
- var i = getTiddlyLinkInfo(title,theClass)
- var btn;
- if(isStatic)
- btn = createExternalLink(place,"#" + title);
- else
- btn = createTiddlyButton(place,text,i.subTitle,onClickTiddlerLink,i.classes);
- btn.setAttribute("refresh","link");
- btn.setAttribute("tiddlyLink",title);
- return(btn);
-}
-
-function refreshTiddlyLink(e,title)
-{
- var i = getTiddlyLinkInfo(title,e.className);
- e.className = i.classes;
- e.title = i.subTitle;
-}
-
-function getTiddlyLinkInfo(title,currClasses)
-{
- var classes = currClasses ? currClasses.split(" ") : [];
- classes.pushUnique("tiddlyLink");
- var tiddler = store.fetchTiddler(title);
- var subTitle;
- if(tiddler)
- {
- subTitle = tiddler.getSubtitle();
- classes.pushUnique("tiddlyLinkExisting");
- classes.remove("tiddlyLinkNonExisting");
- classes.remove("shadow");
- }
- else
- {
- classes.remove("tiddlyLinkExisting");
- classes.pushUnique("tiddlyLinkNonExisting");
- if(store.isShadowTiddler(title))
- {
- subTitle = config.messages.shadowedTiddlerToolTip.format([title]);
- classes.pushUnique("shadow");
- }
- else
- {
- subTitle = config.messages.undefinedTiddlerToolTip.format([title]);
- classes.remove("shadow");
- }
- }
- return {classes: classes.join(" "), subTitle: subTitle};
-}
-
-function createExternalLink(place,url)
-{
- var theLink = document.createElement("a");
- theLink.className = "externalLink";
- theLink.href = url;
- theLink.title = config.messages.externalLinkTooltip.format([url]);
- if(config.options.chkOpenInNewWindow)
- theLink.target = "_blank";
- place.appendChild(theLink);
- return(theLink);
-}
-
-// Event handler for clicking on a tiddly link
-function onClickTiddlerLink(e)
-{
- if (!e) var e = window.event;
- var theTarget = resolveTarget(e);
- var theLink = theTarget;
- var title = null;
- do {
- title = theLink.getAttribute("tiddlyLink");
- theLink = theLink.parentNode;
- } while(title == null && theLink != null);
- if(title)
- {
- var toggling = e.metaKey || e.ctrlKey;
- if(config.options.chkToggleLinks)
- toggling = !toggling;
- var opening;
- if(toggling && document.getElementById("tiddler" + title))
- story.closeTiddler(title,true,e.shiftKey || e.altKey);
- else
- story.displayTiddler(theTarget,title,null,true,e.shiftKey || e.altKey);
- }
- clearMessage();
- return(false);
-}
-
-// Create a button for a tag with a popup listing all the tiddlers that it tags
-function createTagButton(place,tag,excludeTiddler)
-{
- var theTag = createTiddlyButton(place,tag,config.views.wikified.tag.tooltip.format([tag]),onClickTag);
- theTag.setAttribute("tag",tag);
- if(excludeTiddler)
- theTag.setAttribute("tiddler",excludeTiddler);
- return(theTag);
-}
-
-// Event handler for clicking on a tiddler tag
-function onClickTag(e)
-{
- if (!e) var e = window.event;
- var theTarget = resolveTarget(e);
- var popup = Popup.create(this);
- var tag = this.getAttribute("tag");
- var title = this.getAttribute("tiddler");
- if(popup && tag)
- {
- var tagged = store.getTaggedTiddlers(tag);
- var titles = [];
- var li,r;
- for(r=0;r<tagged.length;r++)
- if(tagged[r].title != title)
- titles.push(tagged[r].title);
- var lingo = config.views.wikified.tag;
- if(titles.length > 0)
- {
- var openAll = createTiddlyButton(createTiddlyElement(popup,"li"),lingo.openAllText.format([tag]),lingo.openAllTooltip,onClickTagOpenAll);
- openAll.setAttribute("tag",tag);
- createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
- for(r=0; r<titles.length; r++)
- {
- createTiddlyLink(createTiddlyElement(popup,"li"),titles[r],true);
- }
- }
- else
- createTiddlyText(createTiddlyElement(popup,"li",null,"disabled"),lingo.popupNone.format([tag]));
- createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
- var h = createTiddlyLink(createTiddlyElement(popup,"li"),tag,false);
- createTiddlyText(h,lingo.openTag.format([tag]));
- }
- Popup.show(popup,false);
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- return(false);
-}
-
-// Event handler for 'open all' on a tiddler popup
-function onClickTagOpenAll(e)
-{
- if (!e) var e = window.event;
- var tag = this.getAttribute("tag");
- var tagged = store.getTaggedTiddlers(tag);
- var titles = [];
- for(var t=0; t<tagged.length; t++)
- titles.push(tagged[t].title);
- story.displayTiddlers(this,titles);
- return(false);
-}
-
-function onClickError(e)
-{
- if (!e) var e = window.event;
- var popup = Popup.create(this);
- var lines = this.getAttribute("errorText").split("\n");
- for(var t=0; t<lines.length; t++)
- createTiddlyElement(popup,"li",null,null,lines[t]);
- Popup.show(popup,false);
- e.cancelBubble = true;
- if (e.stopPropagation) e.stopPropagation();
- return false;
-}
-
-function createTiddlyDropDown(place,onchange,options)
-{
- var sel = createTiddlyElement(place,"select");
- sel.onchange = onchange;
- for(var t=0; t<options.length; t++)
- {
- var e = createTiddlyElement(sel,"option",null,null,options[t].caption);
- e.value = options[t].name;
- }
-}
-
-function createTiddlyError(place,title,text)
-{
- var btn = createTiddlyButton(place,title,null,onClickError,"errorButton");
- if (text) btn.setAttribute("errorText",text);
-}
-
-function merge(dst,src,preserveExisting)
-{
- for (p in src)
- if (!preserveExisting || dst[p] === undefined)
- dst[p] = src[p];
- return dst;
-}
-
-// Returns a string containing the description of an exception, optionally prepended by a message
-function exceptionText(e, message)
-{
- var s = e.description ? e.description : e.toString();
- return message ? "%0:\n%1".format([message, s]) : s;
-}
-
-// Displays an alert of an exception description with optional message
-function showException(e, message)
-{
- alert(exceptionText(e, message));
-}
-
-// ---------------------------------------------------------------------------------
-// Animation engine
-// ---------------------------------------------------------------------------------
-
-function Animator()
-{
- this.running = 0; // Incremented at start of each animation, decremented afterwards. If zero, the interval timer is disabled
- this.timerID = 0; // ID of the timer used for animating
- this.animations = []; // List of animations in progress
- return this;
-}
-
-// Start animation engine
-Animator.prototype.startAnimating = function() // Variable number of arguments
-{
- for(var t=0; t<arguments.length; t++)
- this.animations.push(arguments[t]);
- if(this.running == 0)
- {
- var me = this;
- this.timerID = window.setInterval(function() {me.doAnimate(me);},5);
- }
- this.running += arguments.length;
-}
-
-// Perform an animation engine tick, calling each of the known animation modules
-Animator.prototype.doAnimate = function(me)
-{
- var a = 0;
- while(a < me.animations.length)
- {
- var animation = me.animations[a];
- if(animation.tick())
- a++;
- else
- {
- me.animations.splice(a,1);
- if(--me.running == 0)
- window.clearInterval(me.timerID);
- }
- }
-}
-
-// Map a 0..1 value to 0..1, but slow down at the start and end
-Animator.slowInSlowOut = function(progress)
-{
- return(1-((Math.cos(progress * Math.PI)+1)/2));
-}
-
-// ---------------------------------------------------------------------------------
-// Cascade animation
-// ---------------------------------------------------------------------------------
-
-function Cascade(text,startElement,targetElement,slowly)
-{
- var winWidth = findWindowWidth();
- var winHeight = findWindowHeight();
- this.elements = [];
- this.startElement = startElement;
- this.startLeft = findPosX(this.startElement);
- this.startTop = findPosY(this.startElement);
- this.startWidth = Math.min(this.startElement.offsetWidth,winWidth);
- this.startHeight = Math.min(this.startElement.offsetHeight,winHeight);
- this.targetElement = targetElement;
- targetElement.style.position = "relative";
- targetElement.style.zIndex = 2;
- this.targetLeft = findPosX(this.targetElement);
- this.targetTop = findPosY(this.targetElement);
- this.targetWidth = Math.min(this.targetElement.offsetWidth,winWidth);
- this.targetHeight = Math.min(this.targetElement.offsetHeight,winHeight);
- this.progress = -1;
- this.steps = slowly ? config.cascadeSlow : config.cascadeFast;
- this.text = text;
- this.tick();
- return this;
-}
-
-Cascade.prototype.tick = function()
-{
- this.progress++;
- if(this.progress >= this.steps)
- {
- while(this.elements.length > 0)
- this.removeTail();
- this.targetElement.style.position = "static";
- this.targetElement.style.zIndex = "";
- return false;
- }
- else
- {
- if(this.elements.length > 0 && this.progress > config.cascadeDepth)
- this.removeTail();
- if(this.progress < (this.steps - config.cascadeDepth))
- {
- var f = Animator.slowInSlowOut(this.progress/(this.steps - config.cascadeDepth - 1));
- var e = createTiddlyElement(document.body,"div",null,"cascade",this.text);
- e.style.zIndex = 1;
- e.style.left = this.startLeft + (this.targetLeft-this.startLeft) * f + "px";
- e.style.top = this.startTop + (this.targetTop-this.startTop) * f + "px";
- e.style.width = this.startWidth + (this.targetWidth-this.startWidth) * f + "px";
- e.style.height = this.startHeight + (this.targetHeight-this.startHeight) * f + "px";
- e.style.display = "block";
- this.elements.push(e);
- }
- return true;
- }
-}
-
-Cascade.prototype.removeTail = function()
-{
- var e = this.elements[0];
- e.parentNode.removeChild(e);
- this.elements.shift();
-}
-
-// ---------------------------------------------------------------------------------
-// Scroller animation
-// ---------------------------------------------------------------------------------
-
-function Scroller(targetElement,slowly)
-{
- this.targetElement = targetElement;
- this.startScroll = findScrollY();
- this.targetScroll = ensureVisible(targetElement);
- this.progress = 0;
- this.step = slowly ? config.animSlow : config.animFast;
- return this;
-}
-
-Scroller.prototype.tick = function()
-{
- this.progress += this.step;
- if(this.progress > 1)
- {
- window.scrollTo(0,this.targetScroll);
- return false;
- }
- else
- {
- var f = Animator.slowInSlowOut(this.progress);
- window.scrollTo(0,this.startScroll + (this.targetScroll-this.startScroll) * f);
- return true;
- }
-}
-
-// ---------------------------------------------------------------------------------
-// Slider animation
-// ---------------------------------------------------------------------------------
-
-// deleteMode - "none", "all" [delete target element and it's children], [only] "children" [but not the target element]
-function Slider(element,opening,slowly,deleteMode)
-{
- this.element = element;
- element.style.display = "block";
- this.deleteMode = deleteMode;
- this.element.style.height = "auto";
- this.realHeight = element.offsetHeight;
- this.opening = opening;
- this.step = slowly ? config.animSlow : config.animFast;
- if(opening)
- {
- this.progress = 0;
- element.style.height = "0px";
- element.style.display = "block";
- }
- else
- {
- this.progress = 1;
- this.step = -this.step;
- }
- element.style.overflow = "hidden";
- return this;
-}
-
-Slider.prototype.stop = function()
-{
- if(this.opening)
- {
- this.element.style.height = "auto";
- this.element.style.opacity = 1;
- this.element.style.filter = "alpha(opacity:100)";
- }
- else
- {
- switch(this.deleteMode)
- {
- case "none":
- this.element.style.display = "none";
- break;
- case "all":
- this.element.parentNode.removeChild(this.element);
- break;
- case "children":
- removeChildren(this.element);
- break;
- }
- }
-}
-
-Slider.prototype.tick = function()
-{
- this.progress += this.step;
- if(this.progress < 0 || this.progress > 1)
- {
- this.stop();
- return false;
- }
- else
- {
- var f = Animator.slowInSlowOut(this.progress);
- var h = this.realHeight * f;
- this.element.style.height = h + "px";
- this.element.style.opacity = f;
- this.element.style.filter = "alpha(opacity:" + f * 100 +")";
- return true;
- }
-}
-
-// ---------------------------------------------------------------------------------
-// Popup menu
-// ---------------------------------------------------------------------------------
-
-var Popup = {
- stack: [] // Array of objects with members root: and popup:
- };
-
-Popup.create = function(root)
-{
- Popup.remove();
- var popup = createTiddlyElement(document.body,"ol","popup","popup");
- Popup.stack.push({root: root, popup: popup});
- return popup;
-}
-
-Popup.onDocumentClick = function(e)
-{
- if (!e) var e = window.event;
- var target = resolveTarget(e);
- if(e.eventPhase == undefined)
- Popup.remove();
- else if(e.eventPhase == Event.BUBBLING_PHASE || e.eventPhase == Event.AT_TARGET)
- Popup.remove();
- return true;
-}
-
-Popup.show = function(unused,slowly)
-{
- var curr = Popup.stack[Popup.stack.length-1];
- var rootLeft = findPosX(curr.root);
- var rootTop = findPosY(curr.root);
- var rootHeight = curr.root.offsetHeight;
- var popupLeft = rootLeft;
- var popupTop = rootTop + rootHeight;
- var popupWidth = curr.popup.offsetWidth;
- var winWidth = findWindowWidth();
- if(popupLeft + popupWidth > winWidth)
- popupLeft = winWidth - popupWidth;
- curr.popup.style.left = popupLeft + "px";
- curr.popup.style.top = popupTop + "px";
- curr.popup.style.display = "block";
- addClass(curr.root,"highlight");
- if(anim && config.options.chkAnimate)
- anim.startAnimating(new Scroller(curr.popup,slowly));
- else
- window.scrollTo(0,ensureVisible(curr.popup));
-}
-
-Popup.remove = function()
-{
- if(Popup.stack.length > 0)
- {
- Popup.removeFrom(0);
- }
-}
-
-Popup.removeFrom = function(from)
-{
- for(var t=Popup.stack.length-1; t>=from; t--)
- {
- var p = Popup.stack[t];
- removeClass(p.root,"highlight");
- p.popup.parentNode.removeChild(p.popup);
- }
- Popup.stack = Popup.stack.slice(0,from);
-}
-
-// ---------------------------------------------------------------------------------
-// ListView gadget
-// ---------------------------------------------------------------------------------
-
-var ListView = {};
-
-// Create a listview
-// place - where in the DOM tree to insert the listview
-// listObject - array of objects to be included in the listview
-// listTemplate - template for the listview
-// callback - callback for a command being selected
-// className - optional classname for the <table> element
-ListView.create = function(place,listObject,listTemplate,callback,className)
-{
- var table = createTiddlyElement(place,"table",null,className ? className : "listView");
- var thead = createTiddlyElement(table,"thead");
- var r = createTiddlyElement(thead,"tr");
- for(var t=0; t<listTemplate.columns.length; t++)
- {
- var columnTemplate = listTemplate.columns[t];
- var c = createTiddlyElement(r,"th");
- var colType = ListView.columnTypes[columnTemplate.type];
- if(colType && colType.createHeader)
- colType.createHeader(c,columnTemplate,t);
- }
- var tbody = createTiddlyElement(table,"tbody");
- for(var rc=0; rc<listObject.length; rc++)
- {
- rowObject = listObject[rc];
- r = createTiddlyElement(tbody,"tr");
- for(var c=0; c<listTemplate.rowClasses.length; c++)
- {
- if(rowObject[listTemplate.rowClasses[c].field])
- addClass(r,listTemplate.rowClasses[c].className);
- }
- rowObject.rowElement = rowObject;
- rowObject.colElements = {};
- for(var cc=0; cc<listTemplate.columns.length; cc++)
- {
- var c = createTiddlyElement(r,"td");
- var columnTemplate = listTemplate.columns[cc];
- var field = columnTemplate.field;
- var colType = ListView.columnTypes[columnTemplate.type];
- if(colType && colType.createItem)
- colType.createItem(c,rowObject,field,columnTemplate,cc,rc);
- rowObject.colElements[field] = c;
- }
- }
- if(callback && listTemplate.actions)
- createTiddlyDropDown(place,ListView.getCommandHandler(callback),listTemplate.actions);
- if(callback && listTemplate.buttons)
- {
- for(t=0; t<listTemplate.buttons.length; t++)
- {
- var a = listTemplate.buttons[t];
- if(a && a.name != "")
- createTiddlyButton(place,a.caption,null,ListView.getCommandHandler(callback,a.name,a.allowEmptySelection));
- }
- }
- return table;
-}
-
-ListView.getCommandHandler = function(callback,name,allowEmptySelection)
-{
- return function(e)
- {
- var view = findRelated(this,"TABLE",null,"previousSibling");
- var tiddlers = [];
- ListView.forEachSelector(view,function(e,rowName) {
- if(e.checked)
- tiddlers.push(rowName);
- });
- if(tiddlers.length == 0 && !allowEmptySelection)
- alert(config.messages.nothingSelected);
- else
- {
- if(this.nodeName.toLowerCase() == "select")
- {
- callback(view,this.value,tiddlers);
- this.selectedIndex = 0;
- }
- else
- callback(view,name,tiddlers);
- }
- };
-}
-
-// Invoke a callback for each selector checkbox in the listview
-// view - <table> element of listView
-// callback(checkboxElement,rowName)
-// where
-// checkboxElement - DOM element of checkbox
-// rowName - name of this row as assigned by the column template
-// result: true if at least one selector was checked
-ListView.forEachSelector = function(view,callback)
-{
- var checkboxes = view.getElementsByTagName("input");
- var hadOne = false;
- for(var t=0; t<checkboxes.length; t++)
- {
- var cb = checkboxes[t];
- if(cb.getAttribute("type") == "checkbox")
- {
- var rn = cb.getAttribute("rowName");
- if(rn)
- {
- callback(cb,rn);
- hadOne = true;
- }
- }
- }
- return hadOne;
-}
-
-ListView.columnTypes = {};
-
-ListView.columnTypes.String = {
- createHeader: function(place,columnTemplate,col)
- {
- createTiddlyText(place,columnTemplate.title);
- },
- createItem: function(place,listObject,field,columnTemplate,col,row)
- {
- var v = listObject[field];
- if(v != undefined)
- createTiddlyText(place,v);
- }
-};
-
-ListView.columnTypes.Date = {
- createHeader: ListView.columnTypes.String.createHeader,
- createItem: function(place,listObject,field,columnTemplate,col,row)
- {
- var v = listObject[field];
- if(v != undefined)
- createTiddlyText(place,v.formatString(columnTemplate.dateFormat));
- }
-};
-
-ListView.columnTypes.StringList = {
- createHeader: ListView.columnTypes.String.createHeader,
- createItem: function(place,listObject,field,columnTemplate,col,row)
- {
- var v = listObject[field];
- if(v != undefined)
- {
- for(var t=0; t<v.length; t++)
- {
- createTiddlyText(place,v[t]);
- createTiddlyElement(place,"br");
- }
- }
- }
-};
-
-ListView.columnTypes.Selector = {
- createHeader: function(place,columnTemplate,col)
- {
- createTiddlyCheckbox(place,null,false,this.onHeaderChange);
- },
- createItem: function(place,listObject,field,columnTemplate,col,row)
- {
- var e = createTiddlyCheckbox(place,null,listObject[field],null);
- e.setAttribute("rowName",listObject[columnTemplate.rowName]);
- },
- onHeaderChange: function(e)
- {
- var state = this.checked;
- var view = findRelated(this,"TABLE");
- if(!view)
- return;
- ListView.forEachSelector(view,function(e,rowName) {
- e.checked = state;
- });
- }
-};
-
-ListView.columnTypes.Tags = {
- createHeader: ListView.columnTypes.String.createHeader,
- createItem: function(place,listObject,field,columnTemplate,col,row)
- {
- var tags = listObject[field];
- createTiddlyText(place,String.encodeTiddlyLinkList(tags));
- }
-};
-
-ListView.columnTypes.Boolean = {
- createHeader: ListView.columnTypes.String.createHeader,
- createItem: function(place,listObject,field,columnTemplate,col,row)
- {
- if(listObject[field] == true)
- createTiddlyText(place,columnTemplate.trueText);
- if(listObject[field] == false)
- createTiddlyText(place,columnTemplate.falseText);
- }
-};
-
-ListView.columnTypes.TagCheckbox = {
- createHeader: ListView.columnTypes.String.createHeader,
- createItem: function(place,listObject,field,columnTemplate,col,row)
- {
- var e = createTiddlyCheckbox(place,null,listObject[field],this.onChange);
- e.setAttribute("tiddler",listObject.title);
- e.setAttribute("tag",columnTemplate.tag);
- },
- onChange : function(e)
- {
- var tag = this.getAttribute("tag");
- var tiddler = this.getAttribute("tiddler");
- store.setTiddlerTag(tiddler,this.checked,tag);
- }
-};
-
-ListView.columnTypes.TiddlerLink = {
- createHeader: ListView.columnTypes.String.createHeader,
- createItem: function(place,listObject,field,columnTemplate,col,row)
- {
- var v = listObject[field];
- if(v != undefined)
- {
- var link = createTiddlyLink(place,listObject[columnTemplate.tiddlerLink],false,null);
- createTiddlyText(link,listObject[field]);
- }
- }
-};
-// ---------------------------------------------------------------------------------
-// Augmented methods for the JavaScript Number(), Array(), String() and Date() objects
-// ---------------------------------------------------------------------------------
-
-// Clamp a number to a range
-Number.prototype.clamp = function(min,max)
-{
- var c = this;
- if(c < min)
- c = min;
- if(c > max)
- c = max;
- return c;
-}
-
-// Add indexOf function if browser does not support it
-if(!Array.indexOf) {
-Array.prototype.indexOf = function(item,from)
-{
- if(!from)
- from = 0;
- for(var i=from; i<this.length; i++)
- if(this[i] === item)
- return i;
- return -1;
-}}
-
-// Find an entry in a given field of the members of an array
-Array.prototype.findByField = function(field,value)
-{
- for(var t=0; t<this.length; t++)
- if(this[t][field] == value)
- return t;
- return null;
-}
-
-// Return whether an entry exists in an array
-Array.prototype.contains = function(item)
-{
- return this.indexOf(item) != -1;
-};
-
-// Adds, removes or toggles a particular value within an array
-// value - value to add
-// mode - +1 to add value, -1 to remove value, 0 to toggle it
-Array.prototype.setItem = function(value,mode)
-{
- var p = this.indexOf(value);
- if(mode == 0)
- mode = (p == -1) ? +1 : -1;
- if(mode == +1)
- {
- if(p == -1)
- this.push(value);
- }
- else if(mode == -1)
- {
- if(p != -1)
- this.splice(p,1);
- }
-}
-
-// Return whether one of a list of values exists in an array
-Array.prototype.containsAny = function(items)
-{
- for(var i=0; i<items.length; i++)
- if (this.indexOf(items[i]) != -1)
- return true;
- return false;
-};
-
-// Return whether all of a list of values exists in an array
-Array.prototype.containsAll = function(items)
-{
- for (var i = 0; i<items.length; i++)
- if (this.indexOf(items[i]) == -1)
- return false;
- return true;
-};
-
-// Push a new value into an array only if it is not already present in the array. If the optional unique parameter is false, it reverts to a normal push
-Array.prototype.pushUnique = function(item,unique)
-{
- if(unique != undefined && unique == false)
- this.push(item);
- else
- {
- if(this.indexOf(item) == -1)
- this.push(item);
- }
-}
-
-Array.prototype.remove = function(item)
-{
- var p = this.indexOf(item);
- if(p != -1)
- this.splice(p,1);
-}
-
-// Get characters from the right end of a string
-String.prototype.right = function(n)
-{
- if(n < this.length)
- return this.slice(this.length-n);
- else
- return this;
-}
-
-// Trim whitespace from both ends of a string
-String.prototype.trim = function()
-{
- return this.replace(/^\s*|\s*$/g,"");
-}
-
-// Convert a string from a CSS style property name to a JavaScript style name ("background-color" -> "backgroundColor")
-String.prototype.unDash = function()
-{
- var s = this.split("-");
- if(s.length > 1)
- for(var t=1; t<s.length; t++)
- s[t] = s[t].substr(0,1).toUpperCase() + s[t].substr(1);
- return s.join("");
-}
-
-// Substitute substrings from an array into a format string that includes '%1'-type specifiers
-String.prototype.format = function(substrings)
-{
- var subRegExp = /(?:%(\d+))/mg;
- var currPos = 0;
- var r = [];
- do {
- var match = subRegExp.exec(this);
- if(match && match[1])
- {
- if(match.index > currPos)
- r.push(this.substring(currPos,match.index));
- r.push(substrings[parseInt(match[1])]);
- currPos = subRegExp.lastIndex;
- }
- } while(match);
- if(currPos < this.length)
- r.push(this.substring(currPos,this.length));
- return r.join("");
-}
-
-// Escape any special RegExp characters with that character preceded by a backslash
-String.prototype.escapeRegExp = function()
-{
- var s = "\\^$*+?()=!|,{}[].";
- var c = this;
- for(var t=0; t<s.length; t++)
- c = c.replace(new RegExp("\\" + s.substr(t,1),"g"),"\\" + s.substr(t,1));
- return c;
-}
-
-// Convert "\" to "\s", newlines to "\n" (and remove carriage returns)
-String.prototype.escapeLineBreaks = function()
-{
- return this.replace(/\\/mg,"\\s").replace(/\n/mg,"\\n").replace(/\r/mg,"");
-}
-
-// Convert "\n" to newlines, "\b" to " ", "\s" to "\" (and remove carriage returns)
-String.prototype.unescapeLineBreaks = function()
-{
- return this.replace(/\\n/mg,"\n").replace(/\\b/mg," ").replace(/\\s/mg,"\\").replace(/\r/mg,"");
-}
-
-// Convert & to "&amp;", < to "&lt;", > to "&gt;" and " to "&quot;"
-String.prototype.htmlEncode = function()
-{
- return(this.replace(/&/mg,"&amp;").replace(/</mg,"&lt;").replace(/>/mg,"&gt;").replace(/\"/mg,"&quot;"));
-}
-
-// Convert "&amp;" to &, "&lt;" to <, "&gt;" to > and "&quot;" to "
-String.prototype.htmlDecode = function()
-{
- return(this.replace(/&amp;/mg,"&").replace(/&lt;/mg,"<").replace(/&gt;/mg,">").replace(/&quot;/mg,"\""));
-}
-
-// Parse a space-separated string of name:value parameters where:
-// - the name or the value can be optional (in which case separate defaults are used instead)
-// - in case of ambiguity, a lone word is taken to be a value
-// - if 'cascadeDefaults' is set to true, then the defaults are modified by updated by each specified name or value
-// - name prefixes are not allowed if the 'noNames' parameter is true
-// - if both the name and value are present they must be separated by a colon
-// - the name and the value may both be quoted with single- or double-quotes, double-square brackets
-// - names or values quoted with {{double-curly braces}} are evaluated as a JavaScript expression
-// - as long as the 'allowEval' parameter is true
-// The result is an array of objects:
-// result[0] = object with a member for each parameter name, value of that member being an array of values
-// result[1..n] = one object for each parameter, with 'name' and 'value' members
-String.prototype.parseParams = function(defaultName,defaultValue,allowEval,noNames,cascadeDefaults)
-{
- var parseToken = function(match,p)
- {
- var n;
- if(match[p]) // Double quoted
- n = match[p];
- else if(match[p+1]) // Single quoted
- n = match[p+1];
- else if(match[p+2]) // Double-square-bracket quoted
- n = match[p+2];
- else if(match[p+3]) // Double-brace quoted
- try
- {
- n = match[p+3];
- if(allowEval)
- n = window.eval(n);
- }
- catch(e)
- {
- throw "Unable to evaluate {{" + match[p+3] + "}}: " + exceptionText(e);
- }
- else if(match[p+4]) // Unquoted
- n = match[p+4];
- else if(match[p+5]) // empty quote
- n = "";
- return n;
- };
- var r = [{}];
- var dblQuote = "(?:\"((?:(?:\\\\\")|[^\"])+)\")";
- var sngQuote = "(?:'((?:(?:\\\\\')|[^'])+)')";
- var dblSquare = "(?:\\[\\[((?:\\s|\\S)*?)\\]\\])";
- var dblBrace = "(?:\\{\\{((?:\\s|\\S)*?)\\}\\})";
- var unQuoted = noNames ? "([^\"'\\s]\\S*)" : "([^\"':\\s][^\\s:]*)";
- var emptyQuote = "((?:\"\")|(?:''))";
- var skipSpace = "(?:\\s*)";
- var token = "(?:" + dblQuote + "|" + sngQuote + "|" + dblSquare + "|" + dblBrace + "|" + unQuoted + "|" + emptyQuote + ")";
- var re = noNames
- ? new RegExp(token,"mg")
- : new RegExp(skipSpace + token + skipSpace + "(?:(\\:)" + skipSpace + token + ")?","mg");
- var params = [];
- do {
- var match = re.exec(this);
- if(match)
- {
- var n = parseToken(match,1);
- if(noNames)
- r.push({name: "", value: n});
- else
- {
- var v = parseToken(match,8);
- if(v == null && defaultName)
- {
- v = n;
- n = defaultName;
- }
- else if(v == null && defaultValue)
- v = defaultValue;
- r.push({name: n, value: v});
- if(cascadeDefaults)
- {
- defaultName = n;
- defaultValue = v;
- }
- }
- }
- } while(match);
- // Summarise parameters into first element
- for(var t=1; t<r.length; t++)
- {
- if(r[0][r[t].name])
- r[0][r[t].name].push(r[t].value);
- else
- r[0][r[t].name] = [r[t].value];
- }
- return r;
-}
-
-// Process a string list of macro parameters into an array. Parameters can be quoted with "", '',
-// [[]], {{ }} or left unquoted (and therefore space-separated). Double-braces {{}} results in
-// an *evaluated* parameter: e.g. {{config.options.txtUserName}} results in the current user's name.
-String.prototype.readMacroParams = function()
-{
- var p = this.parseParams("list",null,true,true);
- var n = [];
- for(var t=1; t<p.length; t++)
- n.push(p[t].value);
- return n;
-}
-
-// Process a string list of unique tiddler names into an array. Tiddler names that have spaces in them must be [[bracketed]]
-String.prototype.readBracketedList = function(unique)
-{
- var p = this.parseParams("list",null,false,true);
- var n = [];
- for(var t=1; t<p.length; t++)
- n.pushUnique(p[t].value,unique);
- return n;
-}
-
-// Returns array with start and end index of chunk between given start and end marker, or undefined.
-String.prototype.getChunkRange = function(start,end)
-{
- var s = this.indexOf(start);
- if(s != -1)
- {
- s += start.length;
- var e = this.indexOf(end,s);
- if(e != -1)
- return [s, e];
- }
-}
-
-// Replace a chunk of a string given start and end markers
-String.prototype.replaceChunk = function(start,end,sub)
-{
- var r = this.getChunkRange(start,end);
- return r
- ? this.substring(0,r[0]) + sub + this.substring(r[1])
- : this;
-}
-
-// Returns a chunk of a string between start and end markers, or undefined
-String.prototype.getChunk = function(start,end)
-{
- var r = this.getChunkRange(start,end);
- if (r)
- return this.substring(r[0],r[1]);
-}
-
-
-// Static method to bracket a string with double square brackets if it contains a space
-String.encodeTiddlyLink = function(title)
-{
- if(title.indexOf(" ") == -1)
- return(title);
- else
- return("[[" + title + "]]");
-}
-
-// Static method to encodeTiddlyLink for every item in an array and join them with spaces
-String.encodeTiddlyLinkList = function(list)
-{
- if(list)
- {
- var results = [];
- for(var t=0; t<list.length; t++)
- results.push(String.encodeTiddlyLink(list[t]));
- return results.join(" ");
- }
- else
- return "";
-}
-
-// Static method to left-pad a string with 0s to a certain width
-String.zeroPad = function(n,d)
-{
- var s = n.toString();
- if(s.length < d)
- s = "000000000000000000000000000".substr(0,d-s.length) + s;
- return(s);
-}
-
-String.prototype.startsWith = function(prefix)
-{
- return !prefix || this.substring(0,prefix.length) == prefix;
-}
-
-// Returns the first value of the given named parameter.
-//#
-//# @param params
-//# as returned by parseParams or null/undefined
-//# @return [may be null/undefined]
-//#
-function getParam(params, name, defaultValue) {
- if (!params)
- return defaultValue;
- var p = params[0][name];
- return p ? p[0] : defaultValue;
-}
-
-// Returns the first value of the given boolean named parameter.
-//#
-//# @param params
-//# as returned by parseParams or null/undefined
-//#
-function getFlag(params, name, defaultValue) {
- return !!getParam(params, name, defaultValue);
-}
-
-// Substitute date components into a string
-Date.prototype.formatString = function(template)
-{
- var t = template.replace(/0hh12/g,String.zeroPad(this.getHours12(),2));
- t = t.replace(/hh12/g,this.getHours12());
- t = t.replace(/0hh/g,String.zeroPad(this.getHours(),2));
- t = t.replace(/hh/g,this.getHours());
- t = t.replace(/0mm/g,String.zeroPad(this.getMinutes(),2));
- t = t.replace(/mm/g,this.getMinutes());
- t = t.replace(/0ss/g,String.zeroPad(this.getSeconds(),2));
- t = t.replace(/ss/g,this.getSeconds());
- t = t.replace(/[ap]m/g,this.getAmPm().toLowerCase());
- t = t.replace(/[AP]M/g,this.getAmPm().toUpperCase());
- t = t.replace(/wYYYY/g,this.getYearForWeekNo());
- t = t.replace(/wYY/g,String.zeroPad(this.getYearForWeekNo()-2000,2));
- t = t.replace(/YYYY/g,this.getFullYear());
- t = t.replace(/YY/g,String.zeroPad(this.getFullYear()-2000,2));
- t = t.replace(/MMM/g,config.messages.dates.months[this.getMonth()]);
- t = t.replace(/mmm/g,config.messages.dates.shortMonths[this.getMonth()]);
- t = t.replace(/0MM/g,String.zeroPad(this.getMonth()+1,2));
- t = t.replace(/MM/g,this.getMonth()+1);
- t = t.replace(/0WW/g,String.zeroPad(this.getWeek(),2));
- t = t.replace(/WW/g,this.getWeek());
- t = t.replace(/DDD/g,config.messages.dates.days[this.getDay()]);
- t = t.replace(/ddd/g,config.messages.dates.shortDays[this.getDay()]);
- t = t.replace(/0DD/g,String.zeroPad(this.getDate(),2));
- t = t.replace(/DDth/g,this.getDate()+this.daySuffix());
- t = t.replace(/DD/g,this.getDate());
- return t;
-}
-
-Date.prototype.getWeek = function()
-{
- var dt = new Date(this.getTime());
- var d = dt.getDay();
- if (d==0) d=7;// JavaScript Sun=0, ISO Sun=7
- dt.setTime(dt.getTime()+(4-d)*86400000);// shift day to Thurs of same week to calculate weekNo
- var n = Math.floor((dt.getTime()-new Date(dt.getFullYear(),0,1)+3600000)/86400000);
- return Math.floor(n/7)+1;
-}
-
-Date.prototype.getYearForWeekNo = function()
-{
- var dt = new Date(this.getTime());
- var d = dt.getDay();
- if (d==0) d=7;// JavaScript Sun=0, ISO Sun=7
- dt.setTime(dt.getTime()+(4-d)*86400000);// shift day to Thurs of same week
- return dt.getFullYear();
-}
-
-Date.prototype.getHours12 = function()
-{
- var h = this.getHours();
- return h > 12 ? h-12 : ( h > 0 ? h : 12 );
-}
-
-Date.prototype.getAmPm = function()
-{
- return this.getHours() >= 12 ? "pm" : "am";
-}
-
-Date.prototype.daySuffix = function()
-{
- var num = this.getDate();
- if (num >= 11 && num <= 13) return "th";
- else if (num.toString().substr(-1)=="1") return "st";
- else if (num.toString().substr(-1)=="2") return "nd";
- else if (num.toString().substr(-1)=="3") return "rd";
- return "th";
-}
-
-// Convert a date to local YYYYMMDDHHMM string format
-Date.prototype.convertToLocalYYYYMMDDHHMM = function()
-{
- return(String.zeroPad(this.getFullYear(),4) + String.zeroPad(this.getMonth()+1,2) + String.zeroPad(this.getDate(),2) + String.zeroPad(this.getHours(),2) + String.zeroPad(this.getMinutes(),2));
-}
-
-// Convert a date to UTC YYYYMMDDHHMM string format
-Date.prototype.convertToYYYYMMDDHHMM = function()
-{
- return(String.zeroPad(this.getUTCFullYear(),4) + String.zeroPad(this.getUTCMonth()+1,2) + String.zeroPad(this.getUTCDate(),2) + String.zeroPad(this.getUTCHours(),2) + String.zeroPad(this.getUTCMinutes(),2));
-}
-
-// Convert a date to UTC YYYYMMDD.HHMMSSMMM string format
-Date.prototype.convertToYYYYMMDDHHMMSSMMM = function()
-{
- return(String.zeroPad(this.getUTCFullYear(),4) + String.zeroPad(this.getUTCMonth()+1,2) + String.zeroPad(this.getUTCDate(),2) + "." + String.zeroPad(this.getUTCHours(),2) + String.zeroPad(this.getUTCMinutes(),2) + String.zeroPad(this.getUTCSeconds(),2) + String.zeroPad(this.getUTCMilliseconds(),4));
-}
-
-// Static method to create a date from a UTC YYYYMMDDHHMM format string
-Date.convertFromYYYYMMDDHHMM = function(d)
-{
- var theDate = new Date(Date.UTC(parseInt(d.substr(0,4),10),
- parseInt(d.substr(4,2),10)-1,
- parseInt(d.substr(6,2),10),
- parseInt(d.substr(8,2),10),
- parseInt(d.substr(10,2),10),0,0));
- return(theDate);
-}
-
-// ---------------------------------------------------------------------------------
-// Crypto functions and associated conversion routines
-// ---------------------------------------------------------------------------------
-
-// Crypto "namespace"
-function Crypto() {}
-
-// Convert a string to an array of big-endian 32-bit words
-Crypto.strToBe32s = function(str)
-{
- var be = Array();
- var len = Math.floor(str.length/4);
- var i, j;
- for(i=0, j=0; i<len; i++, j+=4)
- {
- be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
- }
- while (j<str.length)
- {
- be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
- j++;
- }
- return be;
-}
-
-// Convert an array of big-endian 32-bit words to a string
-Crypto.be32sToStr = function(be)
-{
- var str = "";
- for(var i=0;i<be.length*32;i+=8)
- str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
- return str;
-}
-
-// Convert an array of big-endian 32-bit words to a hex string
-Crypto.be32sToHex = function(be)
-{
- var hex = "0123456789ABCDEF";
- var str = "";
- for(var i=0;i<be.length*4;i++)
- str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
- return str;
-}
-
-// Return, in hex, the SHA-1 hash of a string
-Crypto.hexSha1Str = function(str)
-{
- return Crypto.be32sToHex(Crypto.sha1Str(str));
-}
-
-// Return the SHA-1 hash of a string
-Crypto.sha1Str = function(str)
-{
- return Crypto.sha1(Crypto.strToBe32s(str),str.length);
-}
-
-// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
-Crypto.sha1 = function(x,blen)
-{
- // Add 32-bit integers, wrapping at 32 bits
- //# Uses 16-bit operations internally to work around bugs in some JavaScript interpreters.
- add32 = function(a,b)
- {
- var lsw = (a&0xFFFF)+(b&0xFFFF);
- var msw = (a>>16)+(b>>16)+(lsw>>16);
- return (msw<<16)|(lsw&0xFFFF);
- };
- // Add five 32-bit integers, wrapping at 32 bits
- //# Uses 16-bit operations internally to work around bugs in some JavaScript interpreters.
- add32x5 = function(a,b,c,d,e)
- {
- var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
- var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
- return (msw<<16)|(lsw&0xFFFF);
- };
- // Bitwise rotate left a 32-bit integer by 1 bit
- rol32 = function(n)
- {
- return (n>>>31)|(n<<1);
- };
-
- var len = blen*8;
- // Append padding so length in bits is 448 mod 512
- x[len>>5] |= 0x80 << (24-len%32);
- // Append length
- x[((len+64>>9)<<4)+15] = len;
- var w = Array(80);
-
- var k1 = 0x5A827999;
- var k2 = 0x6ED9EBA1;
- var k3 = 0x8F1BBCDC;
- var k4 = 0xCA62C1D6;
-
- var h0 = 0x67452301;
- var h1 = 0xEFCDAB89;
- var h2 = 0x98BADCFE;
- var h3 = 0x10325476;
- var h4 = 0xC3D2E1F0;
-
- for(var i=0;i<x.length;i+=16)
- {
- var j,t;
- var a = h0;
- var b = h1;
- var c = h2;
- var d = h3;
- var e = h4;
- for(j = 0;j<16;j++)
- {
- w[j] = x[i+j];
- t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
- e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
- }
- for(j=16;j<20;j++)
- {
- w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
- t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
- e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
- }
- for(j=20;j<40;j++)
- {
- w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
- t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
- e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
- }
- for(j=40;j<60;j++)
- {
- w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
- t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
- e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
- }
- for(j=60;j<80;j++)
- {
- w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
- t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
- e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
- }
-
- h0 = add32(h0,a);
- h1 = add32(h1,b);
- h2 = add32(h2,c);
- h3 = add32(h3,d);
- h4 = add32(h4,e);
- }
- return Array(h0,h1,h2,h3,h4);
-}
-
-// ---------------------------------------------------------------------------------
-// RGB colour object
-// ---------------------------------------------------------------------------------
-
-// Construct an RGB colour object from a '#rrggbb', '#rgb' or 'rgb(n,n,n)' string or from separate r,g,b values
-function RGB(r,g,b)
-{
- this.r = 0;
- this.g = 0;
- this.b = 0;
- if(typeof r == "string")
- {
- if(r.substr(0,1) == "#")
- {
- if(r.length == 7)
- {
- this.r = parseInt(r.substr(1,2),16)/255;
- this.g = parseInt(r.substr(3,2),16)/255;
- this.b = parseInt(r.substr(5,2),16)/255;
- }
- else
- {
- this.r = parseInt(r.substr(1,1),16)/15;
- this.g = parseInt(r.substr(2,1),16)/15;
- this.b = parseInt(r.substr(3,1),16)/15;
- }
- }
- else
- {
- var rgbPattern = /rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/ ;
- var c = r.match(rgbPattern);
- if (c)
- {
- this.r = parseInt(c[1],10)/255;
- this.g = parseInt(c[2],10)/255;
- this.b = parseInt(c[3],10)/255;
- }
- }
- }
- else
- {
- this.r = r;
- this.g = g;
- this.b = b;
- }
- return this;
-}
-
-// Mixes this colour with another in a specified proportion
-// c = other colour to mix
-// f = 0..1 where 0 is this colour and 1 is the new colour
-// Returns an RGB object
-RGB.prototype.mix = function(c,f)
-{
- return new RGB(this.r + (c.r-this.r) * f,this.g + (c.g-this.g) * f,this.b + (c.b-this.b) * f);
-}
-
-// Return an rgb colour as a #rrggbb format hex string
-RGB.prototype.toString = function()
-{
- var r = this.r.clamp(0,1);
- var g = this.g.clamp(0,1);
- var b = this.b.clamp(0,1);
- return("#" + ("0" + Math.floor(r * 255).toString(16)).right(2) +
- ("0" + Math.floor(g * 255).toString(16)).right(2) +
- ("0" + Math.floor(b * 255).toString(16)).right(2));
-}
-
-// ---------------------------------------------------------------------------------
-// DOM utilities - many derived from www.quirksmode.org
-// ---------------------------------------------------------------------------------
-
-function drawGradient(place,horiz,colours)
-{
- for(var t=0; t<= 100; t+=2)
- {
- var bar = document.createElement("div");
- place.appendChild(bar);
- bar.style.position = "absolute";
- bar.style.left = horiz ? t + "%" : 0;
- bar.style.top = horiz ? 0 : t + "%";
- bar.style.width = horiz ? (101-t) + "%" : "100%";
- bar.style.height = horiz ? "100%" : (101-t) + "%";
- bar.style.zIndex = -1;
- var f = t/100;
- var p = f*(colours.length-1);
- bar.style.backgroundColor = colours[Math.floor(p)].mix(colours[Math.ceil(p)],p-Math.floor(p)).toString();
- }
-}
-
-function createTiddlyText(theParent,theText)
-{
- return theParent.appendChild(document.createTextNode(theText));
-}
-
-function createTiddlyCheckbox(theParent,caption,checked,onChange)
-{
- var cb = document.createElement("input");
- cb.setAttribute("type","checkbox");
- cb.onclick = onChange;
- theParent.appendChild(cb);
- cb.checked = checked;
- cb.className = "chkOptionInput";
- if(caption)
- wikify(caption,theParent);
- return cb;
-}
-
-function createTiddlyElement(theParent,theElement,theID,theClass,theText)
-{
- var e = document.createElement(theElement);
- if(theClass != null)
- e.className = theClass;
- if(theID != null)
- e.setAttribute("id",theID);
- if(theText != null)
- e.appendChild(document.createTextNode(theText));
- if(theParent != null)
- theParent.appendChild(e);
- return(e);
-}
-
-// Add an event handler
-// Thanks to John Resig, via QuirksMode
-function addEvent(obj,type,fn)
-{
- if(obj.attachEvent)
- {
- obj['e'+type+fn] = fn;
- obj[type+fn] = function(){obj['e'+type+fn](window.event);}
- obj.attachEvent('on'+type,obj[type+fn]);
- }
- else
- obj.addEventListener(type,fn,false);
-}
-
-// Remove an event handler
-// Thanks to John Resig, via QuirksMode
-function removeEvent(obj,type,fn)
-{
- if(obj.detachEvent)
- {
- obj.detachEvent('on'+type,obj[type+fn]);
- obj[type+fn] = null;
- }
- else
- obj.removeEventListener(type,fn,false);
-}
-
-function addClass(e,theClass)
-{
- var currClass = e.className.split(" ");
- if(currClass.indexOf(theClass) == -1)
- e.className += " " + theClass;
-}
-
-function removeClass(e,theClass)
-{
- var currClass = e.className.split(" ");
- var i = currClass.indexOf(theClass);
- while(i != -1)
- {
- currClass.splice(i,1);
- i = currClass.indexOf(theClass);
- }
- e.className = currClass.join(" ");
-}
-
-function hasClass(e,theClass)
-{
- if(e.className)
- {
- if(e.className.split(" ").indexOf(theClass) != -1)
- return true;
- }
- return false;
-}
-
-// Find the closest relative with a given property value (property defaults to tagName, relative defaults to parentNode)
-function findRelated(e,value,name,relative)
-{
- name = name ? name : "tagName";
- relative = relative ? relative : "parentNode";
- if(name == "className")
- {
- while(e && !hasClass(e,value))
- {
- e = e[relative];
- }
- }
- else
- {
- while(e && e[name] != value)
- {
- e = e[relative];
- }
- }
- return e;
-}
-
-// Resolve the target object of an event
-function resolveTarget(e)
-{
- var obj;
- if (e.target)
- obj = e.target;
- else if (e.srcElement)
- obj = e.srcElement;
- if (obj.nodeType == 3) // defeat Safari bug
- obj = obj.parentNode;
- return(obj);
-}
-
-// Return the content of an element as plain text with no formatting
-function getPlainText(e)
-{
- var text = "";
- if(e.innerText)
- text = e.innerText;
- else if(e.textContent)
- text = e.textContent;
- return text;
-}
-
-// Get the scroll position for window.scrollTo necessary to scroll a given element into view
-function ensureVisible(e)
-{
- var posTop = findPosY(e);
- var posBot = posTop + e.offsetHeight;
- var winTop = findScrollY();
- var winHeight = findWindowHeight();
- var winBot = winTop + winHeight;
- if(posTop < winTop)
- return(posTop);
- else if(posBot > winBot)
- {
- if(e.offsetHeight < winHeight)
- return(posTop - (winHeight - e.offsetHeight));
- else
- return(posTop);
- }
- else
- return(winTop);
-}
-
-// Get the current width of the display window
-function findWindowWidth()
-{
- return(window.innerWidth ? window.innerWidth : document.documentElement.clientWidth);
-}
-
-// Get the current height of the display window
-function findWindowHeight()
-{
- return(window.innerHeight ? window.innerHeight : document.documentElement.clientHeight);
-}
-
-// Get the current horizontal page scroll position
-function findScrollX()
-{
- return(window.scrollX ? window.scrollX : document.documentElement.scrollLeft);
-}
-
-// Get the current vertical page scroll position
-function findScrollY()
-{
- return(window.scrollY ? window.scrollY : document.documentElement.scrollTop);
-}
-
-function findPosX(obj)
-{
- var curleft = 0;
- while (obj.offsetParent)
- {
- curleft += obj.offsetLeft;
- obj = obj.offsetParent;
- }
- return curleft;
-}
-
-function findPosY(obj)
-{
- var curtop = 0;
- while (obj.offsetParent)
- {
- curtop += obj.offsetTop;
- obj = obj.offsetParent;
- }
- return curtop;
-}
-
-// Blur a particular element
-function blurElement(e)
-{
- if(e != null && e.focus && e.blur)
- {
- e.focus();
- e.blur();
- }
-}
-
-// Create a non-breaking space
-function insertSpacer(place)
-{
- var e = document.createTextNode(String.fromCharCode(160));
- if(place)
- place.appendChild(e);
- return e;
-}
-
-// Remove all children of a node
-function removeChildren(e)
-{
- while(e.hasChildNodes())
- e.removeChild(e.firstChild);
-}
-
-// Add a stylesheet, replacing any previous custom stylesheet
-function setStylesheet(s,id)
-{
- if(!id)
- id = "customStyleSheet";
- var n = document.getElementById(id);
- if(document.createStyleSheet) // Test for IE's non-standard createStyleSheet method
- {
- if(n)
- n.parentNode.removeChild(n);
- // This failed without the &nbsp;
- document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd","&nbsp;<style id='" + id + "'>" + s + "</style>");
- }
- else
- {
- if(n)
- n.replaceChild(document.createTextNode(s),n.firstChild);
- else
- {
- var n = document.createElement("style");
- n.type = "text/css";
- n.id = id;
- n.appendChild(document.createTextNode(s));
- document.getElementsByTagName("head")[0].appendChild(n);
- }
- }
-}
-
-// Replace the current selection of a textarea or text input and scroll it into view
-
-function replaceSelection(e,text)
-{
- if (e.setSelectionRange)
- {
- var oldpos = e.selectionStart + 1;
- e.value = e.value.substr(0,e.selectionStart) + text + e.value.substr(e.selectionStart);
- e.setSelectionRange( oldpos, oldpos);
- var linecount = e.value.split('\n').length;
- var thisline = e.value.substr(0,e.selectionStart).split('\n').length-1;
- e.scrollTop = Math.floor((thisline-e.rows/2)*e.scrollHeight/linecount);
- }
- else if (document.selection)
- {
- var range = document.selection.createRange();
- if (range.parentElement() == e)
- {
- var isCollapsed = range.text == "";
- range.text = text;
- if (!isCollapsed)
- {
- range.moveStart('character', -text.length);
- range.select();
- }
- }
- }
-}
-
-// Returns the text of the given (text) node, possibly merging subsequent text nodes
-function getNodeText(e)
-{
- var t = "";
- while (e && e.nodeName == "#text")
- {
- t += e.nodeValue;
- e = e.nextSibling;
- }
- return t;
-}
-//# -------------------------
-//# LoaderBase: A (abstract) storage loader that loads the tiddlers from a list of HTML elements.
-//# The format of the elements is defined by subclasses of this loader through the internalizeTiddler implementation.
-//# Subclasses must implement:
-//# function getTitle(store, e)
-//#
-//# store must implement:
-//# function createTiddler(title).
-//#
-
-function LoaderBase()
-{
-}
-
-LoaderBase.prototype.loadTiddler = function(store,e,tiddlers)
-{
- var title = this.getTitle(store, e);
- if (title)
- {
- var tiddler = store.createTiddler(title);
- this.internalizeTiddler(store, tiddler, title, e);
- tiddlers.push(tiddler);
- }
-}
-
-LoaderBase.prototype.loadTiddlers = function(store,nodes)
-{
- var tiddlers = [];
- for (var t = 0; t < nodes.length; t++)
- {
- try
- {
- this.loadTiddler(store, nodes[t], tiddlers);
- }
- catch(e)
- {
- showException(e, config.messages.tiddlerLoadError.format([this.getTitle(store, nodes[t])]));
- }
- }
- return tiddlers;
-}
-
-//# -------------------------
-//# SaverBase: a (abstract) storage saver that externalizes all tiddlers into a string,
-//# with every tiddler individually externalized (using this.externalizeTiddler) and joined with newlines
-//# Subclasses must implement:
-//# function externalizeTiddler(store, tiddler)
-//#
-//# store must implement:
-//# function getTiddlers(sortByFieldName)
-//#
-
-function SaverBase()
-{
-}
-
-SaverBase.prototype.externalize = function(store)
-{
- var results = [];
- var tiddlers = store.getTiddlers("title");
- for (var t = 0; t < tiddlers.length; t++)
- results.push(this.externalizeTiddler(store, tiddlers[t]));
- return results.join("\n");
-}
-//--------------------------------
-// TW21Loader (inherits from LoaderBase)
-
-function TW21Loader() {};
-
-TW21Loader.prototype = new LoaderBase();
-
-TW21Loader.prototype.getTitle = function(store, e) {
- var title = null;
- if(e.getAttribute)
- title = e.getAttribute("tiddler");
- if(!title && e.id) {
- var lenPrefix = store.idPrefix.length;
- if (e.id.substr(0,lenPrefix) == store.idPrefix)
- title = e.id.substr(lenPrefix);
- }
- return title;
-}
-
-TW21Loader.prototype.internalizeTiddler = function(store, tiddler, title, data) {
- var text = getNodeText(data.firstChild).unescapeLineBreaks();
- var modifier = data.getAttribute("modifier");
- var modified = Date.convertFromYYYYMMDDHHMM(data.getAttribute("modified"));
- var c = data.getAttribute("created");
- var created = c ? Date.convertFromYYYYMMDDHHMM(c) : modified;
- var tags = data.getAttribute("tags");
- var fields = {};
- var attrs = data.attributes;
- for(var i = attrs.length-1; i >= 0; i--) {
- var name = attrs[i].name;
- if (attrs[i].specified && !TiddlyWiki.isStandardField(name)) {
- fields[name] = attrs[i].value.unescapeLineBreaks();
- }
- }
- tiddler.assign(title,text,modifier,modified,tags,created, fields);
- return tiddler;
-};
-
-//--------------------------------
-// TW21Saver (inherits from SaverBase)
-
-function TW21Saver() {};
-
-TW21Saver.prototype = new SaverBase();
-
-TW21Saver.prototype.externalizeTiddler = function(store, tiddler)
-{
- try {
- var extendedFieldAttributes = "";
- store.forEachField(tiddler,
- function(tiddler, fieldName, value) {
- // don't store stuff from the temp namespace
- if (!fieldName.match(/^temp\./))
- extendedFieldAttributes += ' %0="%1"'.format([fieldName, value.escapeLineBreaks().htmlEncode()]);
- }, true);
- return '<div tiddler="%0" modifier="%1" modified="%2" created="%3" tags="%4"%6>%5</div>'.format([
- tiddler.title.htmlEncode(),
- tiddler.modifier.htmlEncode(),
- tiddler.modified.convertToYYYYMMDDHHMM(),
- tiddler.created.convertToYYYYMMDDHHMM(),
- tiddler.getTags().htmlEncode(),
- tiddler.escapeLineBreaks().htmlEncode(),
- extendedFieldAttributes
- ]);
- } catch (e) {
- throw exceptionText(e, config.messages.tiddlerSaveError.format([tiddler.title]));
- }
-}
-
-// ---------------------------------------------------------------------------------
-// Deprecated code
-// ---------------------------------------------------------------------------------
-
-// @Deprecated: Use createElementAndWikify and this.termRegExp instead
-config.formatterHelpers.charFormatHelper = function(w)
-{
- w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
-}
-
-// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
-config.formatterHelpers.monospacedByLineHelper = function(w)
-{
- var lookaheadRegExp = new RegExp(this.lookahead,"mg");
- lookaheadRegExp.lastIndex = w.matchStart;
- var lookaheadMatch = lookaheadRegExp.exec(w.source);
- if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
- {
- var text = lookaheadMatch[1];
- if(config.browser.isIE)
- text = text.replace(/\n/g,"\r");
- createTiddlyElement(w.output,"pre",null,null,text);
- w.nextMatch = lookaheadRegExp.lastIndex;
- }
-}
-
-// @Deprecated: Use <br> or <br /> instead of <<br>>
-config.macros.br.handler = function(place)
-{
- createTiddlyElement(place,"br");
-}
-
-// Find an entry in an array. Returns the array index or null
-// @Deprecated: Use indexOf instead
-Array.prototype.find = function(item)
-{
- var i = this.indexOf(item);
- return i == -1 ? null : i;
-}
-
-// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
-// @Deprecated: Use store.getLoader().internalizeTiddler instead
-Tiddler.prototype.loadFromDiv = function(divRef,title)
-{
- return store.getLoader().internalizeTiddler(store,this,title,divRef);
-}
-
-// Format the text for storage in an HTML DIV
-// @Deprecated Use store.getSaver().externalizeTiddler instead.
-Tiddler.prototype.saveToDiv = function()
-{
- return store.getSaver().externalizeTiddler(store,this);
-}
-
-// @Deprecated: Use store.allTiddlersAsHtml() instead
-function allTiddlersAsHtml()
-{
- return store.allTiddlersAsHtml();
-}
-
-// @Deprecated: Use refreshPageTemplate instead
-function applyPageTemplate(title)
-{
- refreshPageTemplate(title);
-}
-
-// @Deprecated: Use story.displayTiddlers instead
-function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,slowly)
-{
- story.displayTiddlers(srcElement,titles,template,animate,slowly);
-}
-
-// @Deprecated: Use story.displayTiddler instead
-function displayTiddler(srcElement,title,template,unused1,unused2,animate,slowly)
-{
- story.displayTiddler(srcElement,title,template,animate,slowly);
-}
-
-// @Deprecated: Use functions on right hand side directly instead
-var createTiddlerPopup = Popup.create;
-var scrollToTiddlerPopup = Popup.show;
-var hideTiddlerPopup = Popup.remove;
-
-// @Deprecated: Use right hand side directly instead
-var regexpBackSlashEn = new RegExp("\\\\n","mg");
-var regexpBackSlash = new RegExp("\\\\","mg");
-var regexpBackSlashEss = new RegExp("\\\\s","mg");
-var regexpNewLine = new RegExp("\n","mg");
-var regexpCarriageReturn = new RegExp("\r","mg");
-// ---------------------------------------------------------------------------------
-// End of scripts
-merge(config.shadowTiddlers,{SiteTitle:'DevFire'});
-merge(config.shadowTiddlers,{MainMenu:"PageTemplate\nStyleSheet\nMainMenu\nDefaultTiddlers"});
-merge(config.shadowTiddlers,{SiteSubtitle:"a theme for ~TiddlyWiki"});
-merge(config.shadowTiddlers,{DefaultTiddlers:"LorumIpsum"});
-merge(config.shadowTiddlers,{LorumIpsum:"Aenean eros arcu, condimentum nec, dapibus ut, tincidunt sit amet, urna. Quisque viverra, eros sed imperdiet iaculis, est risus facilisis quam, id malesuada arcu nulla luctus urna. Nullam et est. Vestibulum velit sem, faucibus cursus, dapibus vestibulum, pellentesque et, urna. Donec luctus. Donec lectus. Aliquam eget eros facilisis tortor feugiat sollicitudin. Integer lobortis vulputate sapien. Sed iaculis erat ac nunc. Etiam eu enim. Mauris ipsum urna, rhoncus at, bibendum sit amet, euismod eget, dolor. Mauris fermentum quam vitae ligula. Vestibulum in libero feugiat justo dictum consectetuer. Vestibulum euismod purus eget elit. Nunc sed massa porta elit bibendum posuere. Nunc pulvinar justo sit amet odio. In sed est. Phasellus ornare elementum nulla. Nulla ipsum neque, cursus a, viverra a, imperdiet at, enim. Quisque facilisis, diam sed accumsan suscipit, odio arcu hendrerit dolor, quis aliquet massa nulla nec sem.\n!heading 1\n!!heading 2\n!!!heading3\n----\n<<tag button>>\nThis is a link to a [[StyleSheet]] tiddler.\n\n> This is a blockquote\n> This is a blockquote\n> This is a blockquote\n|>|>| !This is a header |h\n|column1|column2|column3|\n|row2| row2 |row2|\n|column1|column2|column3|\n|row2| row2 |row2|\n|column1|column2|column3|\n|row2| row2 |row2|"});
-// ---------------------------------------------------------------------------------
-//]]>
-</script>
-<style type="text/css">
-
-#saveTest {
- display: none;
-}
-
-.zoomer {
- display: none;
-}
-
-#messageArea {
- display: none;
-}
-
-#copyright {
- display: none;
-}
-
-.popup {
- position: absolute;
-}
-
-#storeArea {
- display: none;
- margin: 4em 10em 3em;
-}
-
-#storeArea div {
- padding: 0.5em;
- margin: 1em 0em 0em 0em;
- border-color: #f0f0f0 #606060 #404040 #d0d0d0;
- border-style: solid;
- border-width: 2px;
- overflow: auto;
-}
-
-#javascriptWarning {
- width: 100%;
- text-align: center;
- font-weight: bold;
- background-color: #dd1100;
- color: #fff;
- padding:1em 0em;
-}
-
-</style>
-<!--POST-HEAD-START-->
-
-<!--POST-HEAD-END-->
-</head>
-<body onload="main();" onunload="if(window.checkUnsavedChanges) checkUnsavedChanges();">
-<!--PRE-BODY-START-->
-
-<!--PRE-BODY-END-->
- <script type="text/javascript">
-//<![CDATA[
-if (useJavaSaver)
- document.write("<applet style='position:absolute;left:-1px' name='TiddlySaver' code='TiddlySaver.class' archive='TiddlySaver.jar' width='1' height='1'></applet>");
-//]]>
- </script>
- <div id="copyright">
- Welcome to TiddlyWiki by Jeremy Ruston, Copyright &copy; 2006 Osmosoft Limited
- </div>
- <noscript>
- <div id="javascriptWarning">This page requires JavaScript to function properly</div>
- </noscript>
- <div id="saveTest"></div>
- <div id="contentWrapper"></div>
- <div id="contentStash"></div>
- <div id="storeArea">
-<div tiddler="(built-in shadow tiddler)" modifier="CameronRich" modified="200702240024" created="200702240024" tags="">changes, notes and errata</div>
-<div tiddler="Cam" modifier="YourName" modified="200804011313" created="200804011313" tags="">Type the text for 'YourName'</div>
-<div tiddler="Changelog" modifier="YourName" modified="201111040904" created="200702240022" tags="">@@bgcolor(#ff0000):color(#ffffff):Changes for 1.4.4@@\n\n!!__axhttpd__\n* Allow other CGI applications (such as PHP) to call HTML files from their command line.\n\n!!__SSL Library__\n* Fixed memory leak with invalid certificates (thanks Jon Trauntvein)\n* Fixed issue with non-blocking client connections not working properly (thanks Richard Titmuss).\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.4.3@@\n\n!!__SSL Library__\n* axtlswrap compilation error fixed.\n\n!!__axhttpd__\n* added '-w' command-line option to set the webroot directory.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.4.2@@\n\n!!__SSL Library__\n* bi_export could have a buffer overrun with incorrect input (thanks Gilles ~Boccon-Gibod - 3334305)\n\n!!__axhttpd__\n* ~RFC1123 time format used in the headers.\n* Expires heading added (current time + ~CONFIG_HTTP_TIMEOUT)\n* UTC/localtime issue with ~If-Modified-Since header.\n\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.4.1@@\n\n!!__SSL Library__\n* Allow reading of ~PKCS8/12 unencrypted keys in PEM format and mconf will allow the option in server mode (thanks Steve Bennett).\n* Issue where comparing a null and an empty string could return a false positive for cert check (thanks Gilles ~Boccon-Gibod - 3310885).\n* -fPIC added as a Linux compile option.\n\n!!__axhttpd__\n* Killing connections on session timeout is guaranteed.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.4.0@@\n\n!!__SSL Library__\n* TLS v1.1 implemented and is enabled by default.\n* Closure alerts implemented correctly.\n* Fixed issue with ~SSLv23 hello versioning. \n \n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.3.4@@\n\n!!__SSL Library__\n* SSL 2.0 client hello is turned off by default as per RFC 4346 Appendix E.\n* Client determines the cipher suite selected rather than the server as per RFC 4346 7.4.1.2.\n* Guard against timing HMAC timing attacks as per RFC 4346 6.2.3.2.\n* Fixed ~SOCKET_WRITE buffer issue (thanks Hardy Griech - 3177419)\n* Fixed variable length MAC issue as used by gnutls.\n* Fixed version issue when TLS &gt;=1.1 is used.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.3.2@@\n\n!!__SSL Library__\n* Loading of PEM certificate bundles now loads CA certs properly.\n* ssl_client_new() can now be broken up into an ssl_client_new() and successive ssl_read()'s now by setting the ~SSL_CONNECT_IN_PARTS as an option in ssl_ctx_new().\n* Non-blocked mode is now not a requirement but calls may still be blocked.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.3.1@@\n\n!!__SSL Library__\n* Certificate bundles which contain &quot;invalid&quot; certificates (i.e. invalid digests types etc) are ignored rather than cause failure.\n\n!!__axhttpd__\n* ~HTTPv1.0 packets close a connection upon completion.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.3.0@@\n\n!!__SSL Library__\n* Close notify is now sent as an error code from ssl_read(). Server code should be modified to check for ~SSL_CLOSE_NOTIFY (thanks to Eric Hu - 3132700).\n* regular_square() issue fixed (3078672)\n* partial_multiply() removed and merged with regular_multiply() (3078372).\n* Invalid session id size now returns ~SSL_ERROR_INVALID_SESSION (thanks to Hardy Griech - 3072881)\n* q-dash issue with Barrett reduction fixed (thanks to Hardy Griech - 3079291).\n* PEM file detection now looks for &quot;-BEGIN&quot; in any part of the file rather than at the start (3123838).\n* 8/16/32 bit native int sizes can be selected in configuration.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.2.7@@\n\n!!__SSL Library__\n* A fix to find_max_exp_index() (thanks to Hardy Griech).\n* Check is made to get_cipher_info() if the appropriate cipher is not found (thanks to Hardy Griech).\n* Extra x509_free() removed from do_client_connect().\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.2.5@@\n\n!!__SSL Library__\n* The custom RNG updated to use an entropy pool (with better hooks to use counters).\n\n!!__axhttpd__\n* Headers are case insensitive (thanks to Joe Pruett for this and the following).\n* Child zombie issue fixed.\n* EOF on ~POSTs fixed.\n* Expect is ignored.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.2.4@@\n\n!!__SSL Library__\n* Client renegotiation now results in an error. This is the result of a security flaw described in this paper http://extendedsubset.com/Renegotiating_TLS.pdf, and also is explained in detail here http://www.cupfighter.net/index.php/2009/11/tls-renegotiation-attack/.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.2.3@@\n\n!!__SSL Library__\n* v3 certificates with ~SANs now supports (thanks to Carsten Sørensen).\n* axtlswrap added - a port of sslwrap (thanks to Steve Bennett)\n\n!!__axhttpd__\n* shutdown() called before socket close in CGI (thanks to Tom Brown)\n* command-line parameters to specify the http/https port.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.2.2@@\n\n!!__axhttpd__\n* File uploads over 1kB (but under MAXPOSTDATASIZE) are now supported.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.2.1@@\n\n!!__SSL Library__\n* Certificate verification now works for Firefox.\n* Extended the openssl API.\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.2.0@@\n\n!!__SSL Library__\n* A self-signed certificate will be verified as ok provided that that it is on the certificate authority list.\n* Certificates are not verified when added as certificate authorities (since self-signed and expired certificates can be added to browsers etc)\n\n@@bgcolor(#ff0000):color(#ffffff):Changes for 1.1.9@@\n\n!!__SSL Library__\n* Now support MS IIS resource kit certificates (thanks to Carsten Sørensen).\n* Fixed a memory leak when freeing more than one CA certificate.\n* The bigint library had a problem with squaring which affected classical reduction (thanks to Manuel Klimek).\n\n!!__axhttpd__\n* Brought back setuid()/setgid() as an option.\n\n!@@bgcolor(#ff0000):color(#ffffff):Changes for 1.1.8@@\n\n!!__SSL Library__\n* Now using a BSD style license.\n* Self-signed certificates can now be automatically generated (the keys still need to be provided).\n* A new API call //ssl_x509_create()// can be used to programatically create the certificate.\n* Certificate/keys can be loaded automatically given a file location.\n\n!@@bgcolor(#ff0000):color(#ffffff):Changes for 1.1.7@@\n\n!!__SSL Library__\n\n* Variable sized session id's is now better handled for session caching. It has meant a new API call //ssl_get_session_id_size()// and a change to //ssl_client_new()// to define the session id size.\n* Muliple records with a single header are now better supported (thanks to Hervé Sibert).\n* ~MD2 added for Verisign root cert verification (thanks to Byron Rakitzis).\n* The ~MD5/~SHA1 digests are calculated incrementally to reduce memory (thanks to Byron Rakitzis).\n* The bigint cache is now cleared regularly to reduce memory.\n\n!!__axhttpd__\n\n* Improved the POST handling (thanks to Christian Melki).\n* CSS files now work properly.\n* Lua's CGI launcher location is configurable.\n* //vfork()// is now used for CGI for performance reasons.\n\n!@@bgcolor(#ff0000):color(#ffffff):Changes for 1.1.6@@\n\n!!__SSL Library__\n\n* ~RC4 speed improvements\n* Lua samples/bindings now work properly\n\n!@@bgcolor(#ff0000):color(#ffffff):Changes for 1.1.5@@\n\n!!__SSL Library__\n\n* Session id's can now be variable lengths in server hello messages.\n* 0 length client certificates are now supported.\n* ssl_version() now returns just the version and not the date.\n* ssl_write() was not sending complete packets under load.\n\n!!__axhttpd__\n\n* Completely updated the CGI code.\n* Lua now integrated - Lua scripts and Lua Pages now run.\n\n!@@bgcolor(#ff0000):color(#ffffff):Changes for 1.1.4@@\n\n!!__SSL Library__\n\n* Fixed a Win32 crypto library issue with non-Administrator users\n* Removed compiler warnings that showed up in ~FC6.\n* GNU TLS certificates are now accepted.\n* Separated the send/receive headers for HMAC calculations.\n* Fixed a compilation problem with swig/perl/~FC6.\n* Fixed an issue with loading PEM CA certificates.\n\n!!__axhttpd__\n\n* Made //setuid()/setgid()// call an mconf option.\n* Made //chroot()// an mconf option. Default to //chdir()// instead.\n* Removed optional permissions checking.\n\n!@@bgcolor(#ff0000):color(#ffffff):Changes for 1.1.1@@\n\n!!__SSL Library__\n\n* AES should now work on 16bit processors (there was an alignment problem).\n* Various freed objects are cleared before freeing.\n* Header files now installed in ///usr/local/include/axTLS//.\n* -DCYGWIN replaced with -~DCONFIG_PLATFORM_CYGWIN (and the same for Solaris).\n* removed &quot;-noextern&quot; option in Swig. Fixed some other warnings in Win32.\n* SSLCTX changed to ~SSL_CTX (to be consistent with openssl). SSLCTX still exists for backwards compatibility.\n* malloc() and friends call abort() on failure.\n* Fixed a memory leak in directory listings.\n* Added openssl() compatibility functions.\n* Fixed Cygwin 'make install' issue.\n\n!!__axhttpd__\n\n* main.c now becomes axhttpd.c.\n* Header file issue fixed (in mime_types.c).\n* //chroot()// now used for better security.\n* Basic authentication implemented (via .htpasswd).\n* SSL access/denial protection implemented (via .htaccess).\n* Directory access protection implemented (via .htaccess).\n* Can now have more than one CGI file extension in mconf.\n* &quot;~If-Modified-Since&quot; request now handled properly.\n* Performance tweaks to remove //ssl_find()//.</div>
-<div tiddler="DefaultTiddlers" modifier="CameronRich" modified="200702240019" created="200702240019" tags="">[[Read Me]]</div>
-<div tiddler="License" modifier="YourName" modified="200804011309" created="200702240022" tags="">axTLS uses a BSD style license:\n\nCopyright (c) 2008, Cameron Rich All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer. Redistributions in binary\nform must reproduce the above copyright notice, this list of conditions and\nthe following disclaimer in the documentation and/or other materials\nprovided with the distribution. Neither the name of the axTLS Project nor\nthe names of its contributors may be used to endorse or promote products\nderived from this software without specific prior written permission. \n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\nOUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.</div>
-<div tiddler="MainMenu" modifier="CameronRich" modified="200702250353" created="200702240021" tags="">[[Read Me]] \n[[Changelog]]\n[[axhttpd]]\n[[License]]</div>
-<div tiddler="PageTemplate" modifier="YourName" modified="200701122313" created="200701122350" tags="DevFireTheme">&lt;div class='header' macro='gradient vert #390108 #900'&gt;\n&lt;div class='headerShadow'&gt;\n&lt;span class='siteTitle' refresh='content' tiddler='SiteTitle'&gt;&lt;/span&gt;&amp;nbsp;\n&lt;span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'&gt;&lt;/span&gt;\n&lt;/div&gt;\n&lt;div class='headerForeground'&gt;\n&lt;span class='siteTitle' refresh='content' tiddler='SiteTitle'&gt;&lt;/span&gt;&amp;nbsp;\n&lt;span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'&gt;&lt;/span&gt;\n&lt;/div&gt;\n&lt;/div&gt;\n&lt;div id='mainMenu'&gt;\n&lt;div refresh='content' tiddler='MainMenu'&gt;&lt;/div&gt;\n&lt;/div&gt;\n&lt;div id='sidebar'&gt;\n&lt;div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'&gt;&lt;/div&gt;\n&lt;div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'&gt;&lt;/div&gt;\n&lt;/div&gt;\n&lt;div id='displayArea'&gt;\n&lt;div id='messageArea'&gt;&lt;/div&gt;\n&lt;div id='tiddlerDisplay'&gt;&lt;/div&gt;\n&lt;/div&gt;</div>
-<div tiddler="Read Me" modifier="YourName" modified="201106261041" created="200702240020" tags="">!@@bgcolor(#ff0000):color(#ffffff):axTLS Quick Start Guide@@\n\nThis is a guide to get a small SSL web-server up and running quickly.\n\n!!__Introduction__\n\nThe axTLS project is an SSL client/server library using the ~TLSv1 protocol. It is designed to be small and fast, and is suited to embedded projects. A web server is included.\n\nThe basic web server + SSL library is around 60-70kB and is configurable for features or size.\n\n!!__Compilation__\n\nAll platforms require GNU make. This means on Win32 that Cygwin needs to be installed with &quot;make&quot; and various developer options selected.\n\nConfiguration now uses a tool called &quot;mconf&quot; which gives a nice way to configure options (similar to what is used in ~BusyBox and the Linux kernel).\n\nYou should be able to compile axTLS simply by extracting it, change into the extracted directory and typing:\n\n{{indent{{{{&gt; make}}}\n\nSelect your platform type, save the configuration, exit, and then type &quot;make&quot; again.\n\nIf all goes well, you should end up with an executable called &quot;axhttpd&quot; (or axhttpd.exe) in the //_stage// directory.\n\nTo play with all the various axTLS options, type:\n\n{{indent{{{{&gt; make menuconfig}}}\n\nSave the new configuration and rebuild.\n\n!!__Running it__\n\nTo run it, go to the //_stage// directory, and type (as superuser):\n\n{{indent{{{{&gt; axhttpd}}}\n\nNote: you may have to set your ~LD_LIBRARY_PATH - e.g. go to //_stage// and type //export ~LD_LIBRARY_PATH=`pwd`//\n\nAnd then point your browser at https://127.0.0.1 And you should see a this html page with a padlock appearing on your browser. or type http://127.0.0.1 to see the same page unencrypted.\n\n!!__The axssl utilities__\n\nThe axssl suite of tools are the SSL test tools in the various language bindings. They are:\n\n* axssl - C sample\n* axssl.csharp - C# sample\n* axssl.vbnet - VB.NET sample\n* axtls.jar - Java sample\n* axssl.pl - Perl sample\n* axssl.lua - Lua sample\n\nAll the tools have identical command-line parameters. e.g. to run something interesting:\n\n{{indent{{{{&gt; axssl s_server -verify -CAfile ../ssl/test/axTLS.ca_x509}}}\n\nand\n\n{{indent{{{{&gt; axssl s_client -cert ../ssl/test/axTLS.x509_1024 -key ../ssl/test/axTLS.key_1024 -reconnect}}}\n\n!!!!C#\n\nIf building under Linux or other non-Win32 platforms, Mono must be installed and the executable is run as:\n\n{{indent{{{{&gt; mono axssl.csharp.exe ...}}}\n\n!!!!Java\n\nThe java version is run as:\n\n{{indent{{{{&gt; java -jar axtls.jar &lt;options&gt;}}}\n\n!!!!Perl\n\n{{indent{{{{&gt; [perl] ./axssl.pl &lt;options&gt;}}}\n\nIf running under Win32, be sure to use the correct version of Perl (i.e. ~ActiveState's version works ok).\n\n!!!!Lua\n\n{{indent{{{{&gt; [lua] ./axssl.lua &lt;options&gt;}}}\n\n!__Known Issues__\n\n* Firefox doesn't handle legacy ~SSLv2 at all well. Disabling ~SSLv2 still initiates a ~SSLv23 handshake (v1.5). And continuous pressing of the &quot;Reload&quot; page instigates a change to ~SSLv3 for some reason (even though the TLS 1.0 option is selected). This will cause a &quot;Firefox and &lt;server&gt; cannot communicate securely because they have no common encryption algorithms&quot; (v1.5), or &quot;Firefox can't connect to &lt;server&gt; because the site uses a security protocol which isn't enabled&quot; (v2.0). See bugzilla issues 343543 and 359484 (Comment #7). It's all broken (hopefully fixed soon).\n* Perl/Java bindings don't work on 64 bit Linux machines. I can't even compile the latest version of Perl on an ~AMD64 box (using ~FC3).\n* Java 1.4 or better is required for the Java interfaces.\n* Processes that fork can't use session resumption unless some form of IPC is used.\n* Ensure libperl.so and libaxtls.so are in the shared library path when running with the perl bindings. A way to do this is with:\n\n{{indent{{{{&gt; export LD_LIBRARY_PATH=`perl -e 'use Config; print $Config{archlib};'`/CORE:.}}}\n* The lua sample requires the luabit library from http://luaforge.net/projects/bit.\n\n!!!!Win32 issues\n\n* Be careful about doing .NET executions on network drives - .NET complains with security exceptions on the binary. //TODO: Add a manifest file to prevent this.//\n* CGI has been removed from Win32 - it needs a lot more work to get it right.\n* The default Microsoft .NET SDK is v2.0.50727. Download from: http://msdn.microsoft.com/netframework/downloads/updates/default.aspx.\n\n!!!!Solaris issues\n\n* mconf doesn't work well - some manual tweaking is required for string values.\n* GNU make is required and needs to be in $PATH.\n* To get swig's library dependencies to work (and for the C library to be found), I needed to type:\n\n{{indent{{{{&gt; export LD_LIBRARY_PATH=/usr/local/gcc-3.3.1/lib:.}}}\n\n!!!!Cygwin issues\n\n* The bindings all compile but don't run under Cygwin with the exception of Perl. This is due to win32 executables being incompatible with Cygwin libraries.\n\n</div>
-<div tiddler="SiteSubtitle" modifier="CameronRich" modified="200702240025" created="200702240025" tags="">changes, notes and errata</div>
-<div tiddler="SiteTitle" modifier="CameronRich" modified="200702240023" created="200702240023" tags="">axTLS Embedded SSL</div>
-<div tiddler="SiteUrl" modifier="CameronRich" modified="200702240025" created="200702240025" tags="">http://axtls.cerocclub.com.au</div>
-<div tiddler="StyleSheet" modifier="CameronRich" modified="200702250600" created="200701122350" tags="DevFireTheme">/***\nhttp://tiddlystyles.com/#theme:DevFire\nAuthor: Clint Checketts\n***/\n\n/*{{{*/\nbody {\nbackground: #000;\n}\n/*}}}*/\n/***\n!Link styles /% ============================================================= %/\n***/\n/*{{{*/\na,\na.button,\n#mainMenu a.button,\n#sidebarOptions .sliderPanel a{\n color: #ffbf00;\n border: 0;\n background: transparent;\n}\n\na:hover,\na.button:hover,\n#mainMenu a.button:hover,\n#sidebarOptions .sliderPanel a:hover\n#sidebarOptions .sliderPanel a:active{\n color: #ff7f00;\n border: 0;\n border-bottom: #ff7f00 1px dashed;\n background: transparent;\n text-decoration: none;\n}\n\n#displayArea .button.highlight{\n color: #ffbf00;\n background: #4c4c4c;\n}\n/*}}}*/\n/***\n!Header styles /% ============================================================= %/\n***/\n/*{{{*/\n.header{\n border-bottom: 2px solid #ffbf00;\n color: #fff;\n}\n\n.headerForeground a {\n color: #fff;\n}\n\n.header a:hover {\n border-bottom: 1px dashed #fff;\n}\n/*}}}*/\n/***\n!Main menu styles /% ============================================================= %/\n***/\n/*{{{*/\n#mainMenu {color: #fff;}\n#mainMenu h1{\n font-size: 1.1em;\n}\n#mainMenu li,#mainMenu ul{\n list-style: none;\n margin: 0;\n padding: 0;\n}\n/*}}}*/\n/***\n!Sidebar styles /% ============================================================= %/\n***/\n/*{{{*/\n#sidebar {\n right: 0;\n color: #fff;\n border: 2px solid #ffbf00;\n border-width: 0 0 2px 2px;\n}\n#sidebarOptions {\n background-color: #4c4c4c;\n padding: 0;\n}\n\n#sidebarOptions a{\n margin: 0;\n color: #ffbf00;\n border: 0;\n}\n#sidebarOptions a:hover {\n color: #4c4c4c;\n background-color: #ffbf00;\n\n}\n\n#sidebarOptions a:active {\n color: #ffbf00;\n background-color: transparent;\n}\n\n#sidebarOptions .sliderPanel {\n background-color: #333;\n margin: 0;\n}\n\n#sidebarTabs {background-color: #4c4c4c;}\n#sidebarTabs .tabSelected {\n padding: 3px 3px;\n cursor: default;\n color: #ffbf00;\n background-color: #666;\n}\n#sidebarTabs .tabUnselected {\n color: #ffbf00;\n background-color: #5f5f5f;\n padding: 0 4px;\n}\n\n#sidebarTabs .tabUnselected:hover,\n#sidebarTabs .tabContents {\n background-color: #666;\n}\n\n.listTitle{color: #FFF;}\n#sidebarTabs .tabContents a{\n color: #ffbf00;\n}\n\n#sidebarTabs .tabContents a:hover{\n color: #ff7f00;\n background: transparent;\n}\n\n#sidebarTabs .txtMoreTab .tabSelected,\n#sidebarTabs .txtMoreTab .tab:hover,\n#sidebarTabs .txtMoreTab .tabContents{\n color: #ffbf00;\n background: #4c4c4c;\n}\n\n#sidebarTabs .txtMoreTab .tabUnselected {\n color: #ffbf00;\n background: #5f5f5f;\n}\n\n.tab.tabSelected, .tab.tabSelected:hover{color: #ffbf00; border: 0; background-color: #4c4c4c;cursor:default;}\n.tab.tabUnselected {background-color: #666;}\n.tab.tabUnselected:hover{color:#ffbf00; border: 0;background-color: #4c4c4c;}\n.tabContents {\n background-color: #4c4c4c;\n border: 0;\n}\n.tabContents .tabContents{background: #666;}\n.tabContents .tabSelected{background: #666;}\n.tabContents .tabUnselected{background: #5f5f5f;}\n.tabContents .tab:hover{background: #666;}\n/*}}}*/\n/***\n!Message area styles /% ============================================================= %/\n***/\n/*{{{*/\n#messageArea {background-color: #666; color: #fff; border: 2px solid #ffbf00;}\n#messageArea a:link, #messageArea a:visited {color: #ffbf00; text-decoration:none;}\n#messageArea a:hover {color: #ff7f00;}\n#messageArea a:active {color: #ff7f00;}\n#messageArea .messageToolbar a{\n border: 1px solid #ffbf00;\n background: #4c4c4c;\n}\n/*}}}*/\n/***\n!Popup styles /% ============================================================= %/\n***/\n/*{{{*/\n.popup {color: #fff; background-color: #4c4c4c; border: 1px solid #ffbf00;}\n.popup li.disabled{color: #fff;}\n.popup a {color: #ffbf00; }\n.popup a:hover { background: transparent; color: #ff7f00; border: 0;}\n.popup hr {color: #ffbf00; background: #ffbf00;}\n/*}}}*/\n/***\n!Tiddler Display styles /% ============================================================= %/\n***/\n/*{{{*/\n.title{color: #fff;}\nh1, h2, h3, h4, h5 {\n color: #fff;\n background-color: transparent;\n border-bottom: 1px solid #333;\n}\n\n.subtitle{\n color: #666;\n}\n\n.viewer {color: #fff; }\n\n.viewer table{background: #666; color: #fff;}\n\n.viewer th {background-color: #996; color: #fff;}\n\n.viewer pre, .viewer code {color: #ddd; background-color: #4c4c4c; border: 1px solid #ffbf00;}\n\n.viewer hr {color: #666;}\n\n.tiddler .button {color: #4c4c4c;}\n.tiddler .button:hover { color: #ffbf00; background-color: #4c4c4c;}\n.tiddler .button:active {color: #ffbf00; background-color: #4c4c4c;}\n\n.toolbar {\n color: #4c4c4c;\n}\n\n.toolbar a.button,\n.toolbar a.button:hover,\n.toolbar a.button:active,\n.editorFooter a{\n border: 0;\n}\n\n.footer {\n color: #ddd;\n}\n\n.selected .footer {\n color: #888;\n}\n\n.highlight, .marked {\n color: #000;\n background-color: #ffe72f;\n}\n.editorFooter {\n color: #aaa;\n}\n\n.tab{\n-moz-border-radius-topleft: 3px;\n-moz-border-radius-topright: 3px;\n}\n\n.tagging,\n.tagged{\n background: #4c4c4c;\n border: 1px solid #4c4c4c; \n}\n\n.selected .tagging,\n.selected .tagged{\n background-color: #333;\n border: 1px solid #ffbf00;\n}\n\n.tagging .listTitle,\n.tagged .listTitle{\n color: #fff;\n}\n\n.tagging .button,\n.tagged .button{\n color: #ffbf00;\n border: 0;\n padding: 0;\n}\n\n.tagging .button:hover,\n.tagged .button:hover{\nbackground: transparent;\n}\n\n.selected .isTag .tagging.simple,\n.selected .tagged.simple,\n.isTag .tagging.simple,\n.tagged.simple {\n float: none;\n display: inline;\n border: 0;\n background: transparent;\n color: #fff;\n margin: 0;\n}\n\n.cascade {\n background: #4c4c4c;\n color: #ddd;\n border: 1px solid #ffbf00;\n}\n/*}}}*/</div>
-<div tiddler="axhttpd" modifier="YourName" modified="201106241105" created="200702242231" tags="">axhttpd is a small embedded web server using the axTLS library. It is based originally on the web server written by Doug Currie which is at http://www.hcsw.org/awhttpd.\n\n!@@bgcolor(#ff0000):color(#ffffff):axhttpd Features@@ \n\n!!__Basic Authentication__\n\nBasic Authentication uses a password file called &quot;.htpasswd&quot;, in the directory to be protected. This file is formatted as the familiar colon-separated username/encrypted-password pair, records delimited by newlines. The protection does not carry over to subdirectories. The utility program htpasswd is included to help manually edit .htpasswd files.\n\nThe encryption of this password uses a proprietary algorithm due to the dependency of many crypt libraries on DES. An example is in [[/test_dir/no_http|https://localhost/test_dir/no_http]] (username 'abcd', password is '1234').\n\n//Note: This is an mconf enabled configuration option.//\n\n!!__SSL Protection__\n\nDirectories/files can be accessed using the 'http' or 'https' uri prefix. If normal http access for a directory needs to be disabled, then put &quot;~SSLRequireSSL&quot; into a '.htaccess' file in the directory to be protected. \n\nConversely, use &quot;~SSLDenySSL&quot; to deny access to directories via SSL.\n\nAn example is in [[/test_dir/no_http|http://localhost/test_dir/no_http]] and [[/test_dir/no_ssl|https://localhost/test_dir/no_ssl]].\n\nEntire directories can be denied access with a &quot;Deny all&quot; directive (regardless of SSL or authentication). An example is in [[/test_dir/bin|http://localhost/test_dir/bin]]\n\n!!__CGI__\n\nMost of the CGI 1.1 variables are now placed into the script environment and should work as normal.\n\n!!__Lua and Lua Pages__\n\nThis is a small scripting language gaining popularity in embedded applications due to its small footprint and fast speed.\n\nLua has been incorporated into the build, so simply select it and it will automatically install. Try pointing your browser at [[test_main.html|http://localhost/lua/test_main.html]] to see an example of Lua Pages.\n\n//Note: This is an mconf enabled configuration option.//\n\nThe readline development library may have to be downloaded: //yum install readline-devel//\n\n!!__Directory Listing__\n\nAn mconf option. Allow the files in directories to be displayed. An example is in [[/test_dir|http://localhost/test_dir]]\n\n!!__Other Features__\n\n* Timeout - HTTP 1.1 allows for persistent connections. This is the time allowed for this connection in seconds.\n* Daemon - Puts the process in daemon mode. \n* SSL session cache size - The size of the session cache (a heavily loaded server should maintain many sessions). A session will save on expensive SSL handshaking.\n\n</div>
-</div>
-<!--POST-BODY-START-->
-
-<!--POST-BODY-END-->
- </body>
-</html>
diff --git a/json-c/json-c.vcproj b/json-c/json-c.vcproj
index 34b85b8..85189ba 100644
--- a/json-c/json-c.vcproj
+++ b/json-c/json-c.vcproj
@@ -79,7 +79,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="xcopy &quot;$(ProjectDir)src\json.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\arraylist.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\bits.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_inttypes.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_object.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_object_iterator.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_tokener.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_util.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)configured\json_config.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;"
+ CommandLine="xcopy &quot;$(ProjectDir)src\json.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\arraylist.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\bits.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\debug.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\linkhash.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_inttypes.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_object.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_object_iterator.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_tokener.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_util.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)configured\json_config.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;"
/>
</Configuration>
<Configuration
@@ -149,7 +149,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="xcopy &quot;$(ProjectDir)src\json.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\arraylist.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\bits.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_inttypes.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_object.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_object_iterator.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_tokener.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_util.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)configured\json_config.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;"
+ CommandLine="xcopy &quot;$(ProjectDir)src\json.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\arraylist.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\bits.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\debug.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\linkhash.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_inttypes.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_object.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_object_iterator.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_tokener.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\json_util.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)configured\json_config.h&quot; &quot;$(SolutionDir)build\temp\include\json\&quot; /I /Y /D&#x0D;&#x0A;"
/>
</Configuration>
</Configurations>
diff --git a/pianobar.sln b/pianobar.sln
index f8d8e61..fb8723c 100644
--- a/pianobar.sln
+++ b/pianobar.sln
@@ -17,19 +17,19 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pianobar", "pianobar\pianobar.vcproj", "{D3B44180-848B-4A1F-9176-9891A87876BF}"
ProjectSection(ProjectDependencies) = postProject
{F0B7D905-BD81-4998-8386-333389BE15DE} = {F0B7D905-BD81-4998-8386-333389BE15DE}
- {3A871221-4317-4839-80D9-C2F03DED1AF8} = {3A871221-4317-4839-80D9-C2F03DED1AF8}
+ {4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60} = {4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60}
{65AB4E50-81EF-4BC4-BBA4-8EC4315ADA3F} = {65AB4E50-81EF-4BC4-BBA4-8EC4315ADA3F}
{7DDFB46B-0754-450D-9A7A-4B982E40367D} = {7DDFB46B-0754-450D-9A7A-4B982E40367D}
{75E224E3-6A99-4C8F-9598-9A6F115B91F2} = {75E224E3-6A99-4C8F-9598-9A6F115B91F2}
{CE4CD8F8-E5AB-46F6-ACF3-167687C47C9F} = {CE4CD8F8-E5AB-46F6-ACF3-167687C47C9F}
EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "axTLS", "axTLS\axTLS.vcproj", "{3A871221-4317-4839-80D9-C2F03DED1AF8}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blowfish", "blowfish\blowfish.vcproj", "{F0B7D905-BD81-4998-8386-333389BE15DE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "json-c", "json-c\json-c.vcproj", "{65AB4E50-81EF-4BC4-BBA4-8EC4315ADA3F}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polarssl", "polarssl\polarssl.vcproj", "{4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -52,10 +52,6 @@ Global
{D3B44180-848B-4A1F-9176-9891A87876BF}.Debug|Win32.Build.0 = Debug|Win32
{D3B44180-848B-4A1F-9176-9891A87876BF}.Release|Win32.ActiveCfg = Release|Win32
{D3B44180-848B-4A1F-9176-9891A87876BF}.Release|Win32.Build.0 = Release|Win32
- {3A871221-4317-4839-80D9-C2F03DED1AF8}.Debug|Win32.ActiveCfg = Debug|Win32
- {3A871221-4317-4839-80D9-C2F03DED1AF8}.Debug|Win32.Build.0 = Debug|Win32
- {3A871221-4317-4839-80D9-C2F03DED1AF8}.Release|Win32.ActiveCfg = Release|Win32
- {3A871221-4317-4839-80D9-C2F03DED1AF8}.Release|Win32.Build.0 = Release|Win32
{F0B7D905-BD81-4998-8386-333389BE15DE}.Debug|Win32.ActiveCfg = Debug|Win32
{F0B7D905-BD81-4998-8386-333389BE15DE}.Debug|Win32.Build.0 = Debug|Win32
{F0B7D905-BD81-4998-8386-333389BE15DE}.Release|Win32.ActiveCfg = Release|Win32
@@ -64,6 +60,10 @@ Global
{65AB4E50-81EF-4BC4-BBA4-8EC4315ADA3F}.Debug|Win32.Build.0 = Debug|Win32
{65AB4E50-81EF-4BC4-BBA4-8EC4315ADA3F}.Release|Win32.ActiveCfg = Release|Win32
{65AB4E50-81EF-4BC4-BBA4-8EC4315ADA3F}.Release|Win32.Build.0 = Release|Win32
+ {4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60}.Debug|Win32.Build.0 = Debug|Win32
+ {4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60}.Release|Win32.ActiveCfg = Release|Win32
+ {4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/pianobar/pianobar.vcproj b/pianobar/pianobar.vcproj
index 718525b..8d31423 100644
--- a/pianobar/pianobar.vcproj
+++ b/pianobar/pianobar.vcproj
@@ -64,7 +64,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="libao-mt-debug.lib libmad-mt-debug.lib pthread-win32-mt-debug.lib axTLS-mt-debug.lib winmm.lib ws2_32.lib"
+ AdditionalDependencies="winmm.lib ws2_32.lib"
OutputFile="$(OutDir)\$(ProjectName)-debug.exe"
AdditionalLibraryDirectories="$(SolutionDir)build\temp\lib\"
GenerateDebugInformation="true"
@@ -142,7 +142,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="libao-mt.lib libmad-mt.lib pthread-win32-mt.lib axTLS-mt.lib winmm.lib ws2_32.lib"
+ AdditionalDependencies="winmm.lib ws2_32.lib"
AdditionalLibraryDirectories="$(SolutionDir)build\temp\lib\"
TargetMachine="1"
/>
diff --git a/pianobar/src b/pianobar/src
-Subproject 7d2715a095b0ac4aef35fb385ec761197c5b8dd
+Subproject 58404487f221fd770378ff2b11f8f5eefe513ed
diff --git a/polarssl/polarssl.vcproj b/polarssl/polarssl.vcproj
new file mode 100644
index 0000000..a3ee489
--- /dev/null
+++ b/polarssl/polarssl.vcproj
@@ -0,0 +1,494 @@
+<?xml version="1.0" encoding="windows-1250"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="polarssl"
+ ProjectGUID="{4F001038-5DD8-4E07-A6DE-4D0DD4A6DF60}"
+ RootNamespace="polarssl"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)build\temp\lib\"
+ IntermediateDirectory="$(SolutionDir)build\temp\obj\$(ProjectName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ WholeProgramOptimization="false"
+ AdditionalIncludeDirectories="&quot;$(SolutionDir)compatibility&quot;;&quot;$(ProjectDir)src\include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;BUILDING_CYASSL;NO_HC128;NO_PSK;NO_FILESYSTEM;DEBUG_CYASSL"
+ MinimalRebuild="false"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="0"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\$(ProjectName)-mt-debug.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="xcopy &quot;$(ProjectDir)src\include\polarssl\aes.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\arc4.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\asn1.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\asn1write.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\base64.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\bignum.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\bn_mul.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\camellia.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\certs.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\cipher.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\cipher_wrap.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\config.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\ctr_drbg.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\debug.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\des.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\dhm.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\entropy.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\entropy_poll.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\error.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\gcm.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\havege.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md_wrap.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md2.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md4.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md5.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\net.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\openssl.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\padlock.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\pem.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\pkcs11.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\rsa.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\sha1.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\sha2.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\sha4.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\ssl.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\timing.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\version.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\x509.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\x509write.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\xtea.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)build\temp\lib\"
+ IntermediateDirectory="$(SolutionDir)build\temp\obj\$(ProjectName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="false"
+ WholeProgramOptimization="false"
+ AdditionalIncludeDirectories="&quot;$(SolutionDir)compatibility&quot;;&quot;$(ProjectDir)src\include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;BUILDING_CYASSL;NO_HC128;NO_PSK;NO_FILESYSTEM"
+ MinimalRebuild="false"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="0"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\$(ProjectName)-mt.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="xcopy &quot;$(ProjectDir)src\include\polarssl\aes.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\arc4.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\asn1.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\asn1write.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\base64.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\bignum.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\bn_mul.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\camellia.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\certs.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\cipher.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\cipher_wrap.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\config.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\ctr_drbg.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\debug.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\des.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\dhm.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\entropy.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\entropy_poll.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\error.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\gcm.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\havege.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md_wrap.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md2.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md4.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\md5.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\net.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\openssl.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\padlock.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\pem.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\pkcs11.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\rsa.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\sha1.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\sha2.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\sha4.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\ssl.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\timing.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\version.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\x509.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\x509write.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\polarssl\xtea.h&quot; &quot;$(SolutionDir)build\temp\include\polarssl\&quot; /I /Y /D"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="include"
+ >
+ <File
+ RelativePath=".\src\include\polarssl\aes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\arc4.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\asn1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\asn1write.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\base64.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\bignum.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\bn_mul.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\camellia.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\certs.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\cipher.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\cipher_wrap.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\config.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\ctr_drbg.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\debug.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\des.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\dhm.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\entropy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\entropy_poll.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\error.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\gcm.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\havege.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\md.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\md2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\md4.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\md5.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\md_wrap.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\net.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\openssl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\padlock.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\pem.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\pkcs11.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\rsa.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\sha1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\sha2.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\sha4.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\ssl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\timing.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\version.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\x509.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\x509write.h"
+ >
+ </File>
+ <File
+ RelativePath=".\src\include\polarssl\xtea.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="src"
+ >
+ <File
+ RelativePath=".\src\library\aes.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\arc4.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\asn1parse.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\asn1write.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\base64.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\bignum.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\camellia.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\certs.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\cipher.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\cipher_wrap.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\ctr_drbg.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\debug.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\des.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\dhm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\entropy.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\entropy_poll.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\error.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\gcm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\havege.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\md.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\md2.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\md4.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\md5.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\md_wrap.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\net.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\padlock.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\pem.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\pkcs11.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\rsa.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\sha1.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\sha2.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\sha4.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\ssl_cli.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\ssl_srv.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\ssl_tls.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\timing.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\version.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\x509parse.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\x509write.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\library\xtea.c"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/polarssl/src/LICENSE b/polarssl/src/LICENSE
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/polarssl/src/LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/polarssl/src/include/polarssl/aes.h b/polarssl/src/include/polarssl/aes.h
new file mode 100644
index 0000000..80fd6d9
--- /dev/null
+++ b/polarssl/src/include/polarssl/aes.h
@@ -0,0 +1,176 @@
+/**
+ * \file aes.h
+ *
+ * \brief AES block cipher
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_AES_H
+#define POLARSSL_AES_H
+
+#include <string.h>
+
+#define AES_ENCRYPT 1
+#define AES_DECRYPT 0
+
+#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
+#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
+
+/**
+ * \brief AES context structure
+ */
+typedef struct
+{
+ int nr; /*!< number of rounds */
+ unsigned long *rk; /*!< AES round keys */
+ unsigned long buf[68]; /*!< unaligned data */
+}
+aes_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief AES key schedule (encryption)
+ *
+ * \param ctx AES context to be initialized
+ * \param key encryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief AES key schedule (decryption)
+ *
+ * \param ctx AES context to be initialized
+ * \param key decryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief AES-ECB block encryption/decryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_ecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief AES-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (16 bytes)
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
+ */
+int aes_crypt_cbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief AES-CFB128 buffer encryption/decryption.
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
+ *
+ * both
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/*
+ * \brief AES-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * Note: Due to the nature of CTR you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
+ *
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int aes_crypt_ctr( aes_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output );
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */
diff --git a/polarssl/src/include/polarssl/arc4.h b/polarssl/src/include/polarssl/arc4.h
new file mode 100644
index 0000000..48ad60b
--- /dev/null
+++ b/polarssl/src/include/polarssl/arc4.h
@@ -0,0 +1,80 @@
+/**
+ * \file arc4.h
+ *
+ * \brief The ARCFOUR stream cipher
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ARC4_H
+#define POLARSSL_ARC4_H
+
+#include <string.h>
+
+/**
+ * \brief ARC4 context structure
+ */
+typedef struct
+{
+ int x; /*!< permutation index */
+ int y; /*!< permutation index */
+ unsigned char m[256]; /*!< permutation table */
+}
+arc4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief ARC4 key schedule
+ *
+ * \param ctx ARC4 context to be initialized
+ * \param key the secret key
+ * \param keylen length of the key
+ */
+void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen );
+
+/**
+ * \brief ARC4 cipher function
+ *
+ * \param ctx ARC4 context
+ * \param length length of the input data
+ * \param input buffer holding the input data
+ * \param output buffer for the output data
+ *
+ * \return 0 if successful
+ */
+int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
+ unsigned char *output );
+
+/*
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int arc4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* arc4.h */
diff --git a/polarssl/src/include/polarssl/asn1.h b/polarssl/src/include/polarssl/asn1.h
new file mode 100644
index 0000000..893292d
--- /dev/null
+++ b/polarssl/src/include/polarssl/asn1.h
@@ -0,0 +1,246 @@
+/**
+ * \file asn1.h
+ *
+ * \brief Generic ASN.1 parsing
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ASN1_H
+#define POLARSSL_ASN1_H
+
+#include "config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "bignum.h"
+#endif
+
+#include <string.h>
+
+/**
+ * \addtogroup asn1_module
+ * \{
+ */
+
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity.
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define POLARSSL_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */
+#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */
+#define POLARSSL_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */
+#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */
+#define POLARSSL_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */
+#define POLARSSL_ERR_ASN1_MALLOC_FAILED -0x006A /**< Memory allocation failed */
+#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */
+
+/* \} name */
+
+/**
+ * \name DER constants
+ * These constants comply with DER encoded the ANS1 type tags.
+ * DER encoding uses hexadecimal representation.
+ * An example DER sequence is:\n
+ * - 0x02 -- tag indicating INTEGER
+ * - 0x01 -- length in octets
+ * - 0x05 -- value
+ * Such sequences are typically read into \c ::x509_buf.
+ * \{
+ */
+#define ASN1_BOOLEAN 0x01
+#define ASN1_INTEGER 0x02
+#define ASN1_BIT_STRING 0x03
+#define ASN1_OCTET_STRING 0x04
+#define ASN1_NULL 0x05
+#define ASN1_OID 0x06
+#define ASN1_UTF8_STRING 0x0C
+#define ASN1_SEQUENCE 0x10
+#define ASN1_SET 0x11
+#define ASN1_PRINTABLE_STRING 0x13
+#define ASN1_T61_STRING 0x14
+#define ASN1_IA5_STRING 0x16
+#define ASN1_UTC_TIME 0x17
+#define ASN1_GENERALIZED_TIME 0x18
+#define ASN1_UNIVERSAL_STRING 0x1C
+#define ASN1_BMP_STRING 0x1E
+#define ASN1_PRIMITIVE 0x00
+#define ASN1_CONSTRUCTED 0x20
+#define ASN1_CONTEXT_SPECIFIC 0x80
+/* \} name */
+/* \} addtogroup asn1_module */
+
+/** Returns the size of the binary string, without the trailing \\0 */
+#define OID_SIZE(x) (sizeof(x) - 1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Functions to parse ASN.1 data structures
+ * \{
+ */
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef struct _asn1_buf
+{
+ int tag; /**< ASN1 type, e.g. ASN1_UTF8_STRING. */
+ size_t len; /**< ASN1 length, e.g. in octets. */
+ unsigned char *p; /**< ASN1 data, e.g. in ASCII. */
+}
+asn1_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef struct _asn1_bitstring
+{
+ size_t len; /**< ASN1 length, e.g. in octets. */
+ unsigned char unused_bits; /**< Number of unused bits at the end of the string */
+ unsigned char *p; /**< Raw ASN1 data for the bit string */
+}
+asn1_bitstring;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef struct _asn1_sequence
+{
+ asn1_buf buf; /**< Buffer containing the given ASN.1 item. */
+ struct _asn1_sequence *next; /**< The next entry in the sequence. */
+}
+asn1_sequence;
+
+/**
+ * Get the length of an ASN.1 element.
+ * Updates the pointer to immediately behind the length.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param len The variable that will receive the value
+ *
+ * \return 0 if successful, POLARSSL_ERR_ASN1_OUT_OF_DATA on reaching
+ * end of data, POLARSSL_ERR_ASN1_INVALID_LENGTH if length is
+ * unparseable.
+ */
+int asn1_get_len( unsigned char **p,
+ const unsigned char *end,
+ size_t *len );
+
+/**
+ * Get the tag and length of the tag. Check for the requested tag.
+ * Updates the pointer to immediately behind the tag and length.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param len The variable that will receive the length
+ * \param tag The expected tag
+ *
+ * \return 0 if successful, POLARSSL_ERR_ASN1_UNEXPECTED_TAG if tag did
+ * not match requested tag, or another specific ASN.1 error code.
+ */
+int asn1_get_tag( unsigned char **p,
+ const unsigned char *end,
+ size_t *len, int tag );
+
+/**
+ * Retrieve a boolean ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param val The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_bool( unsigned char **p,
+ const unsigned char *end,
+ int *val );
+
+/**
+ * Retrieve an integer ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param val The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val );
+
+/**
+ * Retrieve a bitstring ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param bs The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+ asn1_bitstring *bs);
+
+/**
+ * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ * Updated the pointer to immediately behind the full sequence tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param cur First variable in the chain to fill
+ * \param tag Type of sequence
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int asn1_get_sequence_of( unsigned char **p,
+ const unsigned char *end,
+ asn1_sequence *cur,
+ int tag);
+
+#if defined(POLARSSL_BIGNUM_C)
+/**
+ * Retrieve a MPI value from an integer ASN.1 tag.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param X The MPI that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 or MPI error code.
+ */
+int asn1_get_mpi( unsigned char **p,
+ const unsigned char *end,
+ mpi *X );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* asn1.h */
diff --git a/polarssl/src/include/polarssl/asn1write.h b/polarssl/src/include/polarssl/asn1write.h
new file mode 100644
index 0000000..52b9baa
--- /dev/null
+++ b/polarssl/src/include/polarssl/asn1write.h
@@ -0,0 +1,46 @@
+/**
+ * \file asn1write.h
+ *
+ * \brief ASN.1 buffer writing functionality
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ASN1_WRITE_H
+#define POLARSSL_ASN1_WRITE_H
+
+#include "asn1.h"
+
+#define ASN1_CHK_ADD(g, f) if( ( ret = f ) < 0 ) return( ret ); else g += ret
+
+int asn1_write_len( unsigned char **p, unsigned char *start, size_t len );
+int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag );
+int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X );
+int asn1_write_null( unsigned char **p, unsigned char *start );
+int asn1_write_oid( unsigned char **p, unsigned char *start, char *oid );
+int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, char *algorithm_oid );
+int asn1_write_int( unsigned char **p, unsigned char *start, int val );
+int asn1_write_printable_string( unsigned char **p, unsigned char *start,
+ char *text );
+int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+ char *text );
+
+#endif /* POLARSSL_ASN1_WRITE_H */
diff --git a/polarssl/src/include/polarssl/base64.h b/polarssl/src/include/polarssl/base64.h
new file mode 100644
index 0000000..883215d
--- /dev/null
+++ b/polarssl/src/include/polarssl/base64.h
@@ -0,0 +1,87 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BASE64_H
+#define POLARSSL_BASE64_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */
+#define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Encode a buffer into base64 format
+ *
+ * \param dst destination buffer
+ * \param dlen size of the buffer
+ * \param src source buffer
+ * \param slen amount of data to be encoded
+ *
+ * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
+ * *dlen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *dlen = 0 to obtain the
+ * required buffer size in *dlen
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+ const unsigned char *src, size_t slen );
+
+/**
+ * \brief Decode a base64-formatted buffer
+ *
+ * \param dst destination buffer
+ * \param dlen size of the buffer
+ * \param src source buffer
+ * \param slen amount of data to be decoded
+ *
+ * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
+ * POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not
+ * correct. *dlen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *dlen = 0 to obtain the
+ * required buffer size in *dlen
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+ const unsigned char *src, size_t slen );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */
diff --git a/polarssl/src/include/polarssl/bignum.h b/polarssl/src/include/polarssl/bignum.h
new file mode 100644
index 0000000..ad03308
--- /dev/null
+++ b/polarssl/src/include/polarssl/bignum.h
@@ -0,0 +1,632 @@
+/**
+ * \file bignum.h
+ *
+ * \brief Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BIGNUM_H
+#define POLARSSL_BIGNUM_H
+
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+
+#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */
+#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */
+#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */
+#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */
+#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */
+#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */
+#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */
+
+#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
+
+/*
+ * Maximum size MPIs are allowed to grow to in number of limbs.
+ */
+#define POLARSSL_MPI_MAX_LIMBS 10000
+
+/*
+ * Maximum window size used for modular exponentiation. Default: 6
+ * Minimum value: 1. Maximum value: 6.
+ *
+ * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used
+ * for the sliding window calculation. (So 64 by default)
+ *
+ * Reduction in size, reduces speed.
+ */
+#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
+
+/*
+ * Maximum size of MPIs allowed in bits and bytes for user-MPIs.
+ * ( Default: 512 bytes => 4096 bits )
+ *
+ * Note: Calculations can results temporarily in larger MPIs. So the number
+ * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher.
+ */
+#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */
+#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */
+
+/*
+ * When reading from files with mpi_read_file() the buffer should have space
+ * for a (short) label, the MPI (in the provided radix), the newline
+ * characters and the '\0'.
+ *
+ * By default we assume at least a 10 char label, a minimum radix of 10
+ * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
+ */
+#define POLARSSL_MPI_READ_BUFFER_SIZE 1250
+
+/*
+ * Define the base integer type, architecture-wise
+ */
+#if defined(POLARSSL_HAVE_INT8)
+typedef signed char t_sint;
+typedef unsigned char t_uint;
+typedef unsigned short t_udbl;
+#else
+#if defined(POLARSSL_HAVE_INT16)
+typedef signed short t_sint;
+typedef unsigned short t_uint;
+typedef unsigned long t_udbl;
+#else
+ typedef signed long t_sint;
+ typedef unsigned long t_uint;
+ #if defined(_MSC_VER) && defined(_M_IX86)
+ typedef unsigned __int64 t_udbl;
+ #else
+ #if defined(__GNUC__) && ( \
+ defined(__amd64__) || defined(__x86_64__) || \
+ defined(__ppc64__) || defined(__powerpc64__) || \
+ defined(__ia64__) || defined(__alpha__) || \
+ (defined(__sparc__) && defined(__arch64__)) || \
+ defined(__s390x__) )
+ typedef unsigned int t_udbl __attribute__((mode(TI)));
+ #define POLARSSL_HAVE_LONGLONG
+ #else
+ #if defined(POLARSSL_HAVE_LONGLONG)
+ typedef unsigned long long t_udbl;
+ #endif
+ #endif
+ #endif
+#endif
+#endif
+
+/**
+ * \brief MPI structure
+ */
+typedef struct
+{
+ int s; /*!< integer sign */
+ size_t n; /*!< total # of limbs */
+ t_uint *p; /*!< pointer to limbs */
+}
+mpi;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initialize one MPI
+ *
+ * \param X One MPI to initialize.
+ */
+void mpi_init( mpi *X );
+
+/**
+ * \brief Unallocate one MPI
+ *
+ * \param X One MPI to unallocate.
+ */
+void mpi_free( mpi *X );
+
+/**
+ * \brief Enlarge to the specified number of limbs
+ *
+ * \param X MPI to grow
+ * \param nblimbs The target number of limbs
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_grow( mpi *X, size_t nblimbs );
+
+/**
+ * \brief Copy the contents of Y into X
+ *
+ * \param X Destination MPI
+ * \param Y Source MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_copy( mpi *X, const mpi *Y );
+
+/**
+ * \brief Swap the contents of X and Y
+ *
+ * \param X First MPI value
+ * \param Y Second MPI value
+ */
+void mpi_swap( mpi *X, mpi *Y );
+
+/**
+ * \brief Set value from integer
+ *
+ * \param X MPI to set
+ * \param z Value to use
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_lset( mpi *X, t_sint z );
+
+/*
+ * \brief Get a specific bit from X
+ *
+ * \param X MPI to use
+ * \param pos Zero-based index of the bit in X
+ *
+ * \return Either a 0 or a 1
+ */
+int mpi_get_bit( mpi *X, size_t pos );
+
+/*
+ * \brief Set a bit of X to a specific value of 0 or 1
+ *
+ * \note Will grow X if necessary to set a bit to 1 in a not yet
+ * existing limb. Will not grow if bit should be set to 0
+ *
+ * \param X MPI to use
+ * \param pos Zero-based index of the bit in X
+ * \param val The value to set the bit to (0 or 1)
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val );
+
+/**
+ * \brief Return the number of least significant bits
+ *
+ * \param X MPI to use
+ */
+size_t mpi_lsb( const mpi *X );
+
+/**
+ * \brief Return the number of most significant bits
+ *
+ * \param X MPI to use
+ */
+size_t mpi_msb( const mpi *X );
+
+/**
+ * \brief Return the total size in bytes
+ *
+ * \param X MPI to use
+ */
+size_t mpi_size( const mpi *X );
+
+/**
+ * \brief Import from an ASCII string
+ *
+ * \param X Destination MPI
+ * \param radix Input numeric base
+ * \param s Null-terminated string buffer
+ *
+ * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_string( mpi *X, int radix, const char *s );
+
+/**
+ * \brief Export into an ASCII string
+ *
+ * \param X Source MPI
+ * \param radix Output numeric base
+ * \param s String buffer
+ * \param slen String buffer size
+ *
+ * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code.
+ * *slen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *slen = 0 to obtain the
+ * minimum required buffer size in *slen.
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen );
+
+/**
+ * \brief Read X from an opened file
+ *
+ * \param X Destination MPI
+ * \param radix Input numeric base
+ * \param fin Input file handle
+ *
+ * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if
+ * the file read buffer is too small or a
+ * POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief Write X into an opened file, or stdout if fout is NULL
+ *
+ * \param p Prefix, can be NULL
+ * \param X Source MPI
+ * \param radix Output numeric base
+ * \param fout Output file handle (can be NULL)
+ *
+ * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note Set fout == NULL to print X on the console.
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
+
+/**
+ * \brief Import X from unsigned binary data, big endian
+ *
+ * \param X Destination MPI
+ * \param buf Input buffer
+ * \param buflen Input buffer size
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Export X into unsigned binary data, big endian
+ *
+ * \param X Source MPI
+ * \param buf Output buffer
+ * \param buflen Output buffer size
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Left-shift: X <<= count
+ *
+ * \param X MPI to shift
+ * \param count Amount to shift
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_shift_l( mpi *X, size_t count );
+
+/**
+ * \brief Right-shift: X >>= count
+ *
+ * \param X MPI to shift
+ * \param count Amount to shift
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_shift_r( mpi *X, size_t count );
+
+/**
+ * \brief Compare unsigned values
+ *
+ * \param X Left-hand MPI
+ * \param Y Right-hand MPI
+ *
+ * \return 1 if |X| is greater than |Y|,
+ * -1 if |X| is lesser than |Y| or
+ * 0 if |X| is equal to |Y|
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \param X Left-hand MPI
+ * \param Y Right-hand MPI
+ *
+ * \return 1 if X is greater than Y,
+ * -1 if X is lesser than Y or
+ * 0 if X is equal to Y
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \param X Left-hand MPI
+ * \param z The integer value to compare to
+ *
+ * \return 1 if X is greater than z,
+ * -1 if X is lesser than z or
+ * 0 if X is equal to z
+ */
+int mpi_cmp_int( const mpi *X, t_sint z );
+
+/**
+ * \brief Unsigned addition: X = |A| + |B|
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Unsigned substraction: X = |A| - |B|
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed addition: X = A + B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed substraction: X = A - B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Signed addition: X = A + b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to add
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Signed substraction: X = A - b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to subtract
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Baseline multiplication: X = A * B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief Baseline multiplication: X = A * b
+ * Note: b is an unsigned integer type, thus
+ * Negative values of b are ignored.
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to multiply with
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b );
+
+/**
+ * \brief Division by mpi: A = Q * B + R
+ *
+ * \param Q Destination MPI for the quotient
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief Division by int: A = Q * b + R
+ *
+ * \param Q Destination MPI for the quotient
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param b Integer to divide by
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b );
+
+/**
+ * \brief Modulo: R = A mod B
+ *
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief Modulo: r = A mod b
+ *
+ * \param r Destination t_uint
+ * \param A Left-hand MPI
+ * \param b Integer to divide by
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
+
+/**
+ * \brief Sliding-window exponentiation: X = A^E mod N
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param E Exponent MPI
+ * \param N Modular MPI
+ * \param _RR Speed-up MPI used for recalculations
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
+ *
+ * \note _RR is used to avoid re-computing R*R mod N across
+ * multiple calls, which speeds up things a bit. It can
+ * be set to NULL if the extra performance is unneeded.
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
+
+/**
+ * \brief Fill an MPI X with size bytes of random
+ *
+ * \param X Destination MPI
+ * \param size Size in bytes
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_fill_random( mpi *X, size_t size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Greatest common divisor: G = gcd(A, B)
+ *
+ * \param G Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
+
+/**
+ * \brief Modular inverse: X = A^-1 mod N
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param N Right-hand MPI
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
+ POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
+
+/**
+ * \brief Miller-Rabin primality test
+ *
+ * \param X MPI to check
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mpi_is_prime( mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Prime number generation
+ *
+ * \param X Destination MPI
+ * \param nbits Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS )
+ * \param dh_flag If 1, then (X-1)/2 will be prime too
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */
diff --git a/polarssl/src/include/polarssl/bn_mul.h b/polarssl/src/include/polarssl/bn_mul.h
new file mode 100644
index 0000000..a6a2c65
--- /dev/null
+++ b/polarssl/src/include/polarssl/bn_mul.h
@@ -0,0 +1,742 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * Multiply source vector [s] with b, add result
+ * to destination vector [d] and set carry c.
+ *
+ * Currently supports:
+ *
+ * . IA-32 (386+) . AMD64 / EM64T
+ * . IA-32 (SSE2) . Motorola 68000
+ * . PowerPC, 32-bit . MicroBlaze
+ * . PowerPC, 64-bit . TriCore
+ * . SPARC v8 . ARM v3+
+ * . Alpha . MIPS32
+ * . C, longlong . C, generic
+ */
+#ifndef POLARSSL_BN_MUL_H
+#define POLARSSL_BN_MUL_H
+
+#include "bignum.h"
+
+#if defined(POLARSSL_HAVE_ASM)
+
+#if defined(__GNUC__)
+#if defined(__i386__)
+
+#define MULADDC_INIT \
+ asm( " \
+ movl %%ebx, %0; \
+ movl %5, %%esi; \
+ movl %6, %%edi; \
+ movl %7, %%ecx; \
+ movl %8, %%ebx; \
+ "
+
+#define MULADDC_CORE \
+ " \
+ lodsl; \
+ mull %%ebx; \
+ addl %%ecx, %%eax; \
+ adcl $0, %%edx; \
+ addl (%%edi), %%eax; \
+ adcl $0, %%edx; \
+ movl %%edx, %%ecx; \
+ stosl; \
+ "
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define MULADDC_HUIT \
+ " \
+ movd %%ecx, %%mm1; \
+ movd %%ebx, %%mm0; \
+ movd (%%edi), %%mm3; \
+ paddq %%mm3, %%mm1; \
+ movd (%%esi), %%mm2; \
+ pmuludq %%mm0, %%mm2; \
+ movd 4(%%esi), %%mm4; \
+ pmuludq %%mm0, %%mm4; \
+ movd 8(%%esi), %%mm6; \
+ pmuludq %%mm0, %%mm6; \
+ movd 12(%%esi), %%mm7; \
+ pmuludq %%mm0, %%mm7; \
+ paddq %%mm2, %%mm1; \
+ movd 4(%%edi), %%mm3; \
+ paddq %%mm4, %%mm3; \
+ movd 8(%%edi), %%mm5; \
+ paddq %%mm6, %%mm5; \
+ movd 12(%%edi), %%mm4; \
+ paddq %%mm4, %%mm7; \
+ movd %%mm1, (%%edi); \
+ movd 16(%%esi), %%mm2; \
+ pmuludq %%mm0, %%mm2; \
+ psrlq $32, %%mm1; \
+ movd 20(%%esi), %%mm4; \
+ pmuludq %%mm0, %%mm4; \
+ paddq %%mm3, %%mm1; \
+ movd 24(%%esi), %%mm6; \
+ pmuludq %%mm0, %%mm6; \
+ movd %%mm1, 4(%%edi); \
+ psrlq $32, %%mm1; \
+ movd 28(%%esi), %%mm3; \
+ pmuludq %%mm0, %%mm3; \
+ paddq %%mm5, %%mm1; \
+ movd 16(%%edi), %%mm5; \
+ paddq %%mm5, %%mm2; \
+ movd %%mm1, 8(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm7, %%mm1; \
+ movd 20(%%edi), %%mm5; \
+ paddq %%mm5, %%mm4; \
+ movd %%mm1, 12(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm2, %%mm1; \
+ movd 24(%%edi), %%mm5; \
+ paddq %%mm5, %%mm6; \
+ movd %%mm1, 16(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm4, %%mm1; \
+ movd 28(%%edi), %%mm5; \
+ paddq %%mm5, %%mm3; \
+ movd %%mm1, 20(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm6, %%mm1; \
+ movd %%mm1, 24(%%edi); \
+ psrlq $32, %%mm1; \
+ paddq %%mm3, %%mm1; \
+ movd %%mm1, 28(%%edi); \
+ addl $32, %%edi; \
+ addl $32, %%esi; \
+ psrlq $32, %%mm1; \
+ movd %%mm1, %%ecx; \
+ "
+
+#define MULADDC_STOP \
+ " \
+ emms; \
+ movl %4, %%ebx; \
+ movl %%ecx, %1; \
+ movl %%edi, %2; \
+ movl %%esi, %3; \
+ " \
+ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "eax", "ecx", "edx", "esi", "edi" \
+ );
+
+#else
+
+#define MULADDC_STOP \
+ " \
+ movl %4, %%ebx; \
+ movl %%ecx, %1; \
+ movl %%edi, %2; \
+ movl %%esi, %3; \
+ " \
+ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "eax", "ecx", "edx", "esi", "edi" \
+ );
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT \
+ asm( "movq %0, %%rsi " :: "m" (s)); \
+ asm( "movq %0, %%rdi " :: "m" (d)); \
+ asm( "movq %0, %%rcx " :: "m" (c)); \
+ asm( "movq %0, %%rbx " :: "m" (b)); \
+ asm( "xorq %r8, %r8 " );
+
+#define MULADDC_CORE \
+ asm( "movq (%rsi),%rax " ); \
+ asm( "mulq %rbx " ); \
+ asm( "addq $8, %rsi " ); \
+ asm( "addq %rcx, %rax " ); \
+ asm( "movq %r8, %rcx " ); \
+ asm( "adcq $0, %rdx " ); \
+ asm( "nop " ); \
+ asm( "addq %rax, (%rdi) " ); \
+ asm( "adcq %rdx, %rcx " ); \
+ asm( "addq $8, %rdi " );
+
+#define MULADDC_STOP \
+ asm( "movq %%rcx, %0 " : "=m" (c)); \
+ asm( "movq %%rdi, %0 " : "=m" (d)); \
+ asm( "movq %%rsi, %0 " : "=m" (s) :: \
+ "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT \
+ asm( "movl %0, %%a2 " :: "m" (s)); \
+ asm( "movl %0, %%a3 " :: "m" (d)); \
+ asm( "movl %0, %%d3 " :: "m" (c)); \
+ asm( "movl %0, %%d2 " :: "m" (b)); \
+ asm( "moveq #0, %d0 " );
+
+#define MULADDC_CORE \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "moveq #0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "addxl %d4, %d3 " );
+
+#define MULADDC_STOP \
+ asm( "movl %%d3, %0 " : "=m" (c)); \
+ asm( "movl %%a3, %0 " : "=m" (d)); \
+ asm( "movl %%a2, %0 " : "=m" (s) :: \
+ "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
+
+#define MULADDC_HUIT \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d4:%d1 " ); \
+ asm( "addxl %d3, %d1 " ); \
+ asm( "addxl %d0, %d4 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "movel %a2@+, %d1 " ); \
+ asm( "mulul %d2, %d3:%d1 " ); \
+ asm( "addxl %d4, %d1 " ); \
+ asm( "addxl %d0, %d3 " ); \
+ asm( "addl %d1, %a3@+ " ); \
+ asm( "addxl %d0, %d3 " );
+
+#endif /* MC68000 */
+
+#if defined(__powerpc__) || defined(__ppc__)
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ asm( "ld r3, %0 " :: "m" (s)); \
+ asm( "ld r4, %0 " :: "m" (d)); \
+ asm( "ld r5, %0 " :: "m" (c)); \
+ asm( "ld r6, %0 " :: "m" (b)); \
+ asm( "addi r3, r3, -8 " ); \
+ asm( "addi r4, r4, -8 " ); \
+ asm( "addic r5, r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "ldu r7, 8(r3) " ); \
+ asm( "mulld r8, r7, r6 " ); \
+ asm( "mulhdu r9, r7, r6 " ); \
+ asm( "adde r8, r8, r5 " ); \
+ asm( "ld r7, 8(r4) " ); \
+ asm( "addze r5, r9 " ); \
+ asm( "addc r8, r8, r7 " ); \
+ asm( "stdu r8, 8(r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze r5, r5 " ); \
+ asm( "addi r4, r4, 8 " ); \
+ asm( "addi r3, r3, 8 " ); \
+ asm( "std r5, %0 " : "=m" (c)); \
+ asm( "std r4, %0 " : "=m" (d)); \
+ asm( "std r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT \
+ asm( "ld %%r3, %0 " :: "m" (s)); \
+ asm( "ld %%r4, %0 " :: "m" (d)); \
+ asm( "ld %%r5, %0 " :: "m" (c)); \
+ asm( "ld %%r6, %0 " :: "m" (b)); \
+ asm( "addi %r3, %r3, -8 " ); \
+ asm( "addi %r4, %r4, -8 " ); \
+ asm( "addic %r5, %r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "ldu %r7, 8(%r3) " ); \
+ asm( "mulld %r8, %r7, %r6 " ); \
+ asm( "mulhdu %r9, %r7, %r6 " ); \
+ asm( "adde %r8, %r8, %r5 " ); \
+ asm( "ld %r7, 8(%r4) " ); \
+ asm( "addze %r5, %r9 " ); \
+ asm( "addc %r8, %r8, %r7 " ); \
+ asm( "stdu %r8, 8(%r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze %r5, %r5 " ); \
+ asm( "addi %r4, %r4, 8 " ); \
+ asm( "addi %r3, %r3, 8 " ); \
+ asm( "std %%r5, %0 " : "=m" (c)); \
+ asm( "std %%r4, %0 " : "=m" (d)); \
+ asm( "std %%r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#else /* PPC32 */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ asm( "lwz r3, %0 " :: "m" (s)); \
+ asm( "lwz r4, %0 " :: "m" (d)); \
+ asm( "lwz r5, %0 " :: "m" (c)); \
+ asm( "lwz r6, %0 " :: "m" (b)); \
+ asm( "addi r3, r3, -4 " ); \
+ asm( "addi r4, r4, -4 " ); \
+ asm( "addic r5, r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "lwzu r7, 4(r3) " ); \
+ asm( "mullw r8, r7, r6 " ); \
+ asm( "mulhwu r9, r7, r6 " ); \
+ asm( "adde r8, r8, r5 " ); \
+ asm( "lwz r7, 4(r4) " ); \
+ asm( "addze r5, r9 " ); \
+ asm( "addc r8, r8, r7 " ); \
+ asm( "stwu r8, 4(r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze r5, r5 " ); \
+ asm( "addi r4, r4, 4 " ); \
+ asm( "addi r3, r3, 4 " ); \
+ asm( "stw r5, %0 " : "=m" (c)); \
+ asm( "stw r4, %0 " : "=m" (d)); \
+ asm( "stw r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT \
+ asm( "lwz %%r3, %0 " :: "m" (s)); \
+ asm( "lwz %%r4, %0 " :: "m" (d)); \
+ asm( "lwz %%r5, %0 " :: "m" (c)); \
+ asm( "lwz %%r6, %0 " :: "m" (b)); \
+ asm( "addi %r3, %r3, -4 " ); \
+ asm( "addi %r4, %r4, -4 " ); \
+ asm( "addic %r5, %r5, 0 " );
+
+#define MULADDC_CORE \
+ asm( "lwzu %r7, 4(%r3) " ); \
+ asm( "mullw %r8, %r7, %r6 " ); \
+ asm( "mulhwu %r9, %r7, %r6 " ); \
+ asm( "adde %r8, %r8, %r5 " ); \
+ asm( "lwz %r7, 4(%r4) " ); \
+ asm( "addze %r5, %r9 " ); \
+ asm( "addc %r8, %r8, %r7 " ); \
+ asm( "stwu %r8, 4(%r4) " );
+
+#define MULADDC_STOP \
+ asm( "addze %r5, %r5 " ); \
+ asm( "addi %r4, %r4, 4 " ); \
+ asm( "addi %r3, %r3, 4 " ); \
+ asm( "stw %%r5, %0 " : "=m" (c)); \
+ asm( "stw %%r4, %0 " : "=m" (d)); \
+ asm( "stw %%r3, %0 " : "=m" (s) :: \
+ "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#endif /* PPC32 */
+#endif /* PPC64 */
+
+#if defined(__sparc__)
+
+#define MULADDC_INIT \
+ asm( "ld %0, %%o0 " :: "m" (s)); \
+ asm( "ld %0, %%o1 " :: "m" (d)); \
+ asm( "ld %0, %%o2 " :: "m" (c)); \
+ asm( "ld %0, %%o3 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ld [%o0], %o4 " ); \
+ asm( "inc 4, %o0 " ); \
+ asm( "ld [%o1], %o5 " ); \
+ asm( "umul %o3, %o4, %o4 " ); \
+ asm( "addcc %o4, %o2, %o4 " ); \
+ asm( "rd %y, %g1 " ); \
+ asm( "addx %g1, 0, %g1 " ); \
+ asm( "addcc %o4, %o5, %o4 " ); \
+ asm( "st %o4, [%o1] " ); \
+ asm( "addx %g1, 0, %o2 " ); \
+ asm( "inc 4, %o1 " );
+
+#define MULADDC_STOP \
+ asm( "st %%o2, %0 " : "=m" (c)); \
+ asm( "st %%o1, %0 " : "=m" (d)); \
+ asm( "st %%o0, %0 " : "=m" (s) :: \
+ "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
+
+#endif /* SPARCv8 */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT \
+ asm( "lwi r3, %0 " :: "m" (s)); \
+ asm( "lwi r4, %0 " :: "m" (d)); \
+ asm( "lwi r5, %0 " :: "m" (c)); \
+ asm( "lwi r6, %0 " :: "m" (b)); \
+ asm( "andi r7, r6, 0xffff" ); \
+ asm( "bsrli r6, r6, 16 " );
+
+#define MULADDC_CORE \
+ asm( "lhui r8, r3, 0 " ); \
+ asm( "addi r3, r3, 2 " ); \
+ asm( "lhui r9, r3, 0 " ); \
+ asm( "addi r3, r3, 2 " ); \
+ asm( "mul r10, r9, r6 " ); \
+ asm( "mul r11, r8, r7 " ); \
+ asm( "mul r12, r9, r7 " ); \
+ asm( "mul r13, r8, r6 " ); \
+ asm( "bsrli r8, r10, 16 " ); \
+ asm( "bsrli r9, r11, 16 " ); \
+ asm( "add r13, r13, r8 " ); \
+ asm( "add r13, r13, r9 " ); \
+ asm( "bslli r10, r10, 16 " ); \
+ asm( "bslli r11, r11, 16 " ); \
+ asm( "add r12, r12, r10 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "add r12, r12, r11 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "lwi r10, r4, 0 " ); \
+ asm( "add r12, r12, r10 " ); \
+ asm( "addc r13, r13, r0 " ); \
+ asm( "add r12, r12, r5 " ); \
+ asm( "addc r5, r13, r0 " ); \
+ asm( "swi r12, r4, 0 " ); \
+ asm( "addi r4, r4, 4 " );
+
+#define MULADDC_STOP \
+ asm( "swi r5, %0 " : "=m" (c)); \
+ asm( "swi r4, %0 " : "=m" (d)); \
+ asm( "swi r3, %0 " : "=m" (s) :: \
+ "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \
+ "r9", "r10", "r11", "r12", "r13" );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT \
+ asm( "ld.a %%a2, %0 " :: "m" (s)); \
+ asm( "ld.a %%a3, %0 " :: "m" (d)); \
+ asm( "ld.w %%d4, %0 " :: "m" (c)); \
+ asm( "ld.w %%d1, %0 " :: "m" (b)); \
+ asm( "xor %d5, %d5 " );
+
+#define MULADDC_CORE \
+ asm( "ld.w %d0, [%a2+] " ); \
+ asm( "madd.u %e2, %e4, %d0, %d1 " ); \
+ asm( "ld.w %d0, [%a3] " ); \
+ asm( "addx %d2, %d2, %d0 " ); \
+ asm( "addc %d3, %d3, 0 " ); \
+ asm( "mov %d4, %d3 " ); \
+ asm( "st.w [%a3+], %d2 " );
+
+#define MULADDC_STOP \
+ asm( "st.w %0, %%d4 " : "=m" (c)); \
+ asm( "st.a %0, %%a3 " : "=m" (d)); \
+ asm( "st.a %0, %%a2 " : "=m" (s) :: \
+ "d0", "d1", "e2", "d4", "a2", "a3" );
+
+#endif /* TriCore */
+
+#if defined(__arm__)
+
+#if !defined(__thumb__)
+
+#define MULADDC_INIT \
+ asm( "ldr r0, %0 " :: "m" (s)); \
+ asm( "ldr r1, %0 " :: "m" (d)); \
+ asm( "ldr r2, %0 " :: "m" (c)); \
+ asm( "ldr r3, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ldr r4, [r0], #4 " ); \
+ asm( "mov r5, #0 " ); \
+ asm( "ldr r6, [r1] " ); \
+ asm( "umlal r2, r5, r3, r4 " ); \
+ asm( "adds r7, r6, r2 " ); \
+ asm( "adc r2, r5, #0 " ); \
+ asm( "str r7, [r1], #4 " );
+
+#define MULADDC_STOP \
+ asm( "str r2, %0 " : "=m" (c)); \
+ asm( "str r1, %0 " : "=m" (d)); \
+ asm( "str r0, %0 " : "=m" (s) :: \
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
+
+#endif /* Thumb */
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT \
+ asm( "ldq $1, %0 " :: "m" (s)); \
+ asm( "ldq $2, %0 " :: "m" (d)); \
+ asm( "ldq $3, %0 " :: "m" (c)); \
+ asm( "ldq $4, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "ldq $6, 0($1) " ); \
+ asm( "addq $1, 8, $1 " ); \
+ asm( "mulq $6, $4, $7 " ); \
+ asm( "umulh $6, $4, $6 " ); \
+ asm( "addq $7, $3, $7 " ); \
+ asm( "cmpult $7, $3, $3 " ); \
+ asm( "ldq $5, 0($2) " ); \
+ asm( "addq $7, $5, $7 " ); \
+ asm( "cmpult $7, $5, $5 " ); \
+ asm( "stq $7, 0($2) " ); \
+ asm( "addq $2, 8, $2 " ); \
+ asm( "addq $6, $3, $3 " ); \
+ asm( "addq $5, $3, $3 " );
+
+#define MULADDC_STOP \
+ asm( "stq $3, %0 " : "=m" (c)); \
+ asm( "stq $2, %0 " : "=m" (d)); \
+ asm( "stq $1, %0 " : "=m" (s) :: \
+ "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
+
+#endif /* Alpha */
+
+#if defined(__mips__)
+
+#define MULADDC_INIT \
+ asm( "lw $10, %0 " :: "m" (s)); \
+ asm( "lw $11, %0 " :: "m" (d)); \
+ asm( "lw $12, %0 " :: "m" (c)); \
+ asm( "lw $13, %0 " :: "m" (b));
+
+#define MULADDC_CORE \
+ asm( "lw $14, 0($10) " ); \
+ asm( "multu $13, $14 " ); \
+ asm( "addi $10, $10, 4 " ); \
+ asm( "mflo $14 " ); \
+ asm( "mfhi $9 " ); \
+ asm( "addu $14, $12, $14 " ); \
+ asm( "lw $15, 0($11) " ); \
+ asm( "sltu $12, $14, $12 " ); \
+ asm( "addu $15, $14, $15 " ); \
+ asm( "sltu $14, $15, $14 " ); \
+ asm( "addu $12, $12, $9 " ); \
+ asm( "sw $15, 0($11) " ); \
+ asm( "addu $12, $12, $14 " ); \
+ asm( "addi $11, $11, 4 " );
+
+#define MULADDC_STOP \
+ asm( "sw $12, %0 " : "=m" (c)); \
+ asm( "sw $11, %0 " : "=m" (d)); \
+ asm( "sw $10, %0 " : "=m" (s) :: \
+ "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT \
+ __asm mov esi, s \
+ __asm mov edi, d \
+ __asm mov ecx, c \
+ __asm mov ebx, b
+
+#define MULADDC_CORE \
+ __asm lodsd \
+ __asm mul ebx \
+ __asm add eax, ecx \
+ __asm adc edx, 0 \
+ __asm add eax, [edi] \
+ __asm adc edx, 0 \
+ __asm mov ecx, edx \
+ __asm stosd
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define EMIT __asm _emit
+
+#define MULADDC_HUIT \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x1F \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x16 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
+ EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
+ EMIT 0x0F EMIT 0x7E EMIT 0x0F \
+ EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
+ EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
+ EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x7E EMIT 0xC9
+
+#define MULADDC_STOP \
+ EMIT 0x0F EMIT 0x77 \
+ __asm mov c, ecx \
+ __asm mov d, edi \
+ __asm mov s, esi \
+
+#else
+
+#define MULADDC_STOP \
+ __asm mov c, ecx \
+ __asm mov d, edi \
+ __asm mov s, esi \
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* POLARSSL_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(POLARSSL_HAVE_LONGLONG)
+
+#define MULADDC_INIT \
+{ \
+ t_udbl r; \
+ t_uint r0, r1;
+
+#define MULADDC_CORE \
+ r = *(s++) * (t_udbl) b; \
+ r0 = r; \
+ r1 = r >> biL; \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#else
+#define MULADDC_INIT \
+{ \
+ t_uint s0, s1, b0, b1; \
+ t_uint r0, r1, rx, ry; \
+ b0 = ( b << biH ) >> biH; \
+ b1 = ( b >> biH );
+
+#define MULADDC_CORE \
+ s0 = ( *s << biH ) >> biH; \
+ s1 = ( *s >> biH ); s++; \
+ rx = s0 * b1; r0 = s0 * b0; \
+ ry = s1 * b0; r1 = s1 * b1; \
+ r1 += ( rx >> biH ); \
+ r1 += ( ry >> biH ); \
+ rx <<= biH; ry <<= biH; \
+ r0 += rx; r1 += (r0 < rx); \
+ r0 += ry; r1 += (r0 < ry); \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#endif /* C (generic) */
+#endif /* C (longlong) */
+
+#endif /* bn_mul.h */
diff --git a/polarssl/src/include/polarssl/camellia.h b/polarssl/src/include/polarssl/camellia.h
new file mode 100644
index 0000000..b2b1294
--- /dev/null
+++ b/polarssl/src/include/polarssl/camellia.h
@@ -0,0 +1,182 @@
+/**
+ * \file camellia.h
+ *
+ * \brief Camellia block cipher
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CAMELLIA_H
+#define POLARSSL_CAMELLIA_H
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define CAMELLIA_ENCRYPT 1
+#define CAMELLIA_DECRYPT 0
+
+#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */
+#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
+
+/**
+ * \brief CAMELLIA context structure
+ */
+typedef struct
+{
+ int nr; /*!< number of rounds */
+ uint32_t rk[68]; /*!< CAMELLIA round keys */
+}
+camellia_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief CAMELLIA key schedule (encryption)
+ *
+ * \param ctx CAMELLIA context to be initialized
+ * \param key encryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief CAMELLIA key schedule (decryption)
+ *
+ * \param ctx CAMELLIA context to be initialized
+ * \param key decryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief CAMELLIA-ECB block encryption/decryption
+ *
+ * \param ctx CAMELLIA context
+ * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if successful
+ */
+int camellia_crypt_ecb( camellia_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief CAMELLIA-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (16 bytes)
+ *
+ * \param ctx CAMELLIA context
+ * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int camellia_crypt_cbc( camellia_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief CAMELLIA-CFB128 buffer encryption/decryption
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT.
+ *
+ * \param ctx CAMELLIA context
+ * \param mode CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int camellia_crypt_cfb128( camellia_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/*
+ * \brief CAMELLIA-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * Note: Due to the nature of CTR you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * camellia_setkey_enc() for both CAMELLIA_ENCRYPT and CAMELLIA_DECRYPT.
+ *
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int camellia_crypt_ctr( camellia_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int camellia_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* camellia.h */
diff --git a/polarssl/src/include/polarssl/certs.h b/polarssl/src/include/polarssl/certs.h
new file mode 100644
index 0000000..5399e32
--- /dev/null
+++ b/polarssl/src/include/polarssl/certs.h
@@ -0,0 +1,47 @@
+/**
+ * \file certs.h
+ *
+ * \brief Sample certificates and DHM parameters for testing
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CERTS_H
+#define POLARSSL_CERTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char test_ca_crt[];
+extern const char test_ca_key[];
+extern const char test_ca_pwd[];
+extern const char test_srv_crt[];
+extern const char test_srv_key[];
+extern const char test_cli_crt[];
+extern const char test_cli_key[];
+extern const char test_dhm_params[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* certs.h */
diff --git a/polarssl/src/include/polarssl/cipher.h b/polarssl/src/include/polarssl/cipher.h
new file mode 100644
index 0000000..9605066
--- /dev/null
+++ b/polarssl/src/include/polarssl/cipher.h
@@ -0,0 +1,459 @@
+/**
+ * \file cipher.h
+ *
+ * \brief Generic cipher wrapper.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef POLARSSL_CIPHER_H
+#define POLARSSL_CIPHER_H
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */
+#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */
+#define POLARSSL_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */
+#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */
+
+typedef enum {
+ POLARSSL_CIPHER_ID_NONE = 0,
+ POLARSSL_CIPHER_ID_NULL,
+ POLARSSL_CIPHER_ID_AES,
+ POLARSSL_CIPHER_ID_DES,
+ POLARSSL_CIPHER_ID_3DES,
+ POLARSSL_CIPHER_ID_CAMELLIA,
+} cipher_id_t;
+
+typedef enum {
+ POLARSSL_CIPHER_NONE = 0,
+ POLARSSL_CIPHER_NULL,
+ POLARSSL_CIPHER_AES_128_CBC,
+ POLARSSL_CIPHER_AES_192_CBC,
+ POLARSSL_CIPHER_AES_256_CBC,
+ POLARSSL_CIPHER_AES_128_CFB128,
+ POLARSSL_CIPHER_AES_192_CFB128,
+ POLARSSL_CIPHER_AES_256_CFB128,
+ POLARSSL_CIPHER_AES_128_CTR,
+ POLARSSL_CIPHER_AES_192_CTR,
+ POLARSSL_CIPHER_AES_256_CTR,
+ POLARSSL_CIPHER_CAMELLIA_128_CBC,
+ POLARSSL_CIPHER_CAMELLIA_192_CBC,
+ POLARSSL_CIPHER_CAMELLIA_256_CBC,
+ POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_128_CTR,
+ POLARSSL_CIPHER_CAMELLIA_192_CTR,
+ POLARSSL_CIPHER_CAMELLIA_256_CTR,
+ POLARSSL_CIPHER_DES_CBC,
+ POLARSSL_CIPHER_DES_EDE_CBC,
+ POLARSSL_CIPHER_DES_EDE3_CBC
+} cipher_type_t;
+
+typedef enum {
+ POLARSSL_MODE_NONE = 0,
+ POLARSSL_MODE_NULL,
+ POLARSSL_MODE_CBC,
+ POLARSSL_MODE_CFB128,
+ POLARSSL_MODE_OFB,
+ POLARSSL_MODE_CTR,
+} cipher_mode_t;
+
+typedef enum {
+ POLARSSL_OPERATION_NONE = -1,
+ POLARSSL_DECRYPT = 0,
+ POLARSSL_ENCRYPT,
+} operation_t;
+
+enum {
+ /** Undefined key length */
+ POLARSSL_KEY_LENGTH_NONE = 0,
+ /** Key length, in bits (including parity), for DES keys */
+ POLARSSL_KEY_LENGTH_DES = 64,
+ /** Key length, in bits (including parity), for DES in two key EDE */
+ POLARSSL_KEY_LENGTH_DES_EDE = 128,
+ /** Key length, in bits (including parity), for DES in three-key EDE */
+ POLARSSL_KEY_LENGTH_DES_EDE3 = 192,
+ /** Maximum length of any IV, in bytes */
+ POLARSSL_MAX_IV_LENGTH = 16,
+};
+
+/**
+ * Base cipher information. The non-mode specific functions and values.
+ */
+typedef struct {
+
+ /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */
+ cipher_id_t cipher;
+
+ /** Encrypt using CBC */
+ int (*cbc_func)( void *ctx, operation_t mode, size_t length, unsigned char *iv,
+ const unsigned char *input, unsigned char *output );
+
+ /** Encrypt using CFB128 */
+ int (*cfb128_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off,
+ unsigned char *iv, const unsigned char *input, unsigned char *output );
+
+ /** Encrypt using CTR */
+ int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter,
+ unsigned char *stream_block, const unsigned char *input, unsigned char *output );
+
+ /** Set key for encryption purposes */
+ int (*setkey_enc_func)( void *ctx, const unsigned char *key, unsigned int key_length);
+
+ /** Set key for decryption purposes */
+ int (*setkey_dec_func)( void *ctx, const unsigned char *key, unsigned int key_length);
+
+ /** Allocate a new context */
+ void * (*ctx_alloc_func)( void );
+
+ /** Free the given context */
+ void (*ctx_free_func)( void *ctx );
+
+} cipher_base_t;
+
+/**
+ * Cipher information. Allows cipher functions to be called in a generic way.
+ */
+typedef struct {
+ /** Full cipher identifier (e.g. POLARSSL_CIPHER_AES_256_CBC) */
+ cipher_type_t type;
+
+ /** Cipher mode (e.g. POLARSSL_MODE_CBC) */
+ cipher_mode_t mode;
+
+ /** Cipher key length, in bits (default length for variable sized ciphers)
+ * (Includes parity bits for ciphers like DES) */
+ unsigned int key_length;
+
+ /** Name of the cipher */
+ const char * name;
+
+ /** IV size, in bytes */
+ unsigned int iv_size;
+
+ /** block size, in bytes */
+ unsigned int block_size;
+
+ /** Base cipher information and functions */
+ const cipher_base_t *base;
+
+} cipher_info_t;
+
+/**
+ * Generic cipher context.
+ */
+typedef struct {
+ /** Information about the associated cipher */
+ const cipher_info_t *cipher_info;
+
+ /** Key length to use */
+ int key_length;
+
+ /** Operation that the context's key has been initialised for */
+ operation_t operation;
+
+ /** Buffer for data that hasn't been encrypted yet */
+ unsigned char unprocessed_data[POLARSSL_MAX_IV_LENGTH];
+
+ /** Number of bytes that still need processing */
+ size_t unprocessed_len;
+
+ /** Current IV or NONCE_COUNTER for CTR-mode */
+ unsigned char iv[POLARSSL_MAX_IV_LENGTH];
+
+ /** Cipher-specific context */
+ void *cipher_ctx;
+} cipher_context_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Returns the list of ciphers supported by the generic cipher module.
+ *
+ * \return a statically allocated array of ciphers, the last entry
+ * is 0.
+ */
+const int *cipher_list( void );
+
+/**
+ * \brief Returns the cipher information structure associated
+ * with the given cipher name.
+ *
+ * \param cipher_name Name of the cipher to search for.
+ *
+ * \return the cipher information structure associated with the
+ * given cipher_name, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_string( const char *cipher_name );
+
+/**
+ * \brief Returns the cipher information structure associated
+ * with the given cipher type.
+ *
+ * \param cipher_type Type of the cipher to search for.
+ *
+ * \return the cipher information structure associated with the
+ * given cipher_type, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type );
+
+/**
+ * \brief Initialises and fills the cipher context structure with
+ * the appropriate values.
+ *
+ * \param ctx context to initialise. May not be NULL.
+ * \param cipher_info cipher to use.
+ *
+ * \return \c 0 on success,
+ * \c POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
+ * \c POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ * cipher-specific context failed.
+ */
+int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info );
+
+/**
+ * \brief Free the cipher-specific context of ctx. Freeing ctx
+ * itself remains the responsibility of the caller.
+ *
+ * \param ctx Free the cipher-specific context
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ * parameter verification fails.
+ */
+int cipher_free_ctx( cipher_context_t *ctx );
+
+/**
+ * \brief Returns the block size of the given cipher.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return size of the cipher's blocks, or 0 if ctx has not been
+ * initialised.
+ */
+static inline unsigned int cipher_get_block_size( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->block_size;
+}
+
+/**
+ * \brief Returns the mode of operation for the cipher.
+ * (e.g. POLARSSL_MODE_CBC)
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return mode of operation, or POLARSSL_MODE_NONE if ctx
+ * has not been initialised.
+ */
+static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return POLARSSL_MODE_NONE;
+
+ return ctx->cipher_info->mode;
+}
+
+/**
+ * \brief Returns the size of the cipher's IV.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return size of the cipher's IV, or 0 if ctx has not been
+ * initialised.
+ */
+static inline int cipher_get_iv_size( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->iv_size;
+}
+
+/**
+ * \brief Returns the type of the given cipher.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return type of the cipher, or POLARSSL_CIPHER_NONE if ctx has
+ * not been initialised.
+ */
+static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->type;
+}
+
+/**
+ * \brief Returns the name of the given cipher, as a string.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return name of the cipher, or NULL if ctx was not initialised.
+ */
+static inline const char *cipher_get_name( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->name;
+}
+
+/**
+ * \brief Returns the key length of the cipher.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return cipher's key length, in bits, or
+ * POLARSSL_KEY_LENGTH_NONE if ctx has not been
+ * initialised.
+ */
+static inline int cipher_get_key_size ( const cipher_context_t *ctx )
+{
+ if( NULL == ctx )
+ return POLARSSL_KEY_LENGTH_NONE;
+
+ return ctx->key_length;
+}
+
+/**
+ * \brief Returns the operation of the given cipher.
+ *
+ * \param ctx cipher's context. Must have been initialised.
+ *
+ * \return operation (POLARSSL_ENCRYPT or POLARSSL_DECRYPT),
+ * or POLARSSL_OPERATION_NONE if ctx has not been
+ * initialised.
+ */
+static inline operation_t cipher_get_operation( const cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return POLARSSL_OPERATION_NONE;
+
+ return ctx->operation;
+}
+
+/**
+ * \brief Set the key to use with the given context.
+ *
+ * \param ctx generic cipher context. May not be NULL. Must have been
+ * initialised using cipher_context_from_type or
+ * cipher_context_from_string.
+ * \param key The key to use.
+ * \param key_length key length to use, in bits.
+ * \param operation Operation that the key will be used for, either
+ * POLARSSL_ENCRYPT or POLARSSL_DECRYPT.
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ * parameter verification fails or a cipher specific
+ * error code.
+ */
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, int key_length,
+ const operation_t operation );
+
+/**
+ * \brief Reset the given context, setting the IV to iv
+ *
+ * \param ctx generic cipher context
+ * \param iv IV to use or NONCE_COUNTER in the case of a CTR-mode cipher
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
+ * if parameter verification fails.
+ */
+int cipher_reset( cipher_context_t *ctx, const unsigned char *iv );
+
+/**
+ * \brief Generic cipher update function. Encrypts/decrypts
+ * using the given cipher context. Writes as many block
+ * size'd blocks of data as possible to output. Any data
+ * that cannot be written immediately will either be added
+ * to the next block, or flushed when cipher_final is
+ * called.
+ *
+ * \param ctx generic cipher context
+ * \param input buffer holding the input data
+ * \param ilen length of the input data
+ * \param output buffer for the output data. Should be able to hold at
+ * least ilen + block_size. Cannot be the same buffer as
+ * input!
+ * \param olen length of the output data, will be filled with the
+ * actual number of bytes written.
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ * parameter verification fails,
+ * POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an
+ * unsupported mode for a cipher or a cipher specific
+ * error code.
+ */
+int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen );
+
+/**
+ * \brief Generic cipher finalisation function. If data still
+ * needs to be flushed from an incomplete block, data
+ * contained within it will be padded with the size of
+ * the last block, and written to the output buffer.
+ *
+ * \param ctx Generic cipher context
+ * \param output buffer to write data to. Needs block_size data available.
+ * \param olen length of the data written to the output buffer.
+ *
+ * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
+ * parameter verification fails,
+ * POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
+ * expected a full block but was not provided one,
+ * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding
+ * while decrypting or a cipher specific error code.
+ */
+int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen);
+
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int cipher_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_H */
diff --git a/polarssl/src/include/polarssl/cipher_wrap.h b/polarssl/src/include/polarssl/cipher_wrap.h
new file mode 100644
index 0000000..e81c11d
--- /dev/null
+++ b/polarssl/src/include/polarssl/cipher_wrap.h
@@ -0,0 +1,95 @@
+/**
+ * \file cipher_wrap.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CIPHER_WRAP_H
+#define POLARSSL_CIPHER_WRAP_H
+
+#include "config.h"
+#include "cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(POLARSSL_AES_C)
+
+extern const cipher_info_t aes_128_cbc_info;
+extern const cipher_info_t aes_192_cbc_info;
+extern const cipher_info_t aes_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+extern const cipher_info_t aes_128_cfb128_info;
+extern const cipher_info_t aes_192_cfb128_info;
+extern const cipher_info_t aes_256_cfb128_info;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+extern const cipher_info_t aes_128_ctr_info;
+extern const cipher_info_t aes_192_ctr_info;
+extern const cipher_info_t aes_256_ctr_info;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif /* defined(POLARSSL_AES_C) */
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+extern const cipher_info_t camellia_128_cbc_info;
+extern const cipher_info_t camellia_192_cbc_info;
+extern const cipher_info_t camellia_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+extern const cipher_info_t camellia_128_cfb128_info;
+extern const cipher_info_t camellia_192_cfb128_info;
+extern const cipher_info_t camellia_256_cfb128_info;
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+extern const cipher_info_t camellia_128_ctr_info;
+extern const cipher_info_t camellia_192_ctr_info;
+extern const cipher_info_t camellia_256_ctr_info;
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif /* defined(POLARSSL_CAMELLIA_C) */
+
+#if defined(POLARSSL_DES_C)
+
+extern const cipher_info_t des_cbc_info;
+extern const cipher_info_t des_ede_cbc_info;
+extern const cipher_info_t des_ede3_cbc_info;
+
+#endif /* defined(POLARSSL_DES_C) */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+extern const cipher_info_t null_cipher_info;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_CIPHER_WRAP_H */
diff --git a/polarssl/src/include/polarssl/config.h b/polarssl/src/include/polarssl/config.h
new file mode 100644
index 0000000..4e27446
--- /dev/null
+++ b/polarssl/src/include/polarssl/config.h
@@ -0,0 +1,744 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_HAVE_INT8
+ *
+ * The system uses 8-bit wide native integers.
+ *
+ * Uncomment if native integers are 8-bit wide.
+#define POLARSSL_HAVE_INT8
+ */
+
+/**
+ * \def POLARSSL_HAVE_INT16
+ *
+ * The system uses 16-bit wide native integers.
+ *
+ * Uncomment if native integers are 16-bit wide.
+#define POLARSSL_HAVE_INT16
+ */
+
+/**
+ * \def POLARSSL_HAVE_LONGLONG
+ *
+ * The compiler supports the use of long long.
+ *
+ * Uncomment if the compiler supports long long.
+#define POLARSSL_HAVE_LONGLONG
+ */
+
+/**
+ * \def POLARSSL_HAVE_ASM
+ *
+ * The compiler has support for asm()
+ *
+ * Uncomment to enable the use of assembly code.
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ * library/timing.c
+ * library/padlock.c
+ * include/polarssl/bn_mul.h
+ *
+ */
+#define POLARSSL_HAVE_ASM
+
+/**
+ * \def POLARSSL_HAVE_SSE2
+ *
+ * CPI supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ *
+#define POLARSSL_HAVE_SSE2
+ */
+/* \} name */
+
+/**
+ * \name SECTION: PolarSSL feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+#define POLARSSL_AES_ROM_TABLES
+ */
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+//#define POLARSSL_CIPHER_MODE_CFB
+
+/**
+ * \def POLARSSL_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+//#define POLARSSL_CIPHER_MODE_CTR
+
+/**
+ * \def POLARSSL_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable
+ * the following ciphersuites:
+ * SSL_RSA_NULL_MD5
+ * SSL_RSA_NULL_SHA
+ * SSL_RSA_NULL_SHA256
+ *
+ * Uncomment this macro to enable the NULL cipher and ciphersuites
+#define POLARSSL_CIPHER_NULL_CIPHER
+ */
+
+/**
+ * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES
+ *
+ * Enable weak ciphersuites in SSL / TLS (like RC4_40)
+ * Warning: Only do so when you know what you are doing. This allows for
+ * channels without virtually no security at all!
+ *
+ * This enables the following ciphersuites:
+ * SSL_RSA_DES_SHA
+ * SSL_EDH_RSA_DES_SHA
+ *
+ * Uncomment this macro to enable weak ciphersuites
+#define POLARSSL_ENABLE_WEAK_CIPHERSUITES
+ */
+
+/**
+ * \def POLARSSL_GENPRIME
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * Enable the RSA prime-number generation code.
+ */
+//#define POLARSSL_GENPRIME
+
+/**
+ * \def POLARSSL_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+//#define POLARSSL_FS_IO
+
+/**
+ * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES
+ */
+
+/**
+ * \def POLARSSL_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+#define POLARSSL_NO_PLATFORM_ENTROPY
+ */
+
+/**
+ * \def POLARSSL_PKCS1_V21
+ *
+ * Requires: POLARSSL_MD_C, POLARSSL_RSA_C
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+//#define POLARSSL_PKCS1_V21
+
+/**
+ * \def POLARSSL_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+#define POLARSSL_RSA_NO_CRT
+ */
+
+/**
+ * \def POLARSSL_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+//#define POLARSSL_SELF_TEST
+
+/**
+ * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * Uncomment to prevent an error.
+ *
+#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ */
+/* \} name */
+
+/**
+ * \name SECTION: PolarSSL modules
+ *
+ * This section enables or disables entire modules in PolarSSL
+ * \{
+ */
+
+/**
+ * \def POLARSSL_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module: library/aes.c
+ * Caller: library/ssl_tls.c
+ * library/pem.c
+ * library/ctr_drbg.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_AES_128_SHA
+ * SSL_RSA_AES_256_SHA
+ * SSL_EDH_RSA_AES_256_SHA
+ */
+#define POLARSSL_AES_C
+
+/**
+ * \def POLARSSL_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module: library/arc4.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_RC4_128_MD5
+ * SSL_RSA_RC4_128_SHA
+ */
+//#define POLARSSL_ARC4_C
+
+/**
+ * \def POLARSSL_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module: library/asn1.c
+ * Caller: library/x509parse.c
+ */
+#define POLARSSL_ASN1_PARSE_C
+
+/**
+ * \def POLARSSL_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module: library/asn1write.c
+ */
+#define POLARSSL_ASN1_WRITE_C
+
+/**
+ * \def POLARSSL_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module: library/base64.c
+ * Caller: library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+//#define POLARSSL_BASE64_C
+
+/**
+ * \def POLARSSL_BIGNUM_C
+ *
+ * Enable the multo-precision integer library.
+ *
+ * Module: library/bignum.c
+ * Caller: library/dhm.c
+ * library/rsa.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+#define POLARSSL_BIGNUM_C
+
+/**
+ * \def POLARSSL_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module: library/camellia.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enabled the following cipher suites:
+ * SSL_RSA_CAMELLIA_128_SHA
+ * SSL_RSA_CAMELLIA_256_SHA
+ * SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+//#define POLARSSL_CAMELLIA_C
+
+/**
+ * \def POLARSSL_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module: library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+//#define POLARSSL_CERTS_C
+
+/**
+ * \def POLARSSL_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module: library/cipher.c
+ * Caller:
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+//#define POLARSSL_CIPHER_C
+
+/**
+ * \def POLARSSL_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator
+ *
+ * Module: library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: POLARSSL_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+#define POLARSSL_CTR_DRBG_C
+
+/**
+ * \def POLARSSL_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module: library/debug.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+//#define POLARSSL_DEBUG_C
+
+/**
+ * \def POLARSSL_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module: library/des.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_RSA_DES_168_SHA
+ * SSL_EDH_RSA_DES_168_SHA
+ */
+//#define POLARSSL_DES_C
+
+/**
+ * \def POLARSSL_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle key exchange.
+ *
+ * Module: library/dhm.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This module enables the following ciphersuites:
+ * SSL_EDH_RSA_DES_168_SHA
+ * SSL_EDH_RSA_AES_256_SHA
+ * SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+//#define POLARSSL_DHM_C
+
+/**
+ * \def POLARSSL_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module: library/entropy.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SHA4_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define POLARSSL_ENTROPY_C
+
+/**
+ * \def POLARSSL_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module: library/error.c
+ * Caller:
+ *
+ * This module enables err_strerror().
+ */
+#define POLARSSL_ERROR_C
+
+/**
+ * \def POLARSSL_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES
+ *
+ * Module: library/gcm.c
+ *
+ * Requires: POLARSSL_AES_C
+ */
+//#define POLARSSL_GCM_C
+
+/**
+ * \def POLARSSL_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Module: library/havege.c
+ * Caller:
+ *
+ * Requires: POLARSSL_TIMING_C
+ *
+ * This module enables the HAVEGE random number generator.
+ */
+//#define POLARSSL_HAVEGE_C
+
+/**
+ * \def POLARSSL_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module: library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+//#define POLARSSL_MD_C
+
+/**
+ * \def POLARSSL_MD2_C
+ *
+ * Enable the MD2 hash algorithm
+ *
+ * Module: library/md2.c
+ * Caller: library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+#define POLARSSL_MD2_C
+ */
+
+/**
+ * \def POLARSSL_MD4_C
+ *
+ * Enable the MD4 hash algorithm
+ *
+ * Module: library/md4.c
+ * Caller: library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+#define POLARSSL_MD4_C
+ */
+
+/**
+ * \def POLARSSL_MD5_C
+ *
+ * Enable the MD5 hash algorithm
+ *
+ * Module: library/md5.c
+ * Caller: library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ */
+#define POLARSSL_MD5_C
+
+/**
+ * \def POLARSSL_NET_C
+ *
+ * Enable the TCP/IP networking routines.
+ *
+ * Module: library/net.c
+ * Caller:
+ *
+ * This module provides TCP/IP networking routines.
+ */
+//#define POLARSSL_NET_C
+
+/**
+ * \def POLARSSL_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module: library/padlock.c
+ * Caller: library/aes.c
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+//#define POLARSSL_PADLOCK_C
+
+/**
+ * \def POLARSSL_PEM_C
+ *
+ * Enable PEM decoding
+ *
+ * Module: library/pem.c
+ * Caller: library/x509parse.c
+ *
+ * Requires: POLARSSL_BASE64_C
+ *
+ * This modules adds support for decoding PEM files.
+ */
+//#define POLARSSL_PEM_C
+
+/**
+ * \def POLARSSL_PKCS11_C
+ *
+ * Enable support for PKCS#11 smartcard support.
+ *
+ * Module: library/ssl_srv.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+#define POLARSSL_PKCS11_C
+ */
+
+/**
+ * \def POLARSSL_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module: library/rsa.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509.c
+ *
+ * Requires: POLARSSL_BIGNUM_C
+ *
+ * This module is required for SSL/TLS and MD5-signed certificates.
+ */
+#define POLARSSL_RSA_C
+
+/**
+ * \def POLARSSL_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module: library/sha1.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509parse.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+/**
+ * \def POLARSSL_SHA2_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module: library/sha2.c
+ * Caller: library/md_wrap.c
+ * library/x509parse.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ */
+#define POLARSSL_SHA2_C
+
+/**
+ * \def POLARSSL_SHA4_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module: library/sha4.c
+ * Caller: library/md_wrap.c
+ * library/x509parse.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define POLARSSL_SHA4_C
+
+/**
+ * \def POLARSSL_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module: library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define POLARSSL_SSL_CLI_C
+
+/*
+ * \def POLARSSL_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module: library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: POLARSSL_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+//#define POLARSSL_SSL_SRV_C
+
+/**
+ * \def POLARSSL_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module: library/ssl_tls.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/**
+ * \def POLARSSL_TIMING_C
+ *
+ * Enable the portable timing interface.
+ *
+ * Module: library/timing.c
+ * Caller: library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+//#define POLARSSL_TIMING_C
+
+/**
+ * \def POLARSSL_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module: library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define POLARSSL_VERSION_C
+
+/**
+ * \def POLARSSL_X509_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module: library/x509parse.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define POLARSSL_X509_PARSE_C
+
+/**
+ * \def POLARSSL_X509_WRITE_C
+ *
+ * Enable X.509 buffer writing.
+ *
+ * Module: library/x509write.c
+ *
+ * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C
+ *
+ * This module is required for X.509 certificate request writing.
+ */
+//#define POLARSSL_X509_WRITE_C
+
+/**
+ * \def POLARSSL_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module: library/xtea.c
+ * Caller:
+ */
+//#define POLARSSL_XTEA_C
+/* \} name */
+
+#endif /* config.h */
diff --git a/polarssl/src/include/polarssl/ctr_drbg.h b/polarssl/src/include/polarssl/ctr_drbg.h
new file mode 100644
index 0000000..83861a9
--- /dev/null
+++ b/polarssl/src/include/polarssl/ctr_drbg.h
@@ -0,0 +1,228 @@
+/**
+ * \file ctr_drbg.h
+ *
+ * \brief CTR_DRBG based on AES-256 (NIST SP 800-90)
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CTR_DRBG_H
+#define POLARSSL_CTR_DRBG_H
+
+#include <string.h>
+
+#include "aes.h"
+
+#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */
+#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */
+#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */
+#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */
+
+#define CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */
+#define CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */
+#define CTR_DRBG_KEYBITS ( CTR_DRBG_KEYSIZE * 8 )
+#define CTR_DRBG_SEEDLEN ( CTR_DRBG_KEYSIZE + CTR_DRBG_BLOCKSIZE )
+ /**< The seed length (counter + AES key) */
+#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default */
+#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+
+#define CTR_DRBG_PR_OFF 0 /**< No prediction resistance */
+#define CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief CTR_DRBG context structure
+ */
+typedef struct
+{
+ unsigned char counter[16]; /*!< counter (V) */
+ int reseed_counter; /*!< reseed counter */
+ int prediction_resistance; /*!< enable prediction resistance (Automatic
+ reseed before every random generation) */
+ size_t entropy_len; /*!< amount of entropy grabbed on each (re)seed */
+ int reseed_interval; /*!< reseed interval */
+
+ aes_context aes_ctx; /*!< AES context */
+
+ /*
+ * Callbacks (Entropy)
+ */
+ int (*f_entropy)(void *, unsigned char *, size_t);
+
+ void *p_entropy; /*!< context for the entropy function */
+}
+ctr_drbg_context;
+
+/**
+ * \brief CTR_DRBG initialization
+ *
+ * Note: Personalization data can be provided in addition to the more generic
+ * entropy source to make this instantiation as unique as possible.
+ *
+ * \param ctx CTR_DRBG context to be initialized
+ * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer
+ * length)
+ * \param p_entropy Entropy context
+ * \param custom Personalization data (Device specific identifiers)
+ * (Can be NULL)
+ * \param len Length of personalization data
+ *
+ * \return 0 if successful, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_init( ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len );
+
+/**
+ * \brief Enable / disable prediction resistance (Default: Off)
+ *
+ * Note: If enabled, entropy is used for ctx->entropy_len before each call!
+ * Only use this if you have ample supply of good entropy!
+ *
+ * \param ctx CTR_DRBG context
+ * \param resistance CTR_DRBG_PR_ON or CTR_DRBG_PR_OFF
+ */
+void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx,
+ int resistance );
+
+/**
+ * \brief Set the amount of entropy grabbed on each (re)seed
+ * (Default: CTR_DRBG_ENTROPY_LEN)
+ *
+ * \param ctx CTR_DRBG context
+ * \param len Amount of entropy to grab
+ */
+void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx,
+ size_t len );
+
+/**
+ * \brief Set the reseed interval
+ * (Default: CTR_DRBG_RESEED_INTERVAL)
+ *
+ * \param ctx CTR_DRBG context
+ * \param interval Reseed interval
+ */
+void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx,
+ int interval );
+
+/**
+ * \brief CTR_DRBG reseeding (extracts data from entropy source)
+ *
+ * \param ctx CTR_DRBG context
+ * \param additional Additional data to add to state (Can be NULL)
+ * \param len Length of additional data
+ *
+ * \return 0 if successful, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_reseed( ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t len );
+
+/**
+ * \brief CTR_DRBG update state
+ *
+ * \param ctx CTR_DRBG context
+ * \param additional Additional data to update state with
+ * \param add_len Length of additional data
+ */
+void ctr_drbg_update( ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief CTR_DRBG generate random with additional update input
+ *
+ * Note: Automatically reseeds if reseed_counter is reached.
+ *
+ * \param p_rng CTR_DRBG context
+ * \param output Buffer to fill
+ * \param output_len Length of the buffer
+ * \param additional Additional data to update with (Can be NULL)
+ * \param add_len Length of additional data
+ *
+ * \return 0 if successful, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or
+ * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
+ */
+int ctr_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t output_len,
+ const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief CTR_DRBG generate random
+ *
+ * Note: Automatically reseeds if reseed_counter is reached.
+ *
+ * \param p_rng CTR_DRBG context
+ * \param output Buffer to fill
+ * \param output_len Length of the buffer
+ *
+ * \return 0 if successful, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or
+ * POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG
+ */
+int ctr_drbg_random( void *p_rng,
+ unsigned char *output, size_t output_len );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief Write a seed file
+ *
+ * \param path Name of the file
+ *
+ * \return 0 if successful, 1 on file error, or
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path );
+
+/**
+ * \brief Read and update a seed file. Seed is added to this
+ * instance
+ *
+ * \param path Name of the file
+ *
+ * \return 0 if successful, 1 on file error,
+ * POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ * POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG
+ */
+int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path );
+#endif
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int ctr_drbg_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ctr_drbg.h */
diff --git a/polarssl/src/include/polarssl/debug.h b/polarssl/src/include/polarssl/debug.h
new file mode 100644
index 0000000..511e926
--- /dev/null
+++ b/polarssl/src/include/polarssl/debug.h
@@ -0,0 +1,89 @@
+/**
+ * \file debug.h
+ *
+ * \brief Debug functions
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DEBUG_H
+#define POLARSSL_DEBUG_H
+
+#include "config.h"
+#include "ssl.h"
+
+#if defined(POLARSSL_DEBUG_C)
+
+#define SSL_DEBUG_MSG( level, args ) \
+ debug_print_msg( ssl, level, __FILE__, __LINE__, debug_fmt args );
+
+#define SSL_DEBUG_RET( level, text, ret ) \
+ debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret );
+
+#define SSL_DEBUG_BUF( level, text, buf, len ) \
+ debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len );
+
+#define SSL_DEBUG_MPI( level, text, X ) \
+ debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X );
+
+#define SSL_DEBUG_CRT( level, text, crt ) \
+ debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt );
+
+#else
+
+#define SSL_DEBUG_MSG( level, args ) do { } while( 0 )
+#define SSL_DEBUG_RET( level, text, ret ) do { } while( 0 )
+#define SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 )
+#define SSL_DEBUG_MPI( level, text, X ) do { } while( 0 )
+#define SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 )
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *debug_fmt( const char *format, ... );
+
+void debug_print_msg( const ssl_context *ssl, int level,
+ const char *file, int line, const char *text );
+
+void debug_print_ret( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, int ret );
+
+void debug_print_buf( const ssl_context *ssl, int level,
+ const char *file, int line, const char *text,
+ unsigned char *buf, size_t len );
+
+void debug_print_mpi( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const mpi *X );
+
+void debug_print_crt( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const x509_cert *crt );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* debug.h */
diff --git a/polarssl/src/include/polarssl/des.h b/polarssl/src/include/polarssl/des.h
new file mode 100644
index 0000000..653e68b
--- /dev/null
+++ b/polarssl/src/include/polarssl/des.h
@@ -0,0 +1,227 @@
+/**
+ * \file des.h
+ *
+ * \brief DES block cipher
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DES_H
+#define POLARSSL_DES_H
+
+#include <string.h>
+
+#define DES_ENCRYPT 1
+#define DES_DECRYPT 0
+
+#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */
+
+#define DES_KEY_SIZE 8
+
+/**
+ * \brief DES context structure
+ */
+typedef struct
+{
+ int mode; /*!< encrypt/decrypt */
+ unsigned long sk[32]; /*!< DES subkeys */
+}
+des_context;
+
+/**
+ * \brief Triple-DES context structure
+ */
+typedef struct
+{
+ int mode; /*!< encrypt/decrypt */
+ unsigned long sk[96]; /*!< 3DES subkeys */
+}
+des3_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Set key parity on the given key to odd.
+ *
+ * DES keys are 56 bits long, but each byte is padded with
+ * a parity bit to allow verification.
+ *
+ * \param key 8-byte secret key
+ */
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief Check that key parity on the given key is odd.
+ *
+ * DES keys are 56 bits long, but each byte is padded with
+ * a parity bit to allow verification.
+ *
+ * \param key 8-byte secret key
+ *
+ * \return 0 is parity was ok, 1 if parity was not correct.
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief Check that key is not a weak or semi-weak DES key
+ *
+ * \param key 8-byte secret key
+ *
+ * \return 0 if no weak key was found, 1 if a weak key was identified.
+ */
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief DES key schedule (56-bit, encryption)
+ *
+ * \param ctx DES context to be initialized
+ * \param key 8-byte secret key
+ *
+ * \return 0
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief DES key schedule (56-bit, decryption)
+ *
+ * \param ctx DES context to be initialized
+ * \param key 8-byte secret key
+ *
+ * \return 0
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief Triple-DES key schedule (112-bit, encryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 16-byte secret key
+ *
+ * \return 0
+ */
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+
+/**
+ * \brief Triple-DES key schedule (112-bit, decryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 16-byte secret key
+ *
+ * \return 0
+ */
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+
+/**
+ * \brief Triple-DES key schedule (168-bit, encryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 24-byte secret key
+ *
+ * \return 0
+ */
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+
+/**
+ * \brief Triple-DES key schedule (168-bit, decryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 24-byte secret key
+ *
+ * \return 0
+ */
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+
+/**
+ * \brief DES-ECB block encryption/decryption
+ *
+ * \param ctx DES context
+ * \param input 64-bit input block
+ * \param output 64-bit output block
+ *
+ * \return 0 if successful
+ */
+int des_crypt_ecb( des_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] );
+
+/**
+ * \brief DES-CBC buffer encryption/decryption
+ *
+ * \param ctx DES context
+ * \param mode DES_ENCRYPT or DES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ */
+int des_crypt_cbc( des_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief 3DES-ECB block encryption/decryption
+ *
+ * \param ctx 3DES context
+ * \param input 64-bit input block
+ * \param output 64-bit output block
+ *
+ * \return 0 if successful
+ */
+int des3_crypt_ecb( des3_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] );
+
+/**
+ * \brief 3DES-CBC buffer encryption/decryption
+ *
+ * \param ctx 3DES context
+ * \param mode DES_ENCRYPT or DES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or POLARSSL_ERR_DES_INVALID_INPUT_LENGTH
+ */
+int des3_crypt_cbc( des3_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output );
+
+/*
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int des_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* des.h */
diff --git a/polarssl/src/include/polarssl/dhm.h b/polarssl/src/include/polarssl/dhm.h
new file mode 100644
index 0000000..0c8dd55
--- /dev/null
+++ b/polarssl/src/include/polarssl/dhm.h
@@ -0,0 +1,153 @@
+/**
+ * \file dhm.h
+ *
+ * \brief Diffie-Hellman-Merkle key exchange
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_DHM_H
+#define POLARSSL_DHM_H
+
+#include "bignum.h"
+
+/*
+ * DHM Error codes
+ */
+#define POLARSSL_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */
+#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */
+#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */
+#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */
+#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */
+
+/**
+ * \brief DHM context structure
+ */
+typedef struct
+{
+ size_t len; /*!< size(P) in chars */
+ mpi P; /*!< prime modulus */
+ mpi G; /*!< generator */
+ mpi X; /*!< secret value */
+ mpi GX; /*!< self = G^X mod P */
+ mpi GY; /*!< peer = G^Y mod P */
+ mpi K; /*!< key = GY^X mod P */
+ mpi RP; /*!< cached R^2 mod P */
+}
+dhm_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Parse the ServerKeyExchange parameters
+ *
+ * \param ctx DHM context
+ * \param p &(start of input buffer)
+ * \param end end of buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_read_params( dhm_context *ctx,
+ unsigned char **p,
+ const unsigned char *end );
+
+/**
+ * \brief Setup and write the ServerKeyExchange parameters
+ *
+ * \param ctx DHM context
+ * \param x_size private value size in bytes
+ * \param output destination buffer
+ * \param olen number of chars written
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \note This function assumes that ctx->P and ctx->G
+ * have already been properly set (for example
+ * using mpi_read_string or mpi_read_binary).
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_make_params( dhm_context *ctx, int x_size,
+ unsigned char *output, size_t *olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Import the peer's public value G^Y
+ *
+ * \param ctx DHM context
+ * \param input input buffer
+ * \param ilen size of buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_read_public( dhm_context *ctx,
+ const unsigned char *input, size_t ilen );
+
+/**
+ * \brief Create own private value X and export G^X
+ *
+ * \param ctx DHM context
+ * \param x_size private value size in bytes
+ * \param output destination buffer
+ * \param olen must be equal to ctx->P.len
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_make_public( dhm_context *ctx, int x_size,
+ unsigned char *output, size_t olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Derive and export the shared secret (G^Y)^X mod P
+ *
+ * \param ctx DHM context
+ * \param output destination buffer
+ * \param olen number of chars written
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ */
+int dhm_calc_secret( dhm_context *ctx,
+ unsigned char *output, size_t *olen );
+
+/*
+ * \brief Free the components of a DHM key
+ */
+void dhm_free( dhm_context *ctx );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int dhm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/polarssl/src/include/polarssl/entropy.h b/polarssl/src/include/polarssl/entropy.h
new file mode 100644
index 0000000..53bce41
--- /dev/null
+++ b/polarssl/src/include/polarssl/entropy.h
@@ -0,0 +1,150 @@
+/**
+ * \file entropy.h
+ *
+ * \brief Entropy accumulator implementation
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ENTROPY_H
+#define POLARSSL_ENTROPY_H
+
+#include <string.h>
+
+#include "config.h"
+
+#include "sha4.h"
+#if defined(POLARSSL_HAVEGE_C)
+#include "havege.h"
+#endif
+
+#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */
+#define POLARSSL_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */
+#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */
+
+#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
+#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
+#define ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */
+
+#define ENTROPY_SOURCE_MANUAL ENTROPY_MAX_SOURCES
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Entropy poll callback pointer
+ *
+ * \param data Callback-specific data pointer
+ * \param output Data to fill
+ * \param len Maximum size to provide
+ * \param olen The actual amount of bytes put into the buffer (Can be 0)
+ *
+ * \return 0 if no critical failures occurred,
+ * POLARSSL_ERR_ENTROPY_SOURCE_FAILED otherwise
+ */
+typedef int (*f_source_ptr)(void *, unsigned char *, size_t, size_t *);
+
+/**
+ * \brief Entropy source state
+ */
+typedef struct
+{
+ f_source_ptr f_source; /**< The entropy source callback */
+ void * p_source; /**< The callback data pointer */
+ size_t size; /**< Amount received */
+ size_t threshold; /**< Minimum level required before release */
+}
+source_state;
+
+/**
+ * \brief Entropy context structure
+ */
+typedef struct
+{
+ sha4_context accumulator;
+ int source_count;
+ source_state source[ENTROPY_MAX_SOURCES];
+#if defined(POLARSSL_HAVEGE_C)
+ havege_state havege_data;
+#endif
+}
+entropy_context;
+
+/**
+ * \brief Initialize the context
+ *
+ * \param ctx Entropy context to initialize
+ */
+void entropy_init( entropy_context *ctx );
+
+/**
+ * \brief Adds an entropy source to poll
+ *
+ * \param ctx Entropy context
+ * \param f_source Entropy function
+ * \param p_source Function data
+ * \param threshold Minimum required from source before entropy is released
+ * ( with entropy_func() )
+ *
+ * \return 0 if successful or POLARSSL_ERR_ENTROPY_MAX_SOURCES
+ */
+int entropy_add_source( entropy_context *ctx,
+ f_source_ptr f_source, void *p_source,
+ size_t threshold );
+
+/**
+ * \brief Trigger an extra gather poll for the accumulator
+ *
+ * \param ctx Entropy context
+ *
+ * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_gather( entropy_context *ctx );
+
+/**
+ * \brief Retrieve entropy from the accumulator (Max ENTROPY_BLOCK_SIZE)
+ *
+ * \param data Entropy context
+ * \param output Buffer to fill
+ * \param len Length of buffer
+ *
+ * \return 0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_func( void *data, unsigned char *output, size_t len );
+
+/**
+ * \brief Add data to the accumulator manually
+ *
+ * \param ctx Entropy context
+ * \param data Data to add
+ * \param len Length of data
+ *
+ * \return 0 if successful
+ */
+int entropy_update_manual( entropy_context *ctx,
+ const unsigned char *data, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy.h */
diff --git a/polarssl/src/include/polarssl/entropy_poll.h b/polarssl/src/include/polarssl/entropy_poll.h
new file mode 100644
index 0000000..0116598
--- /dev/null
+++ b/polarssl/src/include/polarssl/entropy_poll.h
@@ -0,0 +1,75 @@
+/**
+ * \file entropy_poll.h
+ *
+ * \brief Platform-specific and custom entropy polling functions
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ENTROPY_POLL_H
+#define POLARSSL_ENTROPY_POLL_H
+
+#include <string.h>
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Default thresholds for built-in sources
+ */
+#define ENTROPY_MIN_PLATFORM 128 /**< Minimum for platform source */
+#define ENTROPY_MIN_HAVEGE 128 /**< Minimum for HAVEGE */
+#define ENTROPY_MIN_HARDCLOCK 32 /**< Minimum for hardclock() */
+
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+/**
+ * \brief Platform-specific entropy poll callback
+ */
+int platform_entropy_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(POLARSSL_HAVEGE_C)
+/**
+ * \brief HAVEGE based entropy poll callback
+ *
+ * Requires an HAVEGE state as its data pointer.
+ */
+int havege_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(POLARSSL_TIMING_C)
+/**
+ * \brief hardclock-based entropy poll callback
+ */
+int hardclock_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy_poll.h */
diff --git a/polarssl/src/include/polarssl/error.h b/polarssl/src/include/polarssl/error.h
new file mode 100644
index 0000000..f3514df
--- /dev/null
+++ b/polarssl/src/include/polarssl/error.h
@@ -0,0 +1,102 @@
+/**
+ * \file error.h
+ *
+ * \brief Error to string translation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_ERROR_H
+#define POLARSSL_ERROR_H
+
+/**
+ * Error code layout.
+ *
+ * Currently we try to keep all error codes within the negative space of 16
+ * bytes signed integers to support all platforms (-0x0000 - -0x8000). In
+ * addition we'd like to give two layers of information on the error if
+ * possible.
+ *
+ * For that purpose the error codes are segmented in the following manner:
+ *
+ * 16 bit error code bit-segmentation
+ *
+ * 1 bit - Intentionally not used
+ * 3 bits - High level module ID
+ * 5 bits - Module-dependent error code
+ * 6 bits - Low level module errors
+ * 1 bit - Intentionally not used
+ *
+ * Low-level module errors (0x007E-0x0002)
+ *
+ * Module Nr Codes assigned
+ * MPI 7 0x0002-0x0010
+ * GCM 2 0x0012-0x0014
+ * AES 2 0x0020-0x0022
+ * CAMELLIA 2 0x0024-0x0026
+ * XTEA 1 0x0028-0x0028
+ * BASE64 2 0x002A-0x002C
+ * PADLOCK 1 0x0030-0x0030
+ * DES 1 0x0032-0x0032
+ * CTR_DBRG 3 0x0034-0x003A
+ * ENTROPY 3 0x003C-0x0040
+ * NET 11 0x0042-0x0056
+ * ASN1 7 0x0060-0x006C
+ * MD2 1 0x0070-0x0070
+ * MD4 1 0x0072-0x0072
+ * MD5 1 0x0074-0x0074
+ * SHA1 1 0x0076-0x0076
+ * SHA2 1 0x0078-0x0078
+ * SHA4 1 0x007A-0x007A
+ *
+ * High-level module nr (3 bits - 0x1...-0x8...)
+ * Name ID Nr of Errors
+ * PEM 1 8
+ * X509 2 21
+ * DHM 3 6
+ * RSA 4 9
+ * MD 5 4
+ * CIPHER 6 5
+ * SSL 7 30
+ *
+ * Module dependent error code (5 bits 0x.08.-0x.F8.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Translate a PolarSSL error code into a string representation,
+ * Result is truncated if necessary and always includes a terminating
+ * null byte.
+ *
+ * \param errnum error code
+ * \param buffer buffer to place representation in
+ * \param buflen length of the buffer
+ */
+void error_strerror( int errnum, char *buffer, size_t buflen );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/polarssl/src/include/polarssl/gcm.h b/polarssl/src/include/polarssl/gcm.h
new file mode 100644
index 0000000..2f88c70
--- /dev/null
+++ b/polarssl/src/include/polarssl/gcm.h
@@ -0,0 +1,142 @@
+/**
+ * \file gcm.h
+ *
+ * \brief Galois/Counter mode for AES
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_GCM_H
+#define POLARSSL_GCM_H
+
+#include "aes.h"
+
+#include <stdint.h>
+
+#define GCM_ENCRYPT 1
+#define GCM_DECRYPT 0
+
+#define POLARSSL_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
+#define POLARSSL_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
+
+/**
+ * \brief GCM context structure
+ */
+typedef struct {
+ aes_context aes_ctx; /*!< AES context used */
+ uint64_t HL[16]; /*!< Precalculated HTable */
+ uint64_t HH[16]; /*!< Precalculated HTable */
+}
+gcm_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief GCM initialization (encryption)
+ *
+ * \param ctx GCM context to be initialized
+ * \param key encryption key
+ * \param keysize must be 128, 192 or 256
+ *
+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief GCM buffer encryption/decryption using AES
+ *
+ * \note On encryption, the output buffer can be the same as the input buffer.
+ * On decryption, the output buffer cannot be the same as input buffer.
+ * If buffers overlap, the output buffer must trail at least 8 bytes
+ * behind the input buffer.
+ *
+ * \param ctx GCM context
+ * \param mode GCM_ENCRYPT or GCM_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector
+ * \param iv_len length of IV
+ * \param add additional data
+ * \param add_len length of additional data
+ * \param input buffer holding the input data
+ * \param output buffer for holding the output data
+ * \param tag_len length of the tag to generate
+ * \param tag buffer for holding the tag
+ *
+ * \return 0 if successful
+ */
+int gcm_crypt_and_tag( gcm_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t tag_len,
+ unsigned char *tag );
+
+/**
+ * \brief GCM buffer authenticated decryption using AES
+ *
+ * \note On decryption, the output buffer cannot be the same as input buffer.
+ * If buffers overlap, the output buffer must trail at least 8 bytes
+ * behind the input buffer.
+ *
+ * \param ctx GCM context
+ * \param length length of the input data
+ * \param iv initialization vector
+ * \param iv_len length of IV
+ * \param add additional data
+ * \param add_len length of additional data
+ * \param tag buffer holding the tag
+ * \param tag_len length of the tag
+ * \param input buffer holding the input data
+ * \param output buffer for holding the output data
+ *
+ * \return 0 if successful and authenticated,
+ * POLARSSL_ERR_GCM_AUTH_FAILED if tag does not match
+ */
+int gcm_auth_decrypt( gcm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *tag,
+ size_t tag_len,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int gcm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* gcm.h */
diff --git a/polarssl/src/include/polarssl/havege.h b/polarssl/src/include/polarssl/havege.h
new file mode 100644
index 0000000..53c4f38
--- /dev/null
+++ b/polarssl/src/include/polarssl/havege.h
@@ -0,0 +1,71 @@
+/**
+ * \file havege.h
+ *
+ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_HAVEGE_H
+#define POLARSSL_HAVEGE_H
+
+#include <string.h>
+
+#define COLLECT_SIZE 1024
+
+/**
+ * \brief HAVEGE state structure
+ */
+typedef struct
+{
+ int PT1, PT2, offset[2];
+ int pool[COLLECT_SIZE];
+ int WALK[8192];
+}
+havege_state;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief HAVEGE initialization
+ *
+ * \param hs HAVEGE state to be initialized
+ */
+void havege_init( havege_state *hs );
+
+/**
+ * \brief HAVEGE rand function
+ *
+ * \param p_rng A HAVEGE state
+ * \param output Buffer to fill
+ * \param len Length of buffer
+ *
+ * \return 0
+ */
+int havege_random( void *p_rng, unsigned char *output, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* havege.h */
diff --git a/polarssl/src/include/polarssl/md.h b/polarssl/src/include/polarssl/md.h
new file mode 100644
index 0000000..88596cb
--- /dev/null
+++ b/polarssl/src/include/polarssl/md.h
@@ -0,0 +1,354 @@
+/**
+ * \file md.h
+ *
+ * \brief Generic message digest wrapper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD_H
+#define POLARSSL_MD_H
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */
+#define POLARSSL_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */
+#define POLARSSL_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */
+
+typedef enum {
+ POLARSSL_MD_NONE=0,
+ POLARSSL_MD_MD2,
+ POLARSSL_MD_MD4,
+ POLARSSL_MD_MD5,
+ POLARSSL_MD_SHA1,
+ POLARSSL_MD_SHA224,
+ POLARSSL_MD_SHA256,
+ POLARSSL_MD_SHA384,
+ POLARSSL_MD_SHA512,
+} md_type_t;
+
+#define POLARSSL_MD_MAX_SIZE 64 /* longest known is SHA512 */
+
+/**
+ * Message digest information. Allows message digest functions to be called
+ * in a generic way.
+ */
+typedef struct {
+ /** Digest identifier */
+ md_type_t type;
+
+ /** Name of the message digest */
+ const char * name;
+
+ /** Output length of the digest function */
+ int size;
+
+ /** Digest initialisation function */
+ void (*starts_func)( void *ctx );
+
+ /** Digest update function */
+ void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+ /** Digest finalisation function */
+ void (*finish_func)( void *ctx, unsigned char *output );
+
+ /** Generic digest function */
+ void (*digest_func)( const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+ /** Generic file digest function */
+ int (*file_func)( const char *path, unsigned char *output );
+
+ /** HMAC Initialisation function */
+ void (*hmac_starts_func)( void *ctx, const unsigned char *key, size_t keylen );
+
+ /** HMAC update function */
+ void (*hmac_update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+ /** HMAC finalisation function */
+ void (*hmac_finish_func)( void *ctx, unsigned char *output);
+
+ /** HMAC context reset function */
+ void (*hmac_reset_func)( void *ctx );
+
+ /** Generic HMAC function */
+ void (*hmac_func)( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+ /** Allocate a new context */
+ void * (*ctx_alloc_func)( void );
+
+ /** Free the given context */
+ void (*ctx_free_func)( void *ctx );
+
+} md_info_t;
+
+/**
+ * Generic message digest context.
+ */
+typedef struct {
+ /** Information about the associated message digest */
+ const md_info_t *md_info;
+
+ /** Digest-specific context */
+ void *md_ctx;
+} md_context_t;
+
+#define MD_CONTEXT_T_INIT { \
+ NULL, /* md_info */ \
+ NULL, /* md_ctx */ \
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Returns the list of digests supported by the generic digest module.
+ *
+ * \return a statically allocated array of digests, the last entry
+ * is 0.
+ */
+const int *md_list( void );
+
+/**
+ * \brief Returns the message digest information associated with the
+ * given digest name.
+ *
+ * \param md_name Name of the digest to search for.
+ *
+ * \return The message digest information associated with md_name or
+ * NULL if not found.
+ */
+const md_info_t *md_info_from_string( const char *md_name );
+
+/**
+ * \brief Returns the message digest information associated with the
+ * given digest type.
+ *
+ * \param md_type type of digest to search for.
+ *
+ * \return The message digest information associated with md_type or
+ * NULL if not found.
+ */
+const md_info_t *md_info_from_type( md_type_t md_type );
+
+/**
+ * \brief Initialises and fills the message digest context structure with
+ * the appropriate values.
+ *
+ * \param ctx context to initialise. May not be NULL. The
+ * digest-specific context (ctx->md_ctx) must be NULL. It will
+ * be allocated, and must be freed using md_free_ctx() later.
+ * \param md_info message digest to use.
+ *
+ * \returns \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on
+ * parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if
+ * allocation of the digest-specific context failed.
+ */
+int md_init_ctx( md_context_t *ctx, const md_info_t *md_info );
+
+/**
+ * \brief Free the message-specific context of ctx. Freeing ctx itself
+ * remains the responsibility of the caller.
+ *
+ * \param ctx Free the message-specific context
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_free_ctx( md_context_t *ctx );
+
+/**
+ * \brief Returns the size of the message digest output.
+ *
+ * \param md_info message digest info
+ *
+ * \return size of the message digest output.
+ */
+static inline unsigned char md_get_size( const md_info_t *md_info )
+{
+ return md_info->size;
+}
+
+/**
+ * \brief Returns the type of the message digest output.
+ *
+ * \param md_info message digest info
+ *
+ * \return type of the message digest output.
+ */
+static inline md_type_t md_get_type( const md_info_t *md_info )
+{
+ return md_info->type;
+}
+
+/**
+ * \brief Returns the name of the message digest output.
+ *
+ * \param md_info message digest info
+ *
+ * \return name of the message digest output.
+ */
+static inline const char *md_get_name( const md_info_t *md_info )
+{
+ return md_info->name;
+}
+
+/**
+ * \brief Set-up the given context for a new message digest
+ *
+ * \param ctx generic message digest context.
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_starts( md_context_t *ctx );
+
+/**
+ * \brief Generic message digest process buffer
+ *
+ * \param ctx Generic message digest context
+ * \param input buffer holding the datal
+ * \param ilen length of the input data
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief Generic message digest final digest
+ *
+ * \param ctx Generic message digest context
+ * \param output Generic message digest checksum result
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_finish( md_context_t *ctx, unsigned char *output );
+
+/**
+ * \brief Output = message_digest( input buffer )
+ *
+ * \param md_info message digest info
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output Generic message digest checksum result
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+/**
+ * \brief Output = message_digest( file contents )
+ *
+ * \param md_info message digest info
+ * \param path input file name
+ * \param output generic message digest checksum result
+ *
+ * \return 0 if successful, POLARSSL_ERR_MD_FILE_OPEN_FAILED if fopen
+ * failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed,
+ * POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL.
+ */
+int md_file( const md_info_t *md_info, const char *path, unsigned char *output );
+
+/**
+ * \brief Generic HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief Generic HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief Generic HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output Generic HMAC checksum result
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac_finish( md_context_t *ctx, unsigned char *output);
+
+/**
+ * \brief Generic HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac_reset( md_context_t *ctx );
+
+/**
+ * \brief Output = Generic_HMAC( hmac key, input buffer )
+ *
+ * \param md_info message digest info
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output Generic HMAC-result
+ *
+ * \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_H */
diff --git a/polarssl/src/include/polarssl/md2.h b/polarssl/src/include/polarssl/md2.h
new file mode 100644
index 0000000..1f60470
--- /dev/null
+++ b/polarssl/src/include/polarssl/md2.h
@@ -0,0 +1,153 @@
+/**
+ * \file md2.h
+ *
+ * \brief MD2 message digest algorithm (hash function)
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD2_H
+#define POLARSSL_MD2_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_MD2_FILE_IO_ERROR -0x0070 /**< Read/write error in file. */
+
+/**
+ * \brief MD2 context structure
+ */
+typedef struct
+{
+ unsigned char cksum[16]; /*!< checksum of the data block */
+ unsigned char state[48]; /*!< intermediate digest state */
+ unsigned char buffer[16]; /*!< data block being processed */
+
+ unsigned char ipad[16]; /*!< HMAC: inner padding */
+ unsigned char opad[16]; /*!< HMAC: outer padding */
+ size_t left; /*!< amount of data in buffer */
+}
+md2_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief MD2 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void md2_starts( md2_context *ctx );
+
+/**
+ * \brief MD2 process buffer
+ *
+ * \param ctx MD2 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD2 final digest
+ *
+ * \param ctx MD2 context
+ * \param output MD2 checksum result
+ */
+void md2_finish( md2_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief Output = MD2( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD2 checksum result
+ */
+void md2( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief Output = MD2( file contents )
+ *
+ * \param path input file name
+ * \param output MD2 checksum result
+ *
+ * \return 0 if successful, or POLARSSL_ERR_MD2_FILE_IO_ERROR
+ */
+int md2_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief MD2 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief MD2 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD2 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output MD2 HMAC checksum result
+ */
+void md2_hmac_finish( md2_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief MD2 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void md2_hmac_reset( md2_context *ctx );
+
+/**
+ * \brief Output = HMAC-MD2( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-MD2 result
+ */
+void md2_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int md2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md2.h */
diff --git a/polarssl/src/include/polarssl/md4.h b/polarssl/src/include/polarssl/md4.h
new file mode 100644
index 0000000..2bd35ea
--- /dev/null
+++ b/polarssl/src/include/polarssl/md4.h
@@ -0,0 +1,152 @@
+/**
+ * \file md4.h
+ *
+ * \brief MD4 message digest algorithm (hash function)
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD4_H
+#define POLARSSL_MD4_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_MD4_FILE_IO_ERROR -0x0072 /**< Read/write error in file. */
+
+/**
+ * \brief MD4 context structure
+ */
+typedef struct
+{
+ unsigned long total[2]; /*!< number of bytes processed */
+ unsigned long state[4]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+}
+md4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief MD4 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void md4_starts( md4_context *ctx );
+
+/**
+ * \brief MD4 process buffer
+ *
+ * \param ctx MD4 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD4 final digest
+ *
+ * \param ctx MD4 context
+ * \param output MD4 checksum result
+ */
+void md4_finish( md4_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief Output = MD4( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD4 checksum result
+ */
+void md4( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief Output = MD4( file contents )
+ *
+ * \param path input file name
+ * \param output MD4 checksum result
+ *
+ * \return 0 if successful, or POLARSSL_ERR_MD4_FILE_IO_ERROR
+ */
+int md4_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief MD4 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief MD4 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD4 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output MD4 HMAC checksum result
+ */
+void md4_hmac_finish( md4_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief MD4 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void md4_hmac_reset( md4_context *ctx );
+
+/**
+ * \brief Output = HMAC-MD4( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-MD4 result
+ */
+void md4_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int md4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md4.h */
diff --git a/polarssl/src/include/polarssl/md5.h b/polarssl/src/include/polarssl/md5.h
new file mode 100644
index 0000000..936e9c9
--- /dev/null
+++ b/polarssl/src/include/polarssl/md5.h
@@ -0,0 +1,154 @@
+/**
+ * \file md5.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD5_H
+#define POLARSSL_MD5_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_MD5_FILE_IO_ERROR -0x0074 /**< Read/write error in file. */
+
+/**
+ * \brief MD5 context structure
+ */
+typedef struct
+{
+ unsigned long total[2]; /*!< number of bytes processed */
+ unsigned long state[4]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+}
+md5_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief MD5 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void md5_starts( md5_context *ctx );
+
+/**
+ * \brief MD5 process buffer
+ *
+ * \param ctx MD5 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD5 final digest
+ *
+ * \param ctx MD5 context
+ * \param output MD5 checksum result
+ */
+void md5_finish( md5_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief Output = MD5( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD5 checksum result
+ */
+void md5( const unsigned char *input, size_t ilen, unsigned char output[16] );
+
+/**
+ * \brief Output = MD5( file contents )
+ *
+ * \param path input file name
+ * \param output MD5 checksum result
+ *
+ * \return 0 if successful, or POLARSSL_ERR_MD5_FILE_IO_ERROR
+ */
+int md5_file( const char *path, unsigned char output[16] );
+
+/**
+ * \brief MD5 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void md5_hmac_starts( md5_context *ctx,
+ const unsigned char *key, size_t keylen );
+
+/**
+ * \brief MD5 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void md5_hmac_update( md5_context *ctx,
+ const unsigned char *input, size_t ilen );
+
+/**
+ * \brief MD5 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output MD5 HMAC checksum result
+ */
+void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
+
+/**
+ * \brief MD5 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void md5_hmac_reset( md5_context *ctx );
+
+/**
+ * \brief Output = HMAC-MD5( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-MD5 result
+ */
+void md5_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int md5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* md5.h */
diff --git a/polarssl/src/include/polarssl/md_wrap.h b/polarssl/src/include/polarssl/md_wrap.h
new file mode 100644
index 0000000..46849d0
--- /dev/null
+++ b/polarssl/src/include/polarssl/md_wrap.h
@@ -0,0 +1,64 @@
+/**
+ * \file md_wrap.h
+ *
+ * \brief Message digest wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MD_WRAP_H
+#define POLARSSL_MD_WRAP_H
+
+#include "config.h"
+#include "md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(POLARSSL_MD2_C)
+extern const md_info_t md2_info;
+#endif
+#if defined(POLARSSL_MD4_C)
+extern const md_info_t md4_info;
+#endif
+#if defined(POLARSSL_MD5_C)
+extern const md_info_t md5_info;
+#endif
+#if defined(POLARSSL_SHA1_C)
+extern const md_info_t sha1_info;
+#endif
+#if defined(POLARSSL_SHA2_C)
+extern const md_info_t sha224_info;
+extern const md_info_t sha256_info;
+#endif
+#if defined(POLARSSL_SHA4_C)
+extern const md_info_t sha384_info;
+extern const md_info_t sha512_info;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_MD_WRAP_H */
diff --git a/polarssl/src/include/polarssl/net.h b/polarssl/src/include/polarssl/net.h
new file mode 100644
index 0000000..88302ac
--- /dev/null
+++ b/polarssl/src/include/polarssl/net.h
@@ -0,0 +1,159 @@
+/**
+ * \file net.h
+ *
+ * \brief Network communication functions
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_NET_H
+#define POLARSSL_NET_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_NET_UNKNOWN_HOST -0x0056 /**< Failed to get an IP address for the given hostname. */
+#define POLARSSL_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */
+#define POLARSSL_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */
+#define POLARSSL_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */
+#define POLARSSL_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */
+#define POLARSSL_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */
+#define POLARSSL_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */
+#define POLARSSL_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */
+#define POLARSSL_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */
+#define POLARSSL_ERR_NET_WANT_READ -0x0052 /**< Connection requires a read call. */
+#define POLARSSL_ERR_NET_WANT_WRITE -0x0054 /**< Connection requires a write call. */
+
+#define POLARSSL_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initiate a TCP connection with host:port
+ *
+ * \param fd Socket to use
+ * \param host Host to connect to
+ * \param port Port to connect to
+ *
+ * \return 0 if successful, or one of:
+ * POLARSSL_ERR_NET_SOCKET_FAILED,
+ * POLARSSL_ERR_NET_UNKNOWN_HOST,
+ * POLARSSL_ERR_NET_CONNECT_FAILED
+ */
+int net_connect( int *fd, const char *host, int port );
+
+/**
+ * \brief Create a listening socket on bind_ip:port.
+ * If bind_ip == NULL, all interfaces are binded.
+ *
+ * \param fd Socket to use
+ * \param bind_ip IP to bind to, can be NULL
+ * \param port Port number to use
+ *
+ * \return 0 if successful, or one of:
+ * POLARSSL_ERR_NET_SOCKET_FAILED,
+ * POLARSSL_ERR_NET_BIND_FAILED,
+ * POLARSSL_ERR_NET_LISTEN_FAILED
+ */
+int net_bind( int *fd, const char *bind_ip, int port );
+
+/**
+ * \brief Accept a connection from a remote client
+ *
+ * \param bind_fd Relevant socket
+ * \param client_fd Will contain the connected client socket
+ * \param client_ip Will contain the client IP address
+ *
+ * \return 0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or
+ * POLARSSL_ERR_NET_WOULD_BLOCK is bind_fd was set to
+ * non-blocking and accept() is blocking.
+ */
+int net_accept( int bind_fd, int *client_fd, void *client_ip );
+
+/**
+ * \brief Set the socket blocking
+ *
+ * \param fd Socket to set
+ *
+ * \return 0 if successful, or a non-zero error code
+ */
+int net_set_block( int fd );
+
+/**
+ * \brief Set the socket non-blocking
+ *
+ * \param fd Socket to set
+ *
+ * \return 0 if successful, or a non-zero error code
+ */
+int net_set_nonblock( int fd );
+
+/**
+ * \brief Portable usleep helper
+ *
+ * \param usec Amount of microseconds to sleep
+ *
+ * \note Real amount of time slept will not be less than
+ * select()'s timeout granularity (typically, 10ms).
+ */
+void net_usleep( unsigned long usec );
+
+/**
+ * \brief Read at most 'len' characters. If no error occurs,
+ * the actual amount read is returned.
+ *
+ * \param ctx Socket
+ * \param buf The buffer to write to
+ * \param len Maximum length of the buffer
+ *
+ * \return This function returns the number of bytes received,
+ * or a non-zero error code; POLARSSL_ERR_NET_WANT_READ
+ * indicates read() is blocking.
+ */
+int net_recv( void *ctx, unsigned char *buf, size_t len );
+
+/**
+ * \brief Write at most 'len' characters. If no error occurs,
+ * the actual amount read is returned.
+ *
+ * \param ctx Socket
+ * \param buf The buffer to read from
+ * \param len The length of the buffer
+ *
+ * \return This function returns the number of bytes sent,
+ * or a non-zero error code; POLARSSL_ERR_NET_WANT_WRITE
+ * indicates write() is blocking.
+ */
+int net_send( void *ctx, const unsigned char *buf, size_t len );
+
+/**
+ * \brief Gracefully shutdown the connection
+ *
+ * \param fd The socket to close
+ */
+void net_close( int fd );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* net.h */
diff --git a/polarssl/src/include/polarssl/openssl.h b/polarssl/src/include/polarssl/openssl.h
new file mode 100644
index 0000000..62609a2
--- /dev/null
+++ b/polarssl/src/include/polarssl/openssl.h
@@ -0,0 +1,136 @@
+/**
+ * \file openssl.h
+ *
+ * \brief OpenSSL wrapper (definitions, inline functions).
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * OpenSSL wrapper contributed by David Barett
+ */
+#ifndef POLARSSL_OPENSSL_H
+#define POLARSSL_OPENSSL_H
+
+#include "aes.h"
+#include "md5.h"
+#include "rsa.h"
+#include "sha1.h"
+
+#define AES_SIZE 16
+#define AES_BLOCK_SIZE 16
+#define AES_KEY aes_context
+#define MD5_CTX md5_context
+#define SHA_CTX sha1_context
+
+#define SHA1_Init( CTX ) \
+ sha1_starts( (CTX) )
+#define SHA1_Update( CTX, BUF, LEN ) \
+ sha1_update( (CTX), (unsigned char *)(BUF), (LEN) )
+#define SHA1_Final( OUT, CTX ) \
+ sha1_finish( (CTX), (OUT) )
+
+#define MD5_Init( CTX ) \
+ md5_starts( (CTX) )
+#define MD5_Update( CTX, BUF, LEN ) \
+ md5_update( (CTX), (unsigned char *)(BUF), (LEN) )
+#define MD5_Final( OUT, CTX ) \
+ md5_finish( (CTX), (OUT) )
+
+#define AES_set_encrypt_key( KEY, KEYSIZE, CTX ) \
+ aes_setkey_enc( (CTX), (KEY), (KEYSIZE) )
+#define AES_set_decrypt_key( KEY, KEYSIZE, CTX ) \
+ aes_setkey_dec( (CTX), (KEY), (KEYSIZE) )
+#define AES_cbc_encrypt( INPUT, OUTPUT, LEN, CTX, IV, MODE ) \
+ aes_crypt_cbc( (CTX), (MODE), (LEN), (IV), (INPUT), (OUTPUT) )
+
+/*
+ * RSA stuff follows. TODO: needs cleanup
+ */
+inline int __RSA_Passthrough( void *output, void *input, int size )
+{
+ memcpy( output, input, size );
+ return size;
+}
+
+inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr,
+ int len )
+{
+ unsigned char *buffer = *(unsigned char **) bufptr;
+ rsa_context *rsa;
+
+ /*
+ * Not a general-purpose parser: only parses public key from *exactly*
+ * openssl genrsa -out privkey.pem 512 (or 1024)
+ * openssl rsa -in privkey.pem -out privatekey.der -outform der
+ * openssl rsa -in privkey.pem -out pubkey.der -outform der -pubout
+ *
+ * TODO: make a general-purpose parse
+ */
+ if( ignore != 0 || ( len != 94 && len != 162 ) )
+ return( 0 );
+
+ rsa = (rsa_context *) malloc( sizeof( rsa_rsa ) );
+ if( rsa == NULL )
+ return( 0 );
+
+ memset( rsa, 0, sizeof( rsa_context ) );
+
+ if( ( len == 94 &&
+ mpi_read_binary( &rsa->N, &buffer[ 25], 64 ) == 0 &&
+ mpi_read_binary( &rsa->E, &buffer[ 91], 3 ) == 0 ) ||
+ ( len == 162 &&
+ mpi_read_binary( &rsa->N, &buffer[ 29], 128 ) == 0 ) &&
+ mpi_read_binary( &rsa->E, &buffer[159], 3 ) == 0 )
+ {
+ /*
+ * key read successfully
+ */
+ rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3;
+ return( rsa );
+ }
+ else
+ {
+ memset( rsa, 0, sizeof( rsa_context ) );
+ free( rsa );
+ return( 0 );
+ }
+}
+
+#define RSA rsa_context
+#define RSA_PKCS1_PADDING 1 /* ignored; always encrypt with this */
+#define RSA_size( CTX ) (CTX)->len
+#define RSA_free( CTX ) rsa_free( CTX )
+#define ERR_get_error( ) "ERR_get_error() not supported"
+#define RSA_blinding_off( IGNORE )
+
+#define d2i_RSAPrivateKey( a, b, c ) new rsa_context /* TODO: C++ bleh */
+
+inline int RSA_public_decrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PUBLIC, &outsize, input, output ) ) return outsize; else return -1; }
+inline int RSA_private_decrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { int outsize=size; if( !rsa_pkcs1_decrypt( key, RSA_PRIVATE, &outsize, input, output ) ) return outsize; else return -1; }
+inline int RSA_public_encrypt ( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PUBLIC, size, input, output ) ) return RSA_size(key); else return -1; }
+inline int RSA_private_encrypt( int size, unsigned char* input, unsigned char* output, RSA* key, int ignore ) { if( !rsa_pkcs1_encrypt( key, RSA_PRIVATE, size, input, output ) ) return RSA_size(key); else return -1; }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* openssl.h */
diff --git a/polarssl/src/include/polarssl/padlock.h b/polarssl/src/include/polarssl/padlock.h
new file mode 100644
index 0000000..ce13570
--- /dev/null
+++ b/polarssl/src/include/polarssl/padlock.h
@@ -0,0 +1,100 @@
+/**
+ * \file padlock.h
+ *
+ * \brief VIA PadLock ACE for HW encryption/decryption supported by some processors
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PADLOCK_H
+#define POLARSSL_PADLOCK_H
+
+#include "aes.h"
+
+#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */
+
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
+
+#ifndef POLARSSL_HAVE_X86
+#define POLARSSL_HAVE_X86
+#endif
+
+#define PADLOCK_RNG 0x000C
+#define PADLOCK_ACE 0x00C0
+#define PADLOCK_PHE 0x0C00
+#define PADLOCK_PMM 0x3000
+
+#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PadLock detection routine
+ *
+ * \param The feature to detect
+ *
+ * \return 1 if CPU has support for the feature, 0 otherwise
+ */
+int padlock_supports( int feature );
+
+/**
+ * \brief PadLock AES-ECB block en(de)cryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if success, 1 if operation failed
+ */
+int padlock_xcryptecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief PadLock AES-CBC buffer en(de)cryption
+ *
+ * \param ctx AES context
+ * \param mode AES_ENCRYPT or AES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if success, 1 if operation failed
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_X86 */
+
+#endif /* padlock.h */
diff --git a/polarssl/src/include/polarssl/pem.h b/polarssl/src/include/polarssl/pem.h
new file mode 100644
index 0000000..1505401
--- /dev/null
+++ b/polarssl/src/include/polarssl/pem.h
@@ -0,0 +1,100 @@
+/**
+ * \file pem.h
+ *
+ * \brief Privacy Enhanced Mail (PEM) decoding
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PEM_H
+#define POLARSSL_PEM_H
+
+#include <string.h>
+
+/**
+ * \name PEM Error codes
+ * These error codes are returned in case of errors reading the
+ * PEM data.
+ * \{
+ */
+#define POLARSSL_ERR_PEM_NO_HEADER_PRESENT -0x1080 /**< No PEM header found. */
+#define POLARSSL_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */
+#define POLARSSL_ERR_PEM_MALLOC_FAILED -0x1180 /**< Failed to allocate memory. */
+#define POLARSSL_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */
+#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */
+#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */
+#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */
+#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */
+/* \} name */
+
+/**
+ * \brief PEM context structure
+ */
+typedef struct
+{
+ unsigned char *buf; /*!< buffer for decoded data */
+ size_t buflen; /*!< length of the buffer */
+ unsigned char *info; /*!< buffer for extra header information */
+}
+pem_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PEM context setup
+ *
+ * \param ctx context to be initialized
+ */
+void pem_init( pem_context *ctx );
+
+/**
+ * \brief Read a buffer for PEM information and store the resulting
+ * data into the specified context buffers.
+ *
+ * \param ctx context to use
+ * \param header header string to seek and expect
+ * \param footer footer string to seek and expect
+ * \param data source data to look in
+ * \param pwd password for decryption (can be NULL)
+ * \param pwdlen length of password
+ * \param use_len destination for total length used
+ *
+ * \return 0 on success, ior a specific PEM error code
+ */
+int pem_read_buffer( pem_context *ctx, char *header, char *footer,
+ const unsigned char *data,
+ const unsigned char *pwd,
+ size_t pwdlen, size_t *use_len );
+
+/**
+ * \brief PEM context memory freeing
+ *
+ * \param ctx context to be freed
+ */
+void pem_free( pem_context *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pem.h */
diff --git a/polarssl/src/include/polarssl/pkcs11.h b/polarssl/src/include/polarssl/pkcs11.h
new file mode 100644
index 0000000..a65a72e
--- /dev/null
+++ b/polarssl/src/include/polarssl/pkcs11.h
@@ -0,0 +1,126 @@
+/**
+ * \file pkcs11.h
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PKCS11_H
+#define POLARSSL_PKCS11_H
+
+#include "config.h"
+
+#if defined(POLARSSL_PKCS11_C)
+
+#include "x509.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
+
+/**
+ * Context for PKCS #11 private keys.
+ */
+typedef struct {
+ pkcs11h_certificate_t pkcs11h_cert;
+ int len;
+} pkcs11_context;
+
+/**
+ * Fill in a PolarSSL certificate, based on the given PKCS11 helper certificate.
+ *
+ * \param cert X.509 certificate to fill
+ * \param pkcs11h_cert PKCS #11 helper certificate
+ *
+ * \return 0 on success.
+ */
+int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11h_cert );
+
+/**
+ * Initialise a pkcs11_context, storing the given certificate. Note that the
+ * pkcs11_context will take over control of the certificate, freeing it when
+ * done.
+ *
+ * \param priv_key Private key structure to fill.
+ * \param pkcs11_cert PKCS #11 helper certificate
+ *
+ * \return 0 on success
+ */
+int pkcs11_priv_key_init( pkcs11_context *priv_key,
+ pkcs11h_certificate_t pkcs11_cert );
+
+/**
+ * Free the contents of the given private key context. Note that the structure
+ * itself is not freed.
+ *
+ * \param priv_key Private key structure to cleanup
+ */
+void pkcs11_priv_key_free( pkcs11_context *priv_key );
+
+/**
+ * \brief Do an RSA private key decrypt, then remove the message padding
+ *
+ * \param ctx PKCS #11 context
+ * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param input buffer holding the encrypted data
+ * \param output buffer that will hold the plaintext
+ * \param olen will contain the plaintext length
+ * \param output_max_len maximum length of the output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ * an error is thrown.
+ */
+int pkcs11_decrypt( pkcs11_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ unsigned int output_max_len );
+
+/**
+ * \brief Do a private RSA to sign a message digest
+ *
+ * \param ctx PKCS #11 context
+ * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer that will hold the ciphertext
+ *
+ * \return 0 if the signing operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int pkcs11_sign( pkcs11_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+#endif /* POLARSSL_PKCS11_C */
+
+#endif /* POLARSSL_PKCS11_H */
diff --git a/polarssl/src/include/polarssl/rsa.h b/polarssl/src/include/polarssl/rsa.h
new file mode 100644
index 0000000..513b037
--- /dev/null
+++ b/polarssl/src/include/polarssl/rsa.h
@@ -0,0 +1,379 @@
+/**
+ * \file rsa.h
+ *
+ * \brief The RSA public-key cryptosystem
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_RSA_H
+#define POLARSSL_RSA_H
+
+#include "bignum.h"
+
+/*
+ * RSA Error codes
+ */
+#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */
+#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */
+#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */
+#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */
+#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */
+#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */
+#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */
+#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */
+
+/*
+ * PKCS#1 constants
+ */
+#define SIG_RSA_RAW 0
+#define SIG_RSA_MD2 2
+#define SIG_RSA_MD4 3
+#define SIG_RSA_MD5 4
+#define SIG_RSA_SHA1 5
+#define SIG_RSA_SHA224 14
+#define SIG_RSA_SHA256 11
+#define SIG_RSA_SHA384 12
+#define SIG_RSA_SHA512 13
+
+#define RSA_PUBLIC 0
+#define RSA_PRIVATE 1
+
+#define RSA_PKCS_V15 0
+#define RSA_PKCS_V21 1
+
+#define RSA_SIGN 1
+#define RSA_CRYPT 2
+
+#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30"
+#define ASN1_STR_NULL "\x05"
+#define ASN1_STR_OID "\x06"
+#define ASN1_STR_OCTET_STRING "\x04"
+
+#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
+#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a"
+#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00"
+
+#define OID_ISO_MEMBER_BODIES "\x2a"
+#define OID_ISO_IDENTIFIED_ORG "\x2b"
+
+/*
+ * ISO Member bodies OID parts
+ */
+#define OID_COUNTRY_US "\x86\x48"
+#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d"
+
+/*
+ * ISO Identified organization OID parts
+ */
+#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a"
+
+/*
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * digest Digest }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * Digest ::= OCTET STRING
+ */
+#define ASN1_HASH_MDX \
+( \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \
+ ASN1_STR_OID "\x08" \
+ OID_DIGEST_ALG_MDX \
+ ASN1_STR_NULL "\x00" \
+ ASN1_STR_OCTET_STRING "\x10" \
+)
+
+#define ASN1_HASH_SHA1 \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \
+ ASN1_STR_OID "\x05" \
+ OID_HASH_ALG_SHA1 \
+ ASN1_STR_NULL "\x00" \
+ ASN1_STR_OCTET_STRING "\x14"
+
+#define ASN1_HASH_SHA1_ALT \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \
+ ASN1_STR_OID "\x05" \
+ OID_HASH_ALG_SHA1 \
+ ASN1_STR_OCTET_STRING "\x14"
+
+#define ASN1_HASH_SHA2X \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \
+ ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \
+ ASN1_STR_OID "\x09" \
+ OID_HASH_ALG_SHA2X \
+ ASN1_STR_NULL "\x00" \
+ ASN1_STR_OCTET_STRING "\x00"
+
+/**
+ * \brief RSA context structure
+ */
+typedef struct
+{
+ int ver; /*!< always 0 */
+ size_t len; /*!< size(N) in chars */
+
+ mpi N; /*!< public modulus */
+ mpi E; /*!< public exponent */
+
+ mpi D; /*!< private exponent */
+ mpi P; /*!< 1st prime factor */
+ mpi Q; /*!< 2nd prime factor */
+ mpi DP; /*!< D % (P - 1) */
+ mpi DQ; /*!< D % (Q - 1) */
+ mpi QP; /*!< 1 / (Q % P) */
+
+ mpi RN; /*!< cached R^2 mod N */
+ mpi RP; /*!< cached R^2 mod P */
+ mpi RQ; /*!< cached R^2 mod Q */
+
+ int padding; /*!< RSA_PKCS_V15 for 1.5 padding and
+ RSA_PKCS_v21 for OAEP/PSS */
+ int hash_id; /*!< Hash identifier of md_type_t as
+ specified in the md.h header file
+ for the EME-OAEP and EMSA-PSS
+ encoding */
+}
+rsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initialize an RSA context
+ *
+ * \param ctx RSA context to be initialized
+ * \param padding RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id RSA_PKCS_V21 hash identifier
+ *
+ * \note The hash_id parameter is actually ignored
+ * when using RSA_PKCS_V15 padding.
+ */
+void rsa_init( rsa_context *ctx,
+ int padding,
+ int hash_id);
+
+/**
+ * \brief Generate an RSA keypair
+ *
+ * \param ctx RSA context that will hold the key
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ * \param nbits size of the public key in bits
+ * \param exponent public exponent (e.g., 65537)
+ *
+ * \note rsa_init() must be called beforehand to setup
+ * the RSA context.
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_gen_key( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ unsigned int nbits, int exponent );
+
+/**
+ * \brief Check a public RSA key
+ *
+ * \param ctx RSA context to be checked
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_pubkey( const rsa_context *ctx );
+
+/**
+ * \brief Check a private RSA key
+ *
+ * \param ctx RSA context to be checked
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_privkey( const rsa_context *ctx );
+
+/**
+ * \brief Do an RSA public key operation
+ *
+ * \param ctx RSA context
+ * \param input input buffer
+ * \param output output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note This function does NOT take care of message
+ * padding. Also, be sure to set input[0] = 0 or assure that
+ * input is smaller than N.
+ *
+ * \note The input and output buffers must be large
+ * enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_public( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Do an RSA private key operation
+ *
+ * \param ctx RSA context
+ * \param input input buffer
+ * \param output output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The input and output buffers must be large
+ * enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_private( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Add the message padding, then do an RSA operation
+ *
+ * \param ctx RSA context
+ * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
+ * \param p_rng RNG parameter
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param ilen contains the plaintext length
+ * \param input buffer holding the data to be encrypted
+ * \param output buffer that will hold the ciphertext
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Do an RSA operation, then remove the message padding
+ *
+ * \param ctx RSA context
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param olen will contain the plaintext length
+ * \param input buffer holding the encrypted data
+ * \param output buffer that will hold the plaintext
+ * \param output_max_len maximum length of the output buffer
+ *
+ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ * an error is thrown.
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief Do a private RSA to sign a message digest
+ *
+ * \param ctx RSA context
+ * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
+ * \param p_rng RNG parameter
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer that will hold the ciphertext
+ *
+ * \return 0 if the signing operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note In case of PKCS#1 v2.1 encoding keep in mind that
+ * the hash_id in the RSA context is the one used for the
+ * encoding. hash_id in the function call is the type of hash
+ * that is encoded. According to RFC 3447 it is advised to
+ * keep both hashes the same.
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Do a public RSA and check the message digest
+ *
+ * \param ctx points to an RSA public key
+ * \param mode RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen message digest length (for SIG_RSA_RAW only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer holding the ciphertext
+ *
+ * \return 0 if the verify operation was successful,
+ * or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note In case of PKCS#1 v2.1 encoding keep in mind that
+ * the hash_id in the RSA context is the one used for the
+ * verification. hash_id in the function call is the type of hash
+ * that is verified. According to RFC 3447 it is advised to
+ * keep both hashes the same.
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief Free the components of an RSA key
+ *
+ * \param ctx RSA Context to free
+ */
+void rsa_free( rsa_context *ctx );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int rsa_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa.h */
diff --git a/polarssl/src/include/polarssl/sha1.h b/polarssl/src/include/polarssl/sha1.h
new file mode 100644
index 0000000..0d5e67e
--- /dev/null
+++ b/polarssl/src/include/polarssl/sha1.h
@@ -0,0 +1,152 @@
+/**
+ * \file sha1.h
+ *
+ * \brief SHA-1 cryptographic hash function
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA1_H
+#define POLARSSL_SHA1_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */
+
+/**
+ * \brief SHA-1 context structure
+ */
+typedef struct
+{
+ unsigned long total[2]; /*!< number of bytes processed */
+ unsigned long state[5]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+}
+sha1_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-1 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void sha1_starts( sha1_context *ctx );
+
+/**
+ * \brief SHA-1 process buffer
+ *
+ * \param ctx SHA-1 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-1 final digest
+ *
+ * \param ctx SHA-1 context
+ * \param output SHA-1 checksum result
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief Output = SHA-1( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-1 checksum result
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
+
+/**
+ * \brief Output = SHA-1( file contents )
+ *
+ * \param path input file name
+ * \param output SHA-1 checksum result
+ *
+ * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR
+ */
+int sha1_file( const char *path, unsigned char output[20] );
+
+/**
+ * \brief SHA-1 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen );
+
+/**
+ * \brief SHA-1 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-1 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output SHA-1 HMAC checksum result
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief SHA-1 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void sha1_hmac_reset( sha1_context *ctx );
+
+/**
+ * \brief Output = HMAC-SHA-1( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-SHA-1 result
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[20] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int sha1_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha1.h */
diff --git a/polarssl/src/include/polarssl/sha2.h b/polarssl/src/include/polarssl/sha2.h
new file mode 100644
index 0000000..811b0fd
--- /dev/null
+++ b/polarssl/src/include/polarssl/sha2.h
@@ -0,0 +1,160 @@
+/**
+ * \file sha2.h
+ *
+ * \brief SHA-224 and SHA-256 cryptographic hash function
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA2_H
+#define POLARSSL_SHA2_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_SHA2_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */
+
+/**
+ * \brief SHA-256 context structure
+ */
+typedef struct
+{
+ unsigned long total[2]; /*!< number of bytes processed */
+ unsigned long state[8]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+
+ unsigned char ipad[64]; /*!< HMAC: inner padding */
+ unsigned char opad[64]; /*!< HMAC: outer padding */
+ int is224; /*!< 0 => SHA-256, else SHA-224 */
+}
+sha2_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-256 context setup
+ *
+ * \param ctx context to be initialized
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void sha2_starts( sha2_context *ctx, int is224 );
+
+/**
+ * \brief SHA-256 process buffer
+ *
+ * \param ctx SHA-256 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-256 final digest
+ *
+ * \param ctx SHA-256 context
+ * \param output SHA-224/256 checksum result
+ */
+void sha2_finish( sha2_context *ctx, unsigned char output[32] );
+
+/**
+ * \brief Output = SHA-256( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-224/256 checksum result
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void sha2( const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 );
+
+/**
+ * \brief Output = SHA-256( file contents )
+ *
+ * \param path input file name
+ * \param output SHA-224/256 checksum result
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ *
+ * \return 0 if successful, or POLARSSL_ERR_SHA2_FILE_IO_ERROR
+ */
+int sha2_file( const char *path, unsigned char output[32], int is224 );
+
+/**
+ * \brief SHA-256 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
+ int is224 );
+
+/**
+ * \brief SHA-256 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-256 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output SHA-224/256 HMAC checksum result
+ */
+void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] );
+
+/**
+ * \brief SHA-256 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void sha2_hmac_reset( sha2_context *ctx );
+
+/**
+ * \brief Output = HMAC-SHA-256( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-SHA-224/256 result
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void sha2_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int sha2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha2.h */
diff --git a/polarssl/src/include/polarssl/sha4.h b/polarssl/src/include/polarssl/sha4.h
new file mode 100644
index 0000000..dafebec
--- /dev/null
+++ b/polarssl/src/include/polarssl/sha4.h
@@ -0,0 +1,168 @@
+/**
+ * \file sha4.h
+ *
+ * \brief SHA-384 and SHA-512 cryptographic hash function
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SHA4_H
+#define POLARSSL_SHA4_H
+
+#include <string.h>
+
+#define POLARSSL_ERR_SHA4_FILE_IO_ERROR -0x007A /**< Read/write error in file. */
+
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+ #define UL64(x) x##ui64
+ #define long64 __int64
+#else
+ #define UL64(x) x##ULL
+ #define long64 long long
+#endif
+
+/**
+ * \brief SHA-512 context structure
+ */
+typedef struct
+{
+ unsigned long64 total[2]; /*!< number of bytes processed */
+ unsigned long64 state[8]; /*!< intermediate digest state */
+ unsigned char buffer[128]; /*!< data block being processed */
+
+ unsigned char ipad[128]; /*!< HMAC: inner padding */
+ unsigned char opad[128]; /*!< HMAC: outer padding */
+ int is384; /*!< 0 => SHA-512, else SHA-384 */
+}
+sha4_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-512 context setup
+ *
+ * \param ctx context to be initialized
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ */
+void sha4_starts( sha4_context *ctx, int is384 );
+
+/**
+ * \brief SHA-512 process buffer
+ *
+ * \param ctx SHA-512 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-512 final digest
+ *
+ * \param ctx SHA-512 context
+ * \param output SHA-384/512 checksum result
+ */
+void sha4_finish( sha4_context *ctx, unsigned char output[64] );
+
+/**
+ * \brief Output = SHA-512( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-384/512 checksum result
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ */
+void sha4( const unsigned char *input, size_t ilen,
+ unsigned char output[64], int is384 );
+
+/**
+ * \brief Output = SHA-512( file contents )
+ *
+ * \param path input file name
+ * \param output SHA-384/512 checksum result
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ *
+ * \return 0 if successful, or POLARSSL_ERR_SHA4_FILE_IO_ERROR
+ */
+int sha4_file( const char *path, unsigned char output[64], int is384 );
+
+/**
+ * \brief SHA-512 HMAC context setup
+ *
+ * \param ctx HMAC context to be initialized
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ */
+void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
+ int is384 );
+
+/**
+ * \brief SHA-512 HMAC process buffer
+ *
+ * \param ctx HMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void sha4_hmac_update( sha4_context *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief SHA-512 HMAC final digest
+ *
+ * \param ctx HMAC context
+ * \param output SHA-384/512 HMAC checksum result
+ */
+void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] );
+
+/**
+ * \brief SHA-512 HMAC context reset
+ *
+ * \param ctx HMAC context to be reset
+ */
+void sha4_hmac_reset( sha4_context *ctx );
+
+/**
+ * \brief Output = HMAC-SHA-512( hmac key, input buffer )
+ *
+ * \param key HMAC secret key
+ * \param keylen length of the HMAC key
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output HMAC-SHA-384/512 result
+ * \param is384 0 = use SHA512, 1 = use SHA384
+ */
+void sha4_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[64], int is384 );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int sha4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sha4.h */
diff --git a/polarssl/src/include/polarssl/ssl.h b/polarssl/src/include/polarssl/ssl.h
new file mode 100644
index 0000000..4ac6f86
--- /dev/null
+++ b/polarssl/src/include/polarssl/ssl.h
@@ -0,0 +1,766 @@
+/**
+ * \file ssl.h
+ *
+ * \brief SSL/TLS functions.
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_SSL_H
+#define POLARSSL_SSL_H
+
+#include <time.h>
+
+#include "net.h"
+#include "dhm.h"
+#include "rsa.h"
+#include "md5.h"
+#include "sha1.h"
+#include "sha2.h"
+#include "sha4.h"
+#include "x509.h"
+#include "config.h"
+
+#if defined(POLARSSL_PKCS11_C)
+#include "pkcs11.h"
+#endif
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+/*
+ * SSL Error codes
+ */
+#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */
+#define POLARSSL_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */
+#define POLARSSL_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */
+#define POLARSSL_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */
+#define POLARSSL_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */
+#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */
+#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */
+#define POLARSSL_ERR_SSL_NO_SESSION_FOUND -0x7400 /**< No session to recover was found. */
+#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */
+#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message.*/
+#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */
+#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key is not set, but needed. */
+#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */
+#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */
+#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */
+#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */
+#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM Read Public. */
+#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret. */
+#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */
+#define POLARSSL_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */
+#define POLARSSL_ERR_SSL_MALLOC_FAILED -0x7F00 /**< Memory allocation failed */
+
+/*
+ * Various constants
+ */
+#define SSL_MAJOR_VERSION_3 3
+#define SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */
+#define SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */
+#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */
+#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */
+
+#define SSL_IS_CLIENT 0
+#define SSL_IS_SERVER 1
+#define SSL_COMPRESS_NULL 0
+
+#define SSL_VERIFY_NONE 0
+#define SSL_VERIFY_OPTIONAL 1
+#define SSL_VERIFY_REQUIRED 2
+
+#define SSL_MAX_CONTENT_LEN 16384
+
+/*
+ * Allow an extra 512 bytes for the record header
+ * and encryption overhead (counter + MAC + padding).
+ */
+#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + 512)
+
+/*
+ * Supported ciphersuites
+ */
+#define SSL_RSA_NULL_MD5 0x01 /**< Weak! */
+#define SSL_RSA_NULL_SHA 0x02 /**< Weak! */
+#define SSL_RSA_NULL_SHA256 0x3B /**< Weak! */
+#define SSL_RSA_DES_SHA 0x09 /**< Weak! Not in TLS 1.2 */
+#define SSL_EDH_RSA_DES_SHA 0x15 /**< Weak! Not in TLS 1.2 */
+
+#define SSL_RSA_RC4_128_MD5 0x04
+#define SSL_RSA_RC4_128_SHA 0x05
+
+#define SSL_RSA_DES_168_SHA 0x0A
+#define SSL_EDH_RSA_DES_168_SHA 0x16
+
+#define SSL_RSA_AES_128_SHA 0x2F
+#define SSL_EDH_RSA_AES_128_SHA 0x33
+#define SSL_RSA_AES_256_SHA 0x35
+#define SSL_EDH_RSA_AES_256_SHA 0x39
+#define SSL_RSA_AES_128_SHA256 0x3C /**< TLS 1.2 */
+#define SSL_RSA_AES_256_SHA256 0x3D /**< TLS 1.2 */
+#define SSL_EDH_RSA_AES_128_SHA256 0x67 /**< TLS 1.2 */
+#define SSL_EDH_RSA_AES_256_SHA256 0x6B /**< TLS 1.2 */
+
+#define SSL_RSA_CAMELLIA_128_SHA 0x41
+#define SSL_EDH_RSA_CAMELLIA_128_SHA 0x45
+#define SSL_RSA_CAMELLIA_256_SHA 0x84
+#define SSL_EDH_RSA_CAMELLIA_256_SHA 0x88
+#define SSL_RSA_CAMELLIA_128_SHA256 0xBA /**< TLS 1.2 */
+#define SSL_EDH_RSA_CAMELLIA_128_SHA256 0xBE /**< TLS 1.2 */
+#define SSL_RSA_CAMELLIA_256_SHA256 0xC0 /**< TLS 1.2 */
+#define SSL_EDH_RSA_CAMELLIA_256_SHA256 0xC4 /**< TLS 1.2 */
+
+#define SSL_RSA_AES_128_GCM_SHA256 0x9C
+#define SSL_RSA_AES_256_GCM_SHA384 0x9D
+#define SSL_EDH_RSA_AES_128_GCM_SHA256 0x9E
+#define SSL_EDH_RSA_AES_256_GCM_SHA384 0x9F
+
+/*
+ * Supported Signature and Hash algorithms (For TLS 1.2)
+ */
+#define SSL_HASH_NONE 0
+#define SSL_HASH_MD5 1
+#define SSL_HASH_SHA1 2
+#define SSL_HASH_SHA224 3
+#define SSL_HASH_SHA256 4
+#define SSL_HASH_SHA384 5
+#define SSL_HASH_SHA512 6
+
+#define SSL_SIG_RSA 1
+
+/*
+ * Message, alert and handshake types
+ */
+#define SSL_MSG_CHANGE_CIPHER_SPEC 20
+#define SSL_MSG_ALERT 21
+#define SSL_MSG_HANDSHAKE 22
+#define SSL_MSG_APPLICATION_DATA 23
+
+#define SSL_ALERT_LEVEL_WARNING 1
+#define SSL_ALERT_LEVEL_FATAL 2
+
+#define SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */
+#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */
+#define SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */
+#define SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */
+#define SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */
+#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */
+#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */
+#define SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */
+#define SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */
+#define SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */
+#define SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */
+#define SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */
+#define SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */
+#define SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */
+#define SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */
+#define SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */
+#define SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */
+#define SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */
+#define SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */
+#define SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */
+#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */
+#define SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */
+#define SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */
+#define SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */
+#define SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */
+
+#define SSL_HS_HELLO_REQUEST 0
+#define SSL_HS_CLIENT_HELLO 1
+#define SSL_HS_SERVER_HELLO 2
+#define SSL_HS_CERTIFICATE 11
+#define SSL_HS_SERVER_KEY_EXCHANGE 12
+#define SSL_HS_CERTIFICATE_REQUEST 13
+#define SSL_HS_SERVER_HELLO_DONE 14
+#define SSL_HS_CERTIFICATE_VERIFY 15
+#define SSL_HS_CLIENT_KEY_EXCHANGE 16
+#define SSL_HS_FINISHED 20
+
+/*
+ * TLS extensions
+ */
+#define TLS_EXT_SERVERNAME 0
+#define TLS_EXT_SERVERNAME_HOSTNAME 0
+
+#define TLS_EXT_SIG_ALG 13
+
+/*
+ * SSL state machine
+ */
+typedef enum
+{
+ SSL_HELLO_REQUEST,
+ SSL_CLIENT_HELLO,
+ SSL_SERVER_HELLO,
+ SSL_SERVER_CERTIFICATE,
+ SSL_SERVER_KEY_EXCHANGE,
+ SSL_CERTIFICATE_REQUEST,
+ SSL_SERVER_HELLO_DONE,
+ SSL_CLIENT_CERTIFICATE,
+ SSL_CLIENT_KEY_EXCHANGE,
+ SSL_CERTIFICATE_VERIFY,
+ SSL_CLIENT_CHANGE_CIPHER_SPEC,
+ SSL_CLIENT_FINISHED,
+ SSL_SERVER_CHANGE_CIPHER_SPEC,
+ SSL_SERVER_FINISHED,
+ SSL_FLUSH_BUFFERS,
+ SSL_HANDSHAKE_OVER
+}
+ssl_states;
+
+typedef struct _ssl_session ssl_session;
+typedef struct _ssl_context ssl_context;
+
+/*
+ * This structure is used for session resuming.
+ */
+struct _ssl_session
+{
+ time_t start; /*!< starting time */
+ int ciphersuite; /*!< chosen ciphersuite */
+ size_t length; /*!< session id length */
+ unsigned char id[32]; /*!< session identifier */
+ unsigned char master[48]; /*!< the master secret */
+ ssl_session *next; /*!< next session entry */
+};
+
+struct _ssl_context
+{
+ /*
+ * Miscellaneous
+ */
+ int state; /*!< SSL handshake: current state */
+
+ int major_ver; /*!< equal to SSL_MAJOR_VERSION_3 */
+ int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */
+
+ int max_major_ver; /*!< max. major version from client */
+ int max_minor_ver; /*!< max. minor version from client */
+
+ /*
+ * Callbacks (RNG, debug, I/O, verification)
+ */
+ int (*f_rng)(void *, unsigned char *, size_t);
+ void (*f_dbg)(void *, int, const char *);
+ int (*f_recv)(void *, unsigned char *, size_t);
+ int (*f_send)(void *, const unsigned char *, size_t);
+ int (*f_vrfy)(void *, x509_cert *, int, int);
+
+ void *p_rng; /*!< context for the RNG function */
+ void *p_dbg; /*!< context for the debug function */
+ void *p_recv; /*!< context for reading operations */
+ void *p_send; /*!< context for writing operations */
+ void *p_vrfy; /*!< context for verification */
+
+ /*
+ * Session layer
+ */
+ int resume; /*!< session resuming flag */
+ int timeout; /*!< sess. expiration time */
+ ssl_session *session; /*!< current session data */
+ int (*s_get)(ssl_context *); /*!< (server) get callback */
+ int (*s_set)(ssl_context *); /*!< (server) set callback */
+
+ /*
+ * Record layer (incoming data)
+ */
+ unsigned char *in_ctr; /*!< 64-bit incoming message counter */
+ unsigned char *in_hdr; /*!< 5-byte record header (in_ctr+8) */
+ unsigned char *in_msg; /*!< the message contents (in_hdr+5) */
+ unsigned char *in_offt; /*!< read offset in application data */
+
+ int in_msgtype; /*!< record header: message type */
+ size_t in_msglen; /*!< record header: message length */
+ size_t in_left; /*!< amount of data read so far */
+
+ size_t in_hslen; /*!< current handshake message length */
+ int nb_zero; /*!< # of 0-length encrypted messages */
+
+ /*
+ * Record layer (outgoing data)
+ */
+ unsigned char *out_ctr; /*!< 64-bit outgoing message counter */
+ unsigned char *out_hdr; /*!< 5-byte record header (out_ctr+8) */
+ unsigned char *out_msg; /*!< the message contents (out_hdr+5) */
+
+ int out_msgtype; /*!< record header: message type */
+ size_t out_msglen; /*!< record header: message length */
+ size_t out_left; /*!< amount of data not yet written */
+
+ /*
+ * PKI layer
+ */
+ rsa_context *rsa_key; /*!< own RSA private key */
+#if defined(POLARSSL_PKCS11_C)
+ pkcs11_context *pkcs11_key; /*!< own PKCS#11 RSA private key */
+#endif
+ x509_cert *own_cert; /*!< own X.509 certificate */
+ x509_cert *ca_chain; /*!< own trusted CA chain */
+ x509_crl *ca_crl; /*!< trusted CA CRLs */
+ x509_cert *peer_cert; /*!< peer X.509 cert chain */
+ const char *peer_cn; /*!< expected peer CN */
+
+ int endpoint; /*!< 0: client, 1: server */
+ int authmode; /*!< verification mode */
+ int client_auth; /*!< flag for client auth. */
+ int verify_result; /*!< verification result */
+
+ /*
+ * Crypto layer
+ */
+ dhm_context dhm_ctx; /*!< DHM key exchange */
+ unsigned char ctx_checksum[500]; /*!< Checksum context(s) */
+
+ void (*update_checksum)(ssl_context *, unsigned char *, size_t);
+ void (*calc_verify)(ssl_context *, unsigned char *);
+ void (*calc_finished)(ssl_context *, unsigned char *, int);
+ int (*tls_prf)(unsigned char *, size_t, char *,
+ unsigned char *, size_t,
+ unsigned char *, size_t);
+
+ int do_crypt; /*!< en(de)cryption flag */
+ int *ciphersuites; /*!< allowed ciphersuites */
+ size_t pmslen; /*!< premaster length */
+ unsigned int keylen; /*!< symmetric key length */
+ size_t minlen; /*!< min. ciphertext length */
+ size_t ivlen; /*!< IV length */
+ size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */
+ size_t maclen; /*!< MAC length */
+
+ unsigned char randbytes[64]; /*!< random bytes */
+ unsigned char premaster[256]; /*!< premaster secret */
+
+ unsigned char iv_enc[16]; /*!< IV (encryption) */
+ unsigned char iv_dec[16]; /*!< IV (decryption) */
+
+ unsigned char mac_enc[32]; /*!< MAC (encryption) */
+ unsigned char mac_dec[32]; /*!< MAC (decryption) */
+
+ unsigned long ctx_enc[134]; /*!< encryption context */
+ unsigned long ctx_dec[134]; /*!< decryption context */
+
+ /*
+ * TLS extensions
+ */
+ unsigned char *hostname;
+ size_t hostname_len;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ssl_default_ciphersuites[];
+
+/**
+ * \brief Returns the list of ciphersuites supported by the SSL/TLS module.
+ *
+ * \return a statically allocated array of ciphersuites, the last
+ * entry is 0.
+ */
+static inline const int *ssl_list_ciphersuites( void )
+{
+ return ssl_default_ciphersuites;
+}
+
+/**
+ * \brief Return the name of the ciphersuite associated with the given
+ * ID
+ *
+ * \param ciphersuite_id SSL ciphersuite ID
+ *
+ * \return a string containing the ciphersuite name
+ */
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id );
+
+/**
+ * \brief Return the ID of the ciphersuite associated with the given
+ * name
+ *
+ * \param ciphersuite_name SSL ciphersuite name
+ *
+ * \return the ID with the ciphersuite or 0 if not found
+ */
+int ssl_get_ciphersuite_id( const char *ciphersuite_name );
+
+/**
+ * \brief Initialize an SSL context
+ *
+ * \param ssl SSL context
+ *
+ * \return 0 if successful, or POLARSSL_ERR_SSL_MALLOC_FAILED if
+ * memory allocation failed
+ */
+int ssl_init( ssl_context *ssl );
+
+/**
+ * \brief Reset an already initialized SSL context for re-use
+ * while retaining application-set variables, function
+ * pointers and data.
+ *
+ * \param ssl SSL context
+ */
+void ssl_session_reset( ssl_context *ssl );
+
+/**
+ * \brief Set the current endpoint type
+ *
+ * \param ssl SSL context
+ * \param endpoint must be SSL_IS_CLIENT or SSL_IS_SERVER
+ */
+void ssl_set_endpoint( ssl_context *ssl, int endpoint );
+
+/**
+ * \brief Set the certificate verification mode
+ *
+ * \param ssl SSL context
+ * \param authmode can be:
+ *
+ * SSL_VERIFY_NONE: peer certificate is not checked (default),
+ * this is insecure and SHOULD be avoided.
+ *
+ * SSL_VERIFY_OPTIONAL: peer certificate is checked, however the
+ * handshake continues even if verification failed;
+ * ssl_get_verify_result() can be called after the
+ * handshake is complete.
+ *
+ * SSL_VERIFY_REQUIRED: peer *must* present a valid certificate,
+ * handshake is aborted if verification failed.
+ */
+void ssl_set_authmode( ssl_context *ssl, int authmode );
+
+/**
+ * \brief Set the verification callback (Optional).
+ *
+ * If set, the verification callback is called once for every
+ * certificate in the chain. The verification function has the
+ * following parameter: (void *parameter, x509_cert certificate,
+ * int certifcate_depth, int preverify_ok). It should
+ * return 0 on SUCCESS.
+ *
+ * \param ssl SSL context
+ * \param f_vrfy verification function
+ * \param p_vrfy verification parameter
+ */
+void ssl_set_verify( ssl_context *ssl,
+ int (*f_vrfy)(void *, x509_cert *, int, int),
+ void *p_vrfy );
+
+/**
+ * \brief Set the random number generator callback
+ *
+ * \param ssl SSL context
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ */
+void ssl_set_rng( ssl_context *ssl,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Set the debug callback
+ *
+ * \param ssl SSL context
+ * \param f_dbg debug function
+ * \param p_dbg debug parameter
+ */
+void ssl_set_dbg( ssl_context *ssl,
+ void (*f_dbg)(void *, int, const char *),
+ void *p_dbg );
+
+/**
+ * \brief Set the underlying BIO read and write callbacks
+ *
+ * \param ssl SSL context
+ * \param f_recv read callback
+ * \param p_recv read parameter
+ * \param f_send write callback
+ * \param p_send write parameter
+ */
+void ssl_set_bio( ssl_context *ssl,
+ int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
+ int (*f_send)(void *, const unsigned char *, size_t), void *p_send );
+
+/**
+ * \brief Set the session callbacks (server-side only)
+ *
+ * \param ssl SSL context
+ * \param s_get session get callback
+ * \param s_set session set callback
+ */
+void ssl_set_scb( ssl_context *ssl,
+ int (*s_get)(ssl_context *),
+ int (*s_set)(ssl_context *) );
+
+/**
+ * \brief Set the session resuming flag, timeout and data
+ *
+ * \param ssl SSL context
+ * \param resume if 0 (default), the session will not be resumed
+ * \param timeout session timeout in seconds, or 0 (no timeout)
+ * \param session session context
+ */
+void ssl_set_session( ssl_context *ssl, int resume, int timeout,
+ ssl_session *session );
+
+/**
+ * \brief Set the list of allowed ciphersuites
+ *
+ * \param ssl SSL context
+ * \param ciphersuites 0-terminated list of allowed ciphersuites
+ */
+void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites );
+
+/**
+ * \brief Set the data required to verify peer certificate
+ *
+ * \param ssl SSL context
+ * \param ca_chain trusted CA chain
+ * \param ca_crl trusted CA CRLs
+ * \param peer_cn expected peer CommonName (or NULL)
+ *
+ * \note TODO: add two more parameters: depth and crl
+ */
+void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
+ x509_crl *ca_crl, const char *peer_cn );
+
+/**
+ * \brief Set own certificate and private key
+ *
+ * \param ssl SSL context
+ * \param own_cert own public certificate
+ * \param rsa_key own private RSA key
+ */
+void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
+ rsa_context *rsa_key );
+
+#if defined(POLARSSL_PKCS11_C)
+/**
+ * \brief Set own certificate and PKCS#11 private key
+ *
+ * \param ssl SSL context
+ * \param own_cert own public certificate
+ * \param pkcs11_key own PKCS#11 RSA key
+ */
+void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert,
+ pkcs11_context *pkcs11_key );
+#endif
+
+/**
+ * \brief Set the Diffie-Hellman public P and G values,
+ * read as hexadecimal strings (server-side only)
+ *
+ * \param ssl SSL context
+ * \param dhm_P Diffie-Hellman-Merkle modulus
+ * \param dhm_G Diffie-Hellman-Merkle generator
+ *
+ * \return 0 if successful
+ */
+int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G );
+
+/**
+ * \brief Set the Diffie-Hellman public P and G values,
+ * read from existing context (server-side only)
+ *
+ * \param ssl SSL context
+ * \param dhm_ctx Diffie-Hellman-Merkle context
+ *
+ * \return 0 if successful
+ */
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
+
+/**
+ * \brief Set hostname for ServerName TLS Extension
+ *
+ *
+ * \param ssl SSL context
+ * \param hostname the server hostname
+ *
+ * \return 0 if successful or POLARSSL_ERR_SSL_MALLOC_FAILED
+ */
+int ssl_set_hostname( ssl_context *ssl, const char *hostname );
+
+/**
+ * \brief Set the maximum supported version sent from the client side
+ *
+ * \param ssl SSL context
+ * \param major Major version number (only SSL_MAJOR_VERSION_3 supported)
+ * \param minor Minor version number (SSL_MINOR_VERSION_0,
+ * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2,
+ * SSL_MINOR_VERSION_3 supported)
+ */
+void ssl_set_max_version( ssl_context *ssl, int major, int minor );
+
+/**
+ * \brief Return the number of data bytes available to read
+ *
+ * \param ssl SSL context
+ *
+ * \return how many bytes are available in the read buffer
+ */
+size_t ssl_get_bytes_avail( const ssl_context *ssl );
+
+/**
+ * \brief Return the result of the certificate verification
+ *
+ * \param ssl SSL context
+ *
+ * \return 0 if successful, or a combination of:
+ * BADCERT_EXPIRED
+ * BADCERT_REVOKED
+ * BADCERT_CN_MISMATCH
+ * BADCERT_NOT_TRUSTED
+ */
+int ssl_get_verify_result( const ssl_context *ssl );
+
+/**
+ * \brief Return the name of the current ciphersuite
+ *
+ * \param ssl SSL context
+ *
+ * \return a string containing the ciphersuite name
+ */
+const char *ssl_get_ciphersuite( const ssl_context *ssl );
+
+/**
+ * \brief Return the current SSL version (SSLv3/TLSv1/etc)
+ *
+ * \param ssl SSL context
+ *
+ * \return a string containing the SSL version
+ */
+const char *ssl_get_version( const ssl_context *ssl );
+
+/**
+ * \brief Perform the SSL handshake
+ *
+ * \param ssl SSL context
+ *
+ * \return 0 if successful, POLARSSL_ERR_NET_WANT_READ,
+ * POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code.
+ */
+int ssl_handshake( ssl_context *ssl );
+
+/**
+ * \brief Read at most 'len' application data bytes
+ *
+ * \param ssl SSL context
+ * \param buf buffer that will hold the data
+ * \param len how many bytes must be read
+ *
+ * \return This function returns the number of bytes read, 0 for EOF,
+ * or a negative error code.
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len );
+
+/**
+ * \brief Write exactly 'len' application data bytes
+ *
+ * \param ssl SSL context
+ * \param buf buffer holding the data
+ * \param len how many bytes must be written
+ *
+ * \return This function returns the number of bytes written,
+ * or a negative error code.
+ *
+ * \note When this function returns POLARSSL_ERR_NET_WANT_WRITE,
+ * it must be called later with the *same* arguments,
+ * until it returns a positive value.
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len );
+
+/**
+ * \brief Send an alert message
+ *
+ * \param ssl SSL context
+ * \param level The alert level of the message
+ * (SSL_ALERT_LEVEL_WARNING or SSL_ALERT_LEVEL_FATAL)
+ * \param message The alert message (SSL_ALERT_MSG_*)
+ *
+ * \return 1 if successful, or a specific SSL error code.
+ */
+int ssl_send_alert_message( ssl_context *ssl,
+ unsigned char level,
+ unsigned char message );
+/**
+ * \brief Notify the peer that the connection is being closed
+ *
+ * \param ssl SSL context
+ */
+int ssl_close_notify( ssl_context *ssl );
+
+/**
+ * \brief Free an SSL context
+ *
+ * \param ssl SSL context
+ */
+void ssl_free( ssl_context *ssl );
+
+/*
+ * Internal functions (do not call directly)
+ */
+int ssl_handshake_client( ssl_context *ssl );
+int ssl_handshake_server( ssl_context *ssl );
+
+int ssl_derive_keys( ssl_context *ssl );
+
+int ssl_read_record( ssl_context *ssl );
+/**
+ * \return 0 if successful, POLARSSL_ERR_SSL_CONN_EOF on EOF or
+ * another negative error code.
+ */
+int ssl_fetch_input( ssl_context *ssl, size_t nb_want );
+
+int ssl_write_record( ssl_context *ssl );
+int ssl_flush_output( ssl_context *ssl );
+
+int ssl_parse_certificate( ssl_context *ssl );
+int ssl_write_certificate( ssl_context *ssl );
+
+int ssl_parse_change_cipher_spec( ssl_context *ssl );
+int ssl_write_change_cipher_spec( ssl_context *ssl );
+
+int ssl_parse_finished( ssl_context *ssl );
+int ssl_write_finished( ssl_context *ssl );
+
+void ssl_kickstart_checksum( ssl_context *ssl, int ciphersuite,
+ unsigned char *input_buf, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl.h */
diff --git a/polarssl/src/include/polarssl/timing.h b/polarssl/src/include/polarssl/timing.h
new file mode 100644
index 0000000..355c63c
--- /dev/null
+++ b/polarssl/src/include/polarssl/timing.h
@@ -0,0 +1,75 @@
+/**
+ * \file timing.h
+ *
+ * \brief Portable interface to the CPU cycle counter
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_TIMING_H
+#define POLARSSL_TIMING_H
+
+/**
+ * \brief timer structure
+ */
+struct hr_time
+{
+ unsigned char opaque[32];
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern volatile int alarmed;
+
+/**
+ * \brief Return the CPU cycle counter value
+ */
+unsigned long hardclock( void );
+
+/**
+ * \brief Return the elapsed time in milliseconds
+ *
+ * \param val points to a timer structure
+ * \param reset if set to 1, the timer is restarted
+ */
+unsigned long get_timer( struct hr_time *val, int reset );
+
+/**
+ * \brief Setup an alarm clock
+ *
+ * \param seconds delay before the "alarmed" flag is set
+ */
+void set_alarm( int seconds );
+
+/**
+ * \brief Sleep for a certain amount of time
+ *
+ * \param milliseconds delay in milliseconds
+ */
+void m_sleep( int milliseconds );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* timing.h */
diff --git a/polarssl/src/include/polarssl/version.h b/polarssl/src/include/polarssl/version.h
new file mode 100644
index 0000000..98eb0b3
--- /dev/null
+++ b/polarssl/src/include/polarssl/version.h
@@ -0,0 +1,81 @@
+/**
+ * \file version.h
+ *
+ * \brief Run-time version information
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This set of compile-time defines and run-time variables can be used to
+ * determine the version number of the PolarSSL library used.
+ */
+#ifndef POLARSSL_VERSION_H
+#define POLARSSL_VERSION_H
+
+#include "config.h"
+
+/**
+ * The version number x.y.z is split into three parts.
+ * Major, Minor, Patchlevel
+ */
+#define POLARSSL_VERSION_MAJOR 1
+#define POLARSSL_VERSION_MINOR 1
+#define POLARSSL_VERSION_PATCH 1
+
+/**
+ * The single version number has the following structure:
+ * MMNNPP00
+ * Major version | Minor version | Patch version
+ */
+#define POLARSSL_VERSION_NUMBER 0x01010100
+#define POLARSSL_VERSION_STRING "1.1.1"
+#define POLARSSL_VERSION_STRING_FULL "PolarSSL 1.1.1"
+
+#if defined(POLARSSL_VERSION_C)
+
+/**
+ * Get the version number.
+ *
+ * \return The constructed version number in the format
+ * MMNNPP00 (Major, Minor, Patch).
+ */
+unsigned int version_get_number( void );
+
+/**
+ * Get the version string ("x.y.z").
+ *
+ * \param string The string that will receive the value.
+ * (Should be at least 9 bytes in size)
+ */
+void version_get_string( char *string );
+
+/**
+ * Get the full version string ("PolarSSL x.y.z").
+ *
+ * \param string The string that will receive the value.
+ * (Should be at least 18 bytes in size)
+ */
+void version_get_string_full( char *string );
+
+#endif /* POLARSSL_VERSION_C */
+
+#endif /* version.h */
diff --git a/polarssl/src/include/polarssl/x509.h b/polarssl/src/include/polarssl/x509.h
new file mode 100644
index 0000000..2cd883f
--- /dev/null
+++ b/polarssl/src/include/polarssl/x509.h
@@ -0,0 +1,733 @@
+/**
+ * \file x509.h
+ *
+ * \brief X.509 certificate and private key decoding
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_X509_H
+#define POLARSSL_X509_H
+
+#include "asn1.h"
+#include "rsa.h"
+#include "dhm.h"
+
+/**
+ * \addtogroup x509_module
+ * \{
+ */
+
+/**
+ * \name X509 Error codes
+ * \{
+ */
+#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */
+#define POLARSSL_ERR_X509_CERT_INVALID_PEM -0x2100 /**< The PEM-encoded certificate contains invalid elements, e.g. invalid character. */
+#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT -0x2180 /**< The certificate format is invalid, e.g. different type expected. */
+#define POLARSSL_ERR_X509_CERT_INVALID_VERSION -0x2200 /**< The certificate version element is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY -0x2480 /**< The pubkey tag or value is invalid (only RSA is supported). */
+#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE -0x2500 /**< The signature tag or value invalid. */
+#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS -0x2580 /**< The extension tag or value is invalid. */
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION -0x2600 /**< Certificate or CRL has an unsupported version number. */
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG -0x2680 /**< Signature algorithm (oid) is unsupported. */
+#define POLARSSL_ERR_X509_UNKNOWN_PK_ALG -0x2700 /**< Key algorithm is unsupported (only RSA is supported). */
+#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH -0x2780 /**< Certificate signature algorithms do not match. (see \c ::x509_cert sig_oid) */
+#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED -0x2800 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */
+#define POLARSSL_ERR_X509_KEY_INVALID_VERSION -0x2880 /**< Unsupported RSA key version */
+#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT -0x2900 /**< Invalid RSA key tag or value. */
+#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT -0x2980 /**< Format not recognized as DER or PEM. */
+#define POLARSSL_ERR_X509_INVALID_INPUT -0x2A00 /**< Input invalid. */
+#define POLARSSL_ERR_X509_MALLOC_FAILED -0x2A80 /**< Allocation of memory failed. */
+#define POLARSSL_ERR_X509_FILE_IO_ERROR -0x2B00 /**< Read/write of file failed. */
+/* \} name */
+
+
+/**
+ * \name X509 Verify codes
+ * \{
+ */
+#define BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */
+#define BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */
+#define BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */
+#define BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */
+#define BADCRL_NOT_TRUSTED 0x10 /**< CRL is not correctly signed by the trusted CA. */
+#define BADCRL_EXPIRED 0x20 /**< CRL is expired. */
+#define BADCERT_MISSING 0x40 /**< Certificate was missing. */
+#define BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */
+/* \} name */
+/* \} addtogroup x509_module */
+
+/*
+ * various object identifiers
+ */
+#define X520_COMMON_NAME 3
+#define X520_COUNTRY 6
+#define X520_LOCALITY 7
+#define X520_STATE 8
+#define X520_ORGANIZATION 10
+#define X520_ORG_UNIT 11
+#define PKCS9_EMAIL 1
+
+#define X509_OUTPUT_DER 0x01
+#define X509_OUTPUT_PEM 0x02
+#define PEM_LINE_LENGTH 72
+#define X509_ISSUER 0x01
+#define X509_SUBJECT 0x02
+
+#define OID_X520 "\x55\x04"
+#define OID_CN OID_X520 "\x03"
+#define OID_COUNTRY OID_X520 "\x06"
+#define OID_LOCALITY OID_X520 "\x07"
+#define OID_STATE OID_X520 "\x08"
+#define OID_ORGANIZATION OID_X520 "\x0A"
+#define OID_ORG_UNIT OID_X520 "\x0B"
+
+#define OID_PKCS1 "\x2A\x86\x48\x86\xF7\x0D\x01\x01"
+#define OID_PKCS1_RSA OID_PKCS1 "\x01"
+#define OID_PKCS1_SHA1 OID_PKCS1 "\x05"
+
+#define OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D"
+
+#define OID_PKCS9 "\x2A\x86\x48\x86\xF7\x0D\x01\x09"
+#define OID_PKCS9_EMAIL OID_PKCS9 "\x01"
+
+/** ISO arc for standard certificate and CRL extensions */
+#define OID_ID_CE "\x55\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */
+
+/**
+ * Private Internet Extensions
+ * { iso(1) identified-organization(3) dod(6) internet(1)
+ * security(5) mechanisms(5) pkix(7) }
+ */
+#define OID_PKIX "\x2B\x06\x01\x05\x05\x07"
+
+/*
+ * OIDs for standard certificate extensions
+ */
+#define OID_AUTHORITY_KEY_IDENTIFIER OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */
+#define OID_SUBJECT_KEY_IDENTIFIER OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */
+#define OID_KEY_USAGE OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */
+#define OID_CERTIFICATE_POLICIES OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */
+#define OID_POLICY_MAPPINGS OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */
+#define OID_SUBJECT_ALT_NAME OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */
+#define OID_ISSUER_ALT_NAME OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */
+#define OID_SUBJECT_DIRECTORY_ATTRS OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */
+#define OID_BASIC_CONSTRAINTS OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */
+#define OID_NAME_CONSTRAINTS OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */
+#define OID_POLICY_CONSTRAINTS OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */
+#define OID_EXTENDED_KEY_USAGE OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */
+#define OID_CRL_DISTRIBUTION_POINTS OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */
+#define OID_INIHIBIT_ANYPOLICY OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */
+#define OID_FRESHEST_CRL OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */
+
+/*
+ * X.509 v3 Key Usage Extension flags
+ */
+#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */
+#define KU_NON_REPUDIATION (0x40) /* bit 1 */
+#define KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */
+#define KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */
+#define KU_KEY_AGREEMENT (0x08) /* bit 4 */
+#define KU_KEY_CERT_SIGN (0x04) /* bit 5 */
+#define KU_CRL_SIGN (0x02) /* bit 6 */
+
+/*
+ * X.509 v3 Extended key usage OIDs
+ */
+#define OID_ANY_EXTENDED_KEY_USAGE OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */
+
+#define OID_KP OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */
+#define OID_SERVER_AUTH OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */
+#define OID_CLIENT_AUTH OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */
+#define OID_CODE_SIGNING OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */
+#define OID_EMAIL_PROTECTION OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */
+#define OID_TIME_STAMPING OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */
+#define OID_OCSP_SIGNING OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */
+
+#define STRING_SERVER_AUTH "TLS Web Server Authentication"
+#define STRING_CLIENT_AUTH "TLS Web Client Authentication"
+#define STRING_CODE_SIGNING "Code Signing"
+#define STRING_EMAIL_PROTECTION "E-mail Protection"
+#define STRING_TIME_STAMPING "Time Stamping"
+#define STRING_OCSP_SIGNING "OCSP Signing"
+
+/*
+ * OIDs for CRL extensions
+ */
+#define OID_PRIVATE_KEY_USAGE_PERIOD OID_ID_CE "\x10"
+#define OID_CRL_NUMBER OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */
+
+/*
+ * Netscape certificate extensions
+ */
+#define OID_NETSCAPE "\x60\x86\x48\x01\x86\xF8\x42" /**< Netscape OID */
+#define OID_NS_CERT OID_NETSCAPE "\x01"
+#define OID_NS_CERT_TYPE OID_NS_CERT "\x01"
+#define OID_NS_BASE_URL OID_NS_CERT "\x02"
+#define OID_NS_REVOCATION_URL OID_NS_CERT "\x03"
+#define OID_NS_CA_REVOCATION_URL OID_NS_CERT "\x04"
+#define OID_NS_RENEWAL_URL OID_NS_CERT "\x07"
+#define OID_NS_CA_POLICY_URL OID_NS_CERT "\x08"
+#define OID_NS_SSL_SERVER_NAME OID_NS_CERT "\x0C"
+#define OID_NS_COMMENT OID_NS_CERT "\x0D"
+#define OID_NS_DATA_TYPE OID_NETSCAPE "\x02"
+#define OID_NS_CERT_SEQUENCE OID_NS_DATA_TYPE "\x05"
+
+/*
+ * Netscape certificate types
+ * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html)
+ */
+
+#define NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */
+#define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */
+#define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */
+#define NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */
+#define NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */
+#define NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */
+#define NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */
+#define NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */
+
+#define EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0)
+#define EXT_SUBJECT_KEY_IDENTIFIER (1 << 1)
+#define EXT_KEY_USAGE (1 << 2)
+#define EXT_CERTIFICATE_POLICIES (1 << 3)
+#define EXT_POLICY_MAPPINGS (1 << 4)
+#define EXT_SUBJECT_ALT_NAME (1 << 5)
+#define EXT_ISSUER_ALT_NAME (1 << 6)
+#define EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7)
+#define EXT_BASIC_CONSTRAINTS (1 << 8)
+#define EXT_NAME_CONSTRAINTS (1 << 9)
+#define EXT_POLICY_CONSTRAINTS (1 << 10)
+#define EXT_EXTENDED_KEY_USAGE (1 << 11)
+#define EXT_CRL_DISTRIBUTION_POINTS (1 << 12)
+#define EXT_INIHIBIT_ANYPOLICY (1 << 13)
+#define EXT_FRESHEST_CRL (1 << 14)
+
+#define EXT_NS_CERT_TYPE (1 << 16)
+
+/*
+ * Storage format identifiers
+ * Recognized formats: PEM and DER
+ */
+#define X509_FORMAT_DER 1
+#define X509_FORMAT_PEM 2
+
+/**
+ * \addtogroup x509_module
+ * \{ */
+
+/**
+ * \name Structures for parsing X.509 certificates and CRLs
+ * \{
+ */
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef asn1_buf x509_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef asn1_bitstring x509_bitstring;
+
+/**
+ * Container for ASN1 named information objects.
+ * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.).
+ */
+typedef struct _x509_name
+{
+ x509_buf oid; /**< The object identifier. */
+ x509_buf val; /**< The named value. */
+ struct _x509_name *next; /**< The next named information object. */
+}
+x509_name;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef asn1_sequence x509_sequence;
+
+/** Container for date and time (precision in seconds). */
+typedef struct _x509_time
+{
+ int year, mon, day; /**< Date. */
+ int hour, min, sec; /**< Time. */
+}
+x509_time;
+
+/**
+ * Container for an X.509 certificate. The certificate may be chained.
+ */
+typedef struct _x509_cert
+{
+ x509_buf raw; /**< The raw certificate data (DER). */
+ x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */
+
+ int version; /**< The X.509 version. (0=v1, 1=v2, 2=v3) */
+ x509_buf serial; /**< Unique id for certificate issued by a specific CA. */
+ x509_buf sig_oid1; /**< Signature algorithm, e.g. sha1RSA */
+
+ x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */
+ x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */
+
+ x509_name issuer; /**< The parsed issuer data (named information object). */
+ x509_name subject; /**< The parsed subject data (named information object). */
+
+ x509_time valid_from; /**< Start time of certificate validity. */
+ x509_time valid_to; /**< End time of certificate validity. */
+
+ x509_buf pk_oid; /**< Subject public key info. Includes the public key algorithm and the key itself. */
+ rsa_context rsa; /**< Container for the RSA context. Only RSA is supported for public keys at this time. */
+
+ x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */
+ x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */
+ x509_buf v3_ext; /**< Optional X.509 v3 extensions. Only Basic Contraints are supported at this time. */
+ x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */
+
+ int ext_types; /**< Bit string containing detected and parsed extensions */
+ int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
+ int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. */
+
+ unsigned char key_usage; /**< Optional key usage extension value: See the values below */
+
+ x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
+
+ unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values below */
+
+ x509_buf sig_oid2; /**< Signature algorithm. Must match sig_oid1. */
+ x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */
+ int sig_alg; /**< Internal representation of the signature algorithm, e.g. SIG_RSA_MD2 */
+
+ struct _x509_cert *next; /**< Next certificate in the CA-chain. */
+}
+x509_cert;
+
+/**
+ * Certificate revocation list entry.
+ * Contains the CA-specific serial numbers and revocation dates.
+ */
+typedef struct _x509_crl_entry
+{
+ x509_buf raw;
+
+ x509_buf serial;
+
+ x509_time revocation_date;
+
+ x509_buf entry_ext;
+
+ struct _x509_crl_entry *next;
+}
+x509_crl_entry;
+
+/**
+ * Certificate revocation list structure.
+ * Every CRL may have multiple entries.
+ */
+typedef struct _x509_crl
+{
+ x509_buf raw; /**< The raw certificate data (DER). */
+ x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */
+
+ int version;
+ x509_buf sig_oid1;
+
+ x509_buf issuer_raw; /**< The raw issuer data (DER). */
+
+ x509_name issuer; /**< The parsed issuer data (named information object). */
+
+ x509_time this_update;
+ x509_time next_update;
+
+ x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */
+
+ x509_buf crl_ext;
+
+ x509_buf sig_oid2;
+ x509_buf sig;
+ int sig_alg;
+
+ struct _x509_crl *next;
+}
+x509_crl;
+/** \} name Structures for parsing X.509 certificates and CRLs */
+/** \} addtogroup x509_module */
+
+/**
+ * \name Structures for writing X.509 certificates.
+ * XvP: commented out as they are not used.
+ * - <tt>typedef struct _x509_node x509_node;</tt>
+ * - <tt>typedef struct _x509_raw x509_raw;</tt>
+ */
+/*
+typedef struct _x509_node
+{
+ unsigned char *data;
+ unsigned char *p;
+ unsigned char *end;
+
+ size_t len;
+}
+x509_node;
+
+typedef struct _x509_raw
+{
+ x509_node raw;
+ x509_node tbs;
+
+ x509_node version;
+ x509_node serial;
+ x509_node tbs_signalg;
+ x509_node issuer;
+ x509_node validity;
+ x509_node subject;
+ x509_node subpubkey;
+
+ x509_node signalg;
+ x509_node sign;
+}
+x509_raw;
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Functions to read in DHM parameters, a certificate, CRL or private RSA key
+ * \{
+ */
+
+/** \ingroup x509_module */
+/**
+ * \brief Parse one or more certificates and add them
+ * to the chained list. Parses permissively. If some
+ * certificates can be parsed, the result is the number
+ * of failed certificates it encountered. If none complete
+ * correctly, the first error is returned.
+ *
+ * \param chain points to the start of the chain
+ * \param buf buffer holding the certificate data
+ * \param buflen size of the buffer
+ *
+ * \return 0 if all certificates parsed successfully, a positive number
+ * if partly successful or a specific X509 or PEM error code
+ */
+int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen );
+
+/** \ingroup x509_module */
+/**
+ * \brief Load one or more certificates and add them
+ * to the chained list. Parses permissively. If some
+ * certificates can be parsed, the result is the number
+ * of failed certificates it encountered. If none complete
+ * correctly, the first error is returned.
+ *
+ * \param chain points to the start of the chain
+ * \param path filename to read the certificates from
+ *
+ * \return 0 if all certificates parsed successfully, a positive number
+ * if partly successful or a specific X509 or PEM error code
+ */
+int x509parse_crtfile( x509_cert *chain, const char *path );
+
+/** \ingroup x509_module */
+/**
+ * \brief Parse one or more CRLs and add them
+ * to the chained list
+ *
+ * \param chain points to the start of the chain
+ * \param buf buffer holding the CRL data
+ * \param buflen size of the buffer
+ *
+ * \return 0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen );
+
+/** \ingroup x509_module */
+/**
+ * \brief Load one or more CRLs and add them
+ * to the chained list
+ *
+ * \param chain points to the start of the chain
+ * \param path filename to read the CRLs from
+ *
+ * \return 0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_crlfile( x509_crl *chain, const char *path );
+
+/** \ingroup x509_module */
+/**
+ * \brief Parse a private RSA key
+ *
+ * \param rsa RSA context to be initialized
+ * \param key input buffer
+ * \param keylen size of the buffer
+ * \param pwd password for decryption (optional)
+ * \param pwdlen size of the password
+ *
+ * \return 0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_key( rsa_context *rsa,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *pwd, size_t pwdlen );
+
+/** \ingroup x509_module */
+/**
+ * \brief Load and parse a private RSA key
+ *
+ * \param rsa RSA context to be initialized
+ * \param path filename to read the private key from
+ * \param password password to decrypt the file (can be NULL)
+ *
+ * \return 0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_keyfile( rsa_context *rsa, const char *path,
+ const char *password );
+
+/** \ingroup x509_module */
+/**
+ * \brief Parse a public RSA key
+ *
+ * \param rsa RSA context to be initialized
+ * \param key input buffer
+ * \param keylen size of the buffer
+ *
+ * \return 0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_public_key( rsa_context *rsa,
+ const unsigned char *key, size_t keylen );
+
+/** \ingroup x509_module */
+/**
+ * \brief Load and parse a public RSA key
+ *
+ * \param rsa RSA context to be initialized
+ * \param path filename to read the private key from
+ *
+ * \return 0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_public_keyfile( rsa_context *rsa, const char *path );
+
+/** \ingroup x509_module */
+/**
+ * \brief Parse DHM parameters
+ *
+ * \param dhm DHM context to be initialized
+ * \param dhmin input buffer
+ * \param dhminlen size of the buffer
+ *
+ * \return 0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen );
+
+/** \ingroup x509_module */
+/**
+ * \brief Load and parse DHM parameters
+ *
+ * \param dhm DHM context to be initialized
+ * \param path filename to read the DHM Parameters from
+ *
+ * \return 0 if successful, or a specific X509 or PEM error code
+ */
+int x509parse_dhmfile( dhm_context *dhm, const char *path );
+
+/** \} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */
+
+/**
+ * \brief Store the certificate DN in printable form into buf;
+ * no more than size characters will be written.
+ *
+ * \param buf Buffer to write to
+ * \param size Maximum size of buffer
+ * \param dn The X509 name to represent
+ *
+ * \return The amount of data written to the buffer, or -1 in
+ * case of an error.
+ */
+int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn );
+
+/**
+ * \brief Store the certificate serial in printable form into buf;
+ * no more than size characters will be written.
+ *
+ * \param buf Buffer to write to
+ * \param size Maximum size of buffer
+ * \param serial The X509 serial to represent
+ *
+ * \return The amount of data written to the buffer, or -1 in
+ * case of an error.
+ */
+int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial );
+
+/**
+ * \brief Returns an informational string about the
+ * certificate.
+ *
+ * \param buf Buffer to write to
+ * \param size Maximum size of buffer
+ * \param prefix A line prefix
+ * \param crt The X509 certificate to represent
+ *
+ * \return The amount of data written to the buffer, or -1 in
+ * case of an error.
+ */
+int x509parse_cert_info( char *buf, size_t size, const char *prefix,
+ const x509_cert *crt );
+
+/**
+ * \brief Returns an informational string about the
+ * CRL.
+ *
+ * \param buf Buffer to write to
+ * \param size Maximum size of buffer
+ * \param prefix A line prefix
+ * \param crl The X509 CRL to represent
+ *
+ * \return The amount of data written to the buffer, or -1 in
+ * case of an error.
+ */
+int x509parse_crl_info( char *buf, size_t size, const char *prefix,
+ const x509_crl *crl );
+
+/**
+ * \brief Give an known OID, return its descriptive string.
+ *
+ * \param oid buffer containing the oid
+ *
+ * \return Return a string if the OID is known,
+ * or NULL otherwise.
+ */
+const char *x509_oid_get_description( x509_buf *oid );
+
+/*
+ * \brief Give an OID, return a string version of its OID number.
+ *
+ * \param buf Buffer to write to
+ * \param size Maximum size of buffer
+ * \param oid Buffer containing the OID
+ *
+ * \return The amount of data written to the buffer, or -1 in
+ * case of an error.
+ */
+int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid );
+
+/**
+ * \brief Check a given x509_time against the system time and check
+ * if it is valid.
+ *
+ * \param time x509_time to check
+ *
+ * \return Return 0 if the x509_time is still valid,
+ * or 1 otherwise.
+ */
+int x509parse_time_expired( const x509_time *time );
+
+/**
+ * \name Functions to verify a certificate
+ * \{
+ */
+/** \ingroup x509_module */
+/**
+ * \brief Verify the certificate signature
+ *
+ * \param crt a certificate to be verified
+ * \param trust_ca the trusted CA chain
+ * \param ca_crl the CRL chain for trusted CA's
+ * \param cn expected Common Name (can be set to
+ * NULL if the CN must not be verified)
+ * \param flags result of the verification
+ * \param f_vrfy verification function
+ * \param p_vrfy verification parameter
+ *
+ * \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED,
+ * in which case *flags will have one or more of
+ * the following values set:
+ * BADCERT_EXPIRED --
+ * BADCERT_REVOKED --
+ * BADCERT_CN_MISMATCH --
+ * BADCERT_NOT_TRUSTED
+ *
+ * \note TODO: add two arguments, depth and crl
+ */
+int x509parse_verify( x509_cert *crt,
+ x509_cert *trust_ca,
+ x509_crl *ca_crl,
+ const char *cn, int *flags,
+ int (*f_vrfy)(void *, x509_cert *, int, int),
+ void *p_vrfy );
+
+/**
+ * \brief Verify the certificate signature
+ *
+ * \param crt a certificate to be verified
+ * \param crl the CRL to verify against
+ *
+ * \return 1 if the certificate is revoked, 0 otherwise
+ *
+ */
+int x509parse_revoked( const x509_cert *crt, const x509_crl *crl );
+
+/** \} name Functions to verify a certificate */
+
+
+
+/**
+ * \name Functions to clear a certificate, CRL or private RSA key
+ * \{
+ */
+/** \ingroup x509_module */
+/**
+ * \brief Unallocate all certificate data
+ *
+ * \param crt Certificate chain to free
+ */
+void x509_free( x509_cert *crt );
+
+/** \ingroup x509_module */
+/**
+ * \brief Unallocate all CRL data
+ *
+ * \param crl CRL chain to free
+ */
+void x509_crl_free( x509_crl *crl );
+
+/** \} name Functions to clear a certificate, CRL or private RSA key */
+
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int x509_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* x509.h */
diff --git a/polarssl/src/include/polarssl/x509write.h b/polarssl/src/include/polarssl/x509write.h
new file mode 100644
index 0000000..8ce3d86
--- /dev/null
+++ b/polarssl/src/include/polarssl/x509write.h
@@ -0,0 +1,46 @@
+/**
+ * \file x509write.h
+ *
+ * \brief X509 buffer writing functionality
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_X509_WRITE_H
+#define POLARSSL_X509_WRITE_H
+
+#include "rsa.h"
+
+typedef struct _x509_req_name
+{
+ char oid[128];
+ char name[128];
+
+ struct _x509_req_name *next;
+}
+x509_req_name;
+
+int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa );
+int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa );
+int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa,
+ x509_req_name *req_name, int hash_id );
+
+#endif /* POLARSSL_X509_WRITE_H */
diff --git a/polarssl/src/include/polarssl/xtea.h b/polarssl/src/include/polarssl/xtea.h
new file mode 100644
index 0000000..e2adb87
--- /dev/null
+++ b/polarssl/src/include/polarssl/xtea.h
@@ -0,0 +1,111 @@
+/**
+ * \file xtea.h
+ *
+ * \brief XTEA block cipher (32-bit)
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_XTEA_H
+#define POLARSSL_XTEA_H
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define XTEA_ENCRYPT 1
+#define XTEA_DECRYPT 0
+
+#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */
+
+/**
+ * \brief XTEA context structure
+ */
+typedef struct
+{
+ uint32_t k[4]; /*!< key */
+}
+xtea_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief XTEA key schedule
+ *
+ * \param ctx XTEA context to be initialized
+ * \param key the secret key
+ */
+void xtea_setup( xtea_context *ctx, unsigned char key[16] );
+
+/**
+ * \brief XTEA cipher function
+ *
+ * \param ctx XTEA context
+ * \param mode XTEA_ENCRYPT or XTEA_DECRYPT
+ * \param input 8-byte input block
+ * \param output 8-byte output block
+ *
+ * \return 0 if successful
+ */
+int xtea_crypt_ecb( xtea_context *ctx,
+ int mode,
+ unsigned char input[8],
+ unsigned char output[8] );
+
+/**
+ * \brief XTEA CBC cipher function
+ *
+ * \param ctx XTEA context
+ * \param mode XTEA_ENCRYPT or XTEA_DECRYPT
+ * \param length the length of input, multiple of 8
+ * \param iv initialization vector for CBC mode
+ * \param input input block
+ * \param output output block
+ *
+ * \return 0 if successful,
+ * POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0
+ */
+int xtea_crypt_cbc( xtea_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ unsigned char *input,
+ unsigned char *output);
+
+/*
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int xtea_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* xtea.h */
diff --git a/polarssl/src/library/aes.c b/polarssl/src/library/aes.c
new file mode 100644
index 0000000..2f52202
--- /dev/null
+++ b/polarssl/src/library/aes.c
@@ -0,0 +1,1346 @@
+/*
+ * FIPS-197 compliant AES implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_AES_C)
+
+#include "polarssl/aes.h"
+#include "polarssl/padlock.h"
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_ULONG_LE
+#define GET_ULONG_LE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] ) \
+ | ( (unsigned long) (b)[(i) + 1] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_ULONG_LE
+#define PUT_ULONG_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+}
+#endif
+
+#if defined(POLARSSL_PADLOCK_C)
+static int aes_padlock_ace = -1;
+#endif
+
+#if defined(POLARSSL_AES_ROM_TABLES)
+/*
+ * Forward S-box
+ */
+static const unsigned char FSb[256] =
+{
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+ 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+ 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+ 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+ 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+ 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+ 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+ 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+ 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/*
+ * Forward tables
+ */
+#define FT \
+\
+ V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
+ V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
+ V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
+ V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
+ V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
+ V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
+ V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
+ V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
+ V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
+ V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
+ V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
+ V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
+ V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
+ V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
+ V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
+ V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
+ V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
+ V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
+ V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
+ V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
+ V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
+ V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
+ V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
+ V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
+ V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
+ V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
+ V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
+ V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
+ V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
+ V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
+ V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
+ V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
+ V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
+ V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
+ V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
+ V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
+ V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
+ V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
+ V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
+ V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
+ V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
+ V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
+ V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
+ V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
+ V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
+ V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
+ V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
+ V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
+ V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
+ V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
+ V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
+ V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
+ V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
+ V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
+ V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
+ V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
+ V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
+ V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
+ V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
+ V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
+ V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
+ V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
+ V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
+ V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const unsigned long FT0[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const unsigned long FT1[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const unsigned long FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const unsigned long FT3[256] = { FT };
+#undef V
+
+#undef FT
+
+/*
+ * Reverse S-box
+ */
+static const unsigned char RSb[256] =
+{
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+ 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+ 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+ 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+ 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+ 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+ 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+ 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+ 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+ 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+ 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+ 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/*
+ * Reverse tables
+ */
+#define RT \
+\
+ V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
+ V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
+ V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
+ V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
+ V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
+ V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
+ V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
+ V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
+ V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
+ V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
+ V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
+ V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
+ V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
+ V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
+ V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
+ V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
+ V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
+ V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
+ V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
+ V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
+ V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
+ V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
+ V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
+ V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
+ V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
+ V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
+ V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
+ V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
+ V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
+ V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
+ V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
+ V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
+ V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
+ V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
+ V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
+ V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
+ V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
+ V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
+ V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
+ V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
+ V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
+ V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
+ V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
+ V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
+ V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
+ V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
+ V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
+ V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
+ V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
+ V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
+ V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
+ V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
+ V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
+ V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
+ V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
+ V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
+ V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
+ V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
+ V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
+ V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
+ V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
+ V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
+ V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
+ V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const unsigned long RT0[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const unsigned long RT1[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const unsigned long RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const unsigned long RT3[256] = { RT };
+#undef V
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const unsigned long RCON[10] =
+{
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x0000001B, 0x00000036
+};
+
+#else
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static unsigned long FT0[256];
+static unsigned long FT1[256];
+static unsigned long FT2[256];
+static unsigned long FT3[256];
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static unsigned long RT0[256];
+static unsigned long RT1[256];
+static unsigned long RT2[256];
+static unsigned long RT3[256];
+
+/*
+ * Round constants
+ */
+static unsigned long RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
+
+static int aes_init_done = 0;
+
+static void aes_gen_tables( void )
+{
+ int i, x, y, z;
+ int pow[256];
+ int log[256];
+
+ /*
+ * compute pow and log tables over GF(2^8)
+ */
+ for( i = 0, x = 1; i < 256; i++ )
+ {
+ pow[i] = x;
+ log[x] = i;
+ x = ( x ^ XTIME( x ) ) & 0xFF;
+ }
+
+ /*
+ * calculate the round constants
+ */
+ for( i = 0, x = 1; i < 10; i++ )
+ {
+ RCON[i] = (unsigned long) x;
+ x = XTIME( x ) & 0xFF;
+ }
+
+ /*
+ * generate the forward and reverse S-boxes
+ */
+ FSb[0x00] = 0x63;
+ RSb[0x63] = 0x00;
+
+ for( i = 1; i < 256; i++ )
+ {
+ x = pow[255 - log[i]];
+
+ y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+ x ^= y ^ 0x63;
+
+ FSb[i] = (unsigned char) x;
+ RSb[x] = (unsigned char) i;
+ }
+
+ /*
+ * generate the forward and reverse tables
+ */
+ for( i = 0; i < 256; i++ )
+ {
+ x = FSb[i];
+ y = XTIME( x ) & 0xFF;
+ z = ( y ^ x ) & 0xFF;
+
+ FT0[i] = ( (unsigned long) y ) ^
+ ( (unsigned long) x << 8 ) ^
+ ( (unsigned long) x << 16 ) ^
+ ( (unsigned long) z << 24 );
+
+ FT1[i] = ROTL8( FT0[i] );
+ FT2[i] = ROTL8( FT1[i] );
+ FT3[i] = ROTL8( FT2[i] );
+
+ x = RSb[i];
+
+ RT0[i] = ( (unsigned long) MUL( 0x0E, x ) ) ^
+ ( (unsigned long) MUL( 0x09, x ) << 8 ) ^
+ ( (unsigned long) MUL( 0x0D, x ) << 16 ) ^
+ ( (unsigned long) MUL( 0x0B, x ) << 24 );
+
+ RT1[i] = ROTL8( RT0[i] );
+ RT2[i] = ROTL8( RT1[i] );
+ RT3[i] = ROTL8( RT2[i] );
+ }
+}
+
+#endif
+
+/*
+ * AES key schedule (encryption)
+ */
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ unsigned int i;
+ unsigned long *RK;
+
+#if !defined(POLARSSL_AES_ROM_TABLES)
+ if( aes_init_done == 0 )
+ {
+ aes_gen_tables();
+ aes_init_done = 1;
+
+ }
+#endif
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
+ if( aes_padlock_ace == -1 )
+ aes_padlock_ace = padlock_supports( PADLOCK_ACE );
+
+ if( aes_padlock_ace )
+ ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+ else
+#endif
+ ctx->rk = RK = ctx->buf;
+
+ for( i = 0; i < (keysize >> 5); i++ )
+ {
+ GET_ULONG_LE( RK[i], key, i << 2 );
+ }
+
+ switch( ctx->nr )
+ {
+ case 10:
+
+ for( i = 0; i < 10; i++, RK += 4 )
+ {
+ RK[4] = RK[0] ^ RCON[i] ^
+ ( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 );
+
+ RK[5] = RK[1] ^ RK[4];
+ RK[6] = RK[2] ^ RK[5];
+ RK[7] = RK[3] ^ RK[6];
+ }
+ break;
+
+ case 12:
+
+ for( i = 0; i < 8; i++, RK += 6 )
+ {
+ RK[6] = RK[0] ^ RCON[i] ^
+ ( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 );
+
+ RK[7] = RK[1] ^ RK[6];
+ RK[8] = RK[2] ^ RK[7];
+ RK[9] = RK[3] ^ RK[8];
+ RK[10] = RK[4] ^ RK[9];
+ RK[11] = RK[5] ^ RK[10];
+ }
+ break;
+
+ case 14:
+
+ for( i = 0; i < 7; i++, RK += 8 )
+ {
+ RK[8] = RK[0] ^ RCON[i] ^
+ ( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 );
+
+ RK[9] = RK[1] ^ RK[8];
+ RK[10] = RK[2] ^ RK[9];
+ RK[11] = RK[3] ^ RK[10];
+
+ RK[12] = RK[4] ^
+ ( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+ RK[13] = RK[5] ^ RK[12];
+ RK[14] = RK[6] ^ RK[13];
+ RK[15] = RK[7] ^ RK[14];
+ }
+ break;
+
+ default:
+
+ break;
+ }
+
+ return( 0 );
+}
+
+/*
+ * AES key schedule (decryption)
+ */
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int i, j;
+ aes_context cty;
+ unsigned long *RK;
+ unsigned long *SK;
+ int ret;
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
+ if( aes_padlock_ace == -1 )
+ aes_padlock_ace = padlock_supports( PADLOCK_ACE );
+
+ if( aes_padlock_ace )
+ ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
+ else
+#endif
+ ctx->rk = RK = ctx->buf;
+
+ ret = aes_setkey_enc( &cty, key, keysize );
+ if( ret != 0 )
+ return( ret );
+
+ SK = cty.rk + cty.nr * 4;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+ {
+ for( j = 0; j < 4; j++, SK++ )
+ {
+ *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
+ RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
+ RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
+ RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
+ }
+ }
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ memset( &cty, 0, sizeof( aes_context ) );
+
+ return( 0 );
+}
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
+ FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y3 >> 24 ) & 0xFF ]; \
+ \
+ X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
+ FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y0 >> 24 ) & 0xFF ]; \
+ \
+ X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
+ FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y1 >> 24 ) & 0xFF ]; \
+ \
+ X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
+ FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
+ FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
+ FT3[ ( Y2 >> 24 ) & 0xFF ]; \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
+ RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y1 >> 24 ) & 0xFF ]; \
+ \
+ X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
+ RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y2 >> 24 ) & 0xFF ]; \
+ \
+ X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
+ RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y3 >> 24 ) & 0xFF ]; \
+ \
+ X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
+ RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
+ RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
+ RT3[ ( Y0 >> 24 ) & 0xFF ]; \
+}
+
+/*
+ * AES-ECB block encryption/decryption
+ */
+int aes_crypt_ecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int i;
+ unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+ if( aes_padlock_ace )
+ {
+ if( padlock_xcryptecb( ctx, mode, input, output ) == 0 )
+ return( 0 );
+
+ // If padlock data misaligned, we just fall back to
+ // unaccelerated mode
+ //
+ }
+#endif
+
+ RK = ctx->rk;
+
+ GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++;
+ GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++;
+ GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++;
+ GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++;
+
+ if( mode == AES_DECRYPT )
+ {
+ for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+ {
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ }
+
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+ X0 = *RK++ ^ \
+ ( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^
+ ( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+ X1 = *RK++ ^ \
+ ( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^
+ ( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+ X2 = *RK++ ^ \
+ ( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^
+ ( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+ X3 = *RK++ ^ \
+ ( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^
+ ( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+ }
+ else /* AES_ENCRYPT */
+ {
+ for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+ {
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ }
+
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+ X0 = *RK++ ^ \
+ ( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+ X1 = *RK++ ^ \
+ ( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+ X2 = *RK++ ^ \
+ ( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+ X3 = *RK++ ^ \
+ ( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^
+ ( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+ }
+
+ PUT_ULONG_LE( X0, output, 0 );
+ PUT_ULONG_LE( X1, output, 4 );
+ PUT_ULONG_LE( X2, output, 8 );
+ PUT_ULONG_LE( X3, output, 12 );
+
+ return( 0 );
+}
+
+/*
+ * AES-CBC buffer encryption/decryption
+ */
+int aes_crypt_cbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[16];
+
+ if( length % 16 )
+ return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );
+
+#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
+ if( aes_padlock_ace )
+ {
+ if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
+ return( 0 );
+
+ // If padlock data misaligned, we just fall back to
+ // unaccelerated mode
+ //
+ }
+#endif
+
+ if( mode == AES_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 16 );
+ aes_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ aes_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 buffer encryption/decryption
+ */
+int aes_crypt_cfb128( aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == AES_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR buffer encryption/decryption
+ */
+int aes_crypt_ctr( aes_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block );
+
+ for( i = 16; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = (n + 1) & 0x0F;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * AES test vectors from:
+ *
+ * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
+ */
+static const unsigned char aes_test_ecb_dec[3][16] =
+{
+ { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+ 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+ { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+ 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
+ { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+ 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+};
+
+static const unsigned char aes_test_ecb_enc[3][16] =
+{
+ { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+ 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+ { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+ 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
+ { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+ 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+};
+
+static const unsigned char aes_test_cbc_dec[3][16] =
+{
+ { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
+ 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+ { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
+ 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
+ { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
+ 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+};
+
+static const unsigned char aes_test_cbc_enc[3][16] =
+{
+ { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
+ 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+ { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
+ 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
+ { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
+ 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_cfb128_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_cfb128_iv[16] =
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_cfb128_pt[64] =
+{
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_cfb128_ct[3][64] =
+{
+ { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+ 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+ 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
+ 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
+ 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
+ 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
+ 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
+ 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+ { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+ 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+ 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
+ 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
+ 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
+ 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
+ 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
+ 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
+ { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+ 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+ 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
+ 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
+ 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
+ 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
+ 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
+ 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * AES-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc3686.html
+ */
+
+static const unsigned char aes_test_ctr_key[3][16] =
+{
+ { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+ 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+ { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+ 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+ { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+ 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+{
+ { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+ 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+ 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char aes_test_ctr_pt[3][48] =
+{
+ { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char aes_test_ctr_ct[3][48] =
+{
+ { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+ 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
+ { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+ 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+ 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+ 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
+ { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+ 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+ 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+ 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+ 0x25, 0xB2, 0x07, 0x2F }
+};
+
+static const int aes_test_ctr_len[3] =
+ { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int aes_self_test( int verbose )
+{
+ int i, j, u, v;
+ unsigned char key[32];
+ unsigned char buf[64];
+ unsigned char prv[16];
+ unsigned char iv[16];
+#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB)
+ size_t offset;
+#endif
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ int len;
+ unsigned char nonce_counter[16];
+ unsigned char stream_block[16];
+#endif
+ aes_context ctx;
+
+ memset( key, 0, 32 );
+
+ /*
+ * ECB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-ECB-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( buf, 0, 16 );
+
+ if( v == AES_DECRYPT )
+ {
+ aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_ecb( &ctx, v, buf, buf );
+
+ if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_ecb( &ctx, v, buf, buf );
+
+ if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ /*
+ * CBC mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CBC-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( iv , 0, 16 );
+ memset( prv, 0, 16 );
+ memset( buf, 0, 16 );
+
+ if( v == AES_DECRYPT )
+ {
+ aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ for( j = 0; j < 10000; j++ )
+ {
+ unsigned char tmp[16];
+
+ aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+ memcpy( tmp, prv, 16 );
+ memcpy( prv, buf, 16 );
+ memcpy( buf, tmp, 16 );
+ }
+
+ if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ /*
+ * CFB128 mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CFB128-%3d (%s): ", 128 + u * 64,
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, aes_test_cfb128_iv, 16 );
+ memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
+
+ offset = 0;
+ aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+ if( v == AES_DECRYPT )
+ {
+ memcpy( buf, aes_test_cfb128_ct[u], 64 );
+ aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ memcpy( buf, aes_test_cfb128_pt, 64 );
+ aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+ if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ /*
+ * CTR mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " AES-CTR-128 (%s): ",
+ ( v == AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
+ memcpy( key, aes_test_ctr_key[u], 16 );
+
+ offset = 0;
+ aes_setkey_enc( &ctx, key, 128 );
+
+ if( v == AES_DECRYPT )
+ {
+ len = aes_test_ctr_len[u];
+ memcpy( buf, aes_test_ctr_ct[u], len );
+
+ aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ len = aes_test_ctr_len[u];
+ memcpy( buf, aes_test_ctr_pt[u], len );
+
+ aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/arc4.c b/polarssl/src/library/arc4.c
new file mode 100644
index 0000000..07665ad
--- /dev/null
+++ b/polarssl/src/library/arc4.c
@@ -0,0 +1,169 @@
+/*
+ * An implementation of the ARCFOUR algorithm
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The ARCFOUR algorithm was publicly disclosed on 94/09.
+ *
+ * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ARC4_C)
+
+#include "polarssl/arc4.h"
+
+/*
+ * ARC4 key schedule
+ */
+void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen )
+{
+ int i, j, a;
+ unsigned int k;
+ unsigned char *m;
+
+ ctx->x = 0;
+ ctx->y = 0;
+ m = ctx->m;
+
+ for( i = 0; i < 256; i++ )
+ m[i] = (unsigned char) i;
+
+ j = k = 0;
+
+ for( i = 0; i < 256; i++, k++ )
+ {
+ if( k >= keylen ) k = 0;
+
+ a = m[i];
+ j = ( j + a + key[k] ) & 0xFF;
+ m[i] = m[j];
+ m[j] = (unsigned char) a;
+ }
+}
+
+/*
+ * ARC4 cipher function
+ */
+int arc4_crypt( arc4_context *ctx, size_t length, const unsigned char *input,
+ unsigned char *output )
+{
+ int x, y, a, b;
+ size_t i;
+ unsigned char *m;
+
+ x = ctx->x;
+ y = ctx->y;
+ m = ctx->m;
+
+ for( i = 0; i < length; i++ )
+ {
+ x = ( x + 1 ) & 0xFF; a = m[x];
+ y = ( y + a ) & 0xFF; b = m[y];
+
+ m[x] = (unsigned char) b;
+ m[y] = (unsigned char) a;
+
+ output[i] = (unsigned char)
+ ( input[i] ^ m[(unsigned char)( a + b )] );
+ }
+
+ ctx->x = x;
+ ctx->y = y;
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
+ *
+ * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
+ */
+static const unsigned char arc4_test_key[3][8] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_pt[3][8] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_ct[3][8] =
+{
+ { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
+ { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
+ { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
+};
+
+/*
+ * Checkup routine
+ */
+int arc4_self_test( int verbose )
+{
+ int i;
+ unsigned char ibuf[8];
+ unsigned char obuf[8];
+ arc4_context ctx;
+
+ for( i = 0; i < 3; i++ )
+ {
+ if( verbose != 0 )
+ printf( " ARC4 test #%d: ", i + 1 );
+
+ memcpy( ibuf, arc4_test_pt[i], 8 );
+
+ arc4_setup( &ctx, (unsigned char *) arc4_test_key[i], 8 );
+ arc4_crypt( &ctx, 8, ibuf, obuf );
+
+ if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/asn1parse.c b/polarssl/src/library/asn1parse.c
new file mode 100644
index 0000000..2584774
--- /dev/null
+++ b/polarssl/src/library/asn1parse.c
@@ -0,0 +1,260 @@
+/*
+ * Generic ASN.1 parsing
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+
+#include "polarssl/asn1.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+/*
+ * ASN.1 DER decoding routines
+ */
+int asn1_get_len( unsigned char **p,
+ const unsigned char *end,
+ size_t *len )
+{
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ if( ( **p & 0x80 ) == 0 )
+ *len = *(*p)++;
+ else
+ {
+ switch( **p & 0x7F )
+ {
+ case 1:
+ if( ( end - *p ) < 2 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ *len = (*p)[1];
+ (*p) += 2;
+ break;
+
+ case 2:
+ if( ( end - *p ) < 3 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (*p)[1] << 8 ) | (*p)[2];
+ (*p) += 3;
+ break;
+
+ case 3:
+ if( ( end - *p ) < 4 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (*p)[1] << 16 ) | ( (*p)[2] << 8 ) | (*p)[3];
+ (*p) += 4;
+ break;
+
+ case 4:
+ if( ( end - *p ) < 5 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4];
+ (*p) += 5;
+ break;
+
+ default:
+ return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+ }
+ }
+
+ if( *len > (size_t) ( end - *p ) )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ return( 0 );
+}
+
+int asn1_get_tag( unsigned char **p,
+ const unsigned char *end,
+ size_t *len, int tag )
+{
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ if( **p != tag )
+ return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+ (*p)++;
+
+ return( asn1_get_len( p, end, len ) );
+}
+
+int asn1_get_bool( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
+ return( ret );
+
+ if( len != 1 )
+ return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+ *val = ( **p != 0 ) ? 1 : 0;
+ (*p)++;
+
+ return( 0 );
+}
+
+int asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
+ return( ret );
+
+ if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+ return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+ *val = 0;
+
+ while( len-- > 0 )
+ {
+ *val = ( *val << 8 ) | **p;
+ (*p)++;
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_BIGNUM_C)
+int asn1_get_mpi( unsigned char **p,
+ const unsigned char *end,
+ mpi *X )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
+ return( ret );
+
+ ret = mpi_read_binary( X, *p, len );
+
+ *p += len;
+
+ return( ret );
+}
+#endif /* POLARSSL_BIGNUM_C */
+
+int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+ asn1_bitstring *bs)
+{
+ int ret;
+
+ /* Certificate type is a single byte bitstring */
+ if( ( ret = asn1_get_tag( p, end, &bs->len, ASN1_BIT_STRING ) ) != 0 )
+ return( ret );
+
+ /* Check length, subtract one for actual bit string length */
+ if ( bs->len < 1 )
+ return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
+ bs->len -= 1;
+
+ /* Get number of unused bits, ensure unused bits <= 7 */
+ bs->unused_bits = **p;
+ if( bs->unused_bits > 7 )
+ return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
+ (*p)++;
+
+ /* Get actual bitstring */
+ bs->p = *p;
+ *p += bs->len;
+
+ if( *p != end )
+ return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return 0;
+}
+
+
+/*
+ * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ */
+int asn1_get_sequence_of( unsigned char **p,
+ const unsigned char *end,
+ asn1_sequence *cur,
+ int tag)
+{
+ int ret;
+ size_t len;
+ asn1_buf *buf;
+
+ /* Get main sequence tag */
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( ret );
+
+ if( *p + len != end )
+ return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ while( *p < end )
+ {
+ buf = &(cur->buf);
+ buf->tag = **p;
+
+ if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
+ return( ret );
+
+ buf->p = *p;
+ *p += buf->len;
+
+ /* Allocate and assign next pointer */
+ if (*p < end)
+ {
+ cur->next = (asn1_sequence *) malloc(
+ sizeof( asn1_sequence ) );
+
+ if( cur->next == NULL )
+ return( POLARSSL_ERR_ASN1_MALLOC_FAILED );
+
+ cur = cur->next;
+ }
+ }
+
+ /* Set final sequence entry's next pointer to NULL */
+ cur->next = NULL;
+
+ if( *p != end )
+ return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+#endif
diff --git a/polarssl/src/library/asn1write.c b/polarssl/src/library/asn1write.c
new file mode 100644
index 0000000..e50c17c
--- /dev/null
+++ b/polarssl/src/library/asn1write.c
@@ -0,0 +1,241 @@
+/*
+ * ASN.1 buffer writing functionality
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ASN1_WRITE_C)
+
+#include "polarssl/asn1write.h"
+
+int asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
+{
+ if( len < 0x80 )
+ {
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = len;
+ return( 1 );
+ }
+
+ if( len <= 0xFF )
+ {
+ if( *p - start < 2 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = len;
+ *--(*p) = 0x81;
+ return( 2 );
+ }
+
+ if( *p - start < 3 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ // We assume we never have lengths larger than 65535 bytes
+ //
+ *--(*p) = len % 256;
+ *--(*p) = ( len / 256 ) % 256;
+ *--(*p) = 0x82;
+
+ return( 3 );
+}
+
+int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
+{
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = tag;
+
+ return( 1 );
+}
+
+int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write the MPI
+ //
+ len = mpi_size( X );
+
+ if( *p - start < (int) len )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ mpi_write_binary( X, *p, len );
+
+ // DER format assumes 2s complement for numbers, so the leftmost bit
+ // should be 0 for positive numbers and 1 for negative numbers.
+ //
+ if ( X->s ==1 && **p & 0x80 )
+ {
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = 0x00;
+ len += 1;
+ }
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
+
+ return( len );
+}
+
+int asn1_write_null( unsigned char **p, unsigned char *start )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write NULL
+ //
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, 0) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_NULL ) );
+
+ return( len );
+}
+
+int asn1_write_oid( unsigned char **p, unsigned char *start, char *oid )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write OID
+ //
+ len = strlen( oid );
+
+ if( *p - start < (int) len )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ memcpy( *p, oid, len );
+
+ ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) );
+
+ return( len );
+}
+
+int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
+ char *algorithm_oid )
+{
+ int ret;
+ size_t null_len = 0;
+ size_t oid_len = 0;
+ size_t len = 0;
+
+ // Write NULL
+ //
+ ASN1_CHK_ADD( null_len, asn1_write_null( p, start ) );
+
+ // Write OID
+ //
+ ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, algorithm_oid ) );
+
+ len = oid_len + null_len;
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + null_len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ return( len );
+}
+
+int asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+ int ret;
+ size_t len = 0;
+
+ // TODO negative values and values larger than 128
+ // DER format assumes 2s complement for numbers, so the leftmost bit
+ // should be 0 for positive numbers and 1 for negative numbers.
+ //
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ len += 1;
+ *--(*p) = val;
+
+ if ( val > 0 && **p & 0x80 )
+ {
+ if( *p - start < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = 0x00;
+ len += 1;
+ }
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
+
+ return( len );
+}
+
+int asn1_write_printable_string( unsigned char **p, unsigned char *start,
+ char *text )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write string
+ //
+ len = strlen( text );
+
+ if( *p - start < (int) len )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ memcpy( *p, text, len );
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) );
+
+ return( len );
+}
+
+int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+ char *text )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write string
+ //
+ len = strlen( text );
+
+ if( *p - start < (int) len )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ memcpy( *p, text, len );
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) );
+
+ return( len );
+}
+
+
+#endif
diff --git a/polarssl/src/library/base64.c b/polarssl/src/library/base64.c
new file mode 100644
index 0000000..8601c94
--- /dev/null
+++ b/polarssl/src/library/base64.c
@@ -0,0 +1,254 @@
+/*
+ * RFC 1521 base64 encoding/decoding
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BASE64_C)
+
+#include "polarssl/base64.h"
+
+static const unsigned char base64_enc_map[64] =
+{
+ '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', '+', '/'
+};
+
+static const unsigned char base64_dec_map[128] =
+{
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
+ 127, 64, 127, 127, 127, 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, 127, 127, 127, 127, 127, 127, 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, 127, 127, 127, 127, 127
+};
+
+/*
+ * Encode a buffer into base64 format
+ */
+int base64_encode( unsigned char *dst, size_t *dlen,
+ const unsigned char *src, size_t slen )
+{
+ size_t i, n;
+ int C1, C2, C3;
+ unsigned char *p;
+
+ if( slen == 0 )
+ return( 0 );
+
+ n = (slen << 3) / 6;
+
+ switch( (slen << 3) - (n * 6) )
+ {
+ case 2: n += 3; break;
+ case 4: n += 2; break;
+ default: break;
+ }
+
+ if( *dlen < n + 1 )
+ {
+ *dlen = n + 1;
+ return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ n = (slen / 3) * 3;
+
+ for( i = 0, p = dst; i < n; i += 3 )
+ {
+ C1 = *src++;
+ C2 = *src++;
+ C3 = *src++;
+
+ *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+ *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+ *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
+ *p++ = base64_enc_map[C3 & 0x3F];
+ }
+
+ if( i < slen )
+ {
+ C1 = *src++;
+ C2 = ((i + 1) < slen) ? *src++ : 0;
+
+ *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+ *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+
+ if( (i + 1) < slen )
+ *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+ else *p++ = '=';
+
+ *p++ = '=';
+ }
+
+ *dlen = p - dst;
+ *p = 0;
+
+ return( 0 );
+}
+
+/*
+ * Decode a base64-formatted buffer
+ */
+int base64_decode( unsigned char *dst, size_t *dlen,
+ const unsigned char *src, size_t slen )
+{
+ size_t i, j, n;
+ unsigned long x;
+ unsigned char *p;
+
+ for( i = j = n = 0; i < slen; i++ )
+ {
+ if( ( slen - i ) >= 2 &&
+ src[i] == '\r' && src[i + 1] == '\n' )
+ continue;
+
+ if( src[i] == '\n' )
+ continue;
+
+ if( src[i] == '=' && ++j > 2 )
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+ if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+ if( base64_dec_map[src[i]] < 64 && j != 0 )
+ return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
+ n++;
+ }
+
+ if( n == 0 )
+ return( 0 );
+
+ n = ((n * 6) + 7) >> 3;
+
+ if( *dlen < n )
+ {
+ *dlen = n;
+ return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+ {
+ if( *src == '\r' || *src == '\n' )
+ continue;
+
+ j -= ( base64_dec_map[*src] == 64 );
+ x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
+
+ if( ++n == 4 )
+ {
+ n = 0;
+ if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+ if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
+ if( j > 2 ) *p++ = (unsigned char)( x );
+ }
+ }
+
+ *dlen = p - dst;
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#include <stdio.h>
+
+static const unsigned char base64_test_dec[64] =
+{
+ 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
+ 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
+ 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
+ 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
+ 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
+ 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
+ 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
+ 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
+};
+
+static const unsigned char base64_test_enc[] =
+ "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
+ "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
+
+/*
+ * Checkup routine
+ */
+int base64_self_test( int verbose )
+{
+ size_t len;
+ unsigned char *src, buffer[128];
+
+ if( verbose != 0 )
+ printf( " Base64 encoding test: " );
+
+ len = sizeof( buffer );
+ src = (unsigned char *) base64_test_dec;
+
+ if( base64_encode( buffer, &len, src, 64 ) != 0 ||
+ memcmp( base64_test_enc, buffer, 88 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n Base64 decoding test: " );
+
+ len = sizeof( buffer );
+ src = (unsigned char *) base64_test_enc;
+
+ if( base64_decode( buffer, &len, src, 88 ) != 0 ||
+ memcmp( base64_test_dec, buffer, 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/bignum.c b/polarssl/src/library/bignum.c
new file mode 100644
index 0000000..0cb9505
--- /dev/null
+++ b/polarssl/src/library/bignum.c
@@ -0,0 +1,2111 @@
+/*
+ * Multi-precision integer library
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This MPI implementation is based on:
+ *
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ * http://www.stillhq.com/extracted/gnupg-api/mpi/
+ * http://math.libtomcrypt.com/files/tommath.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+
+#include "polarssl/bignum.h"
+#include "polarssl/bn_mul.h"
+
+#include <stdlib.h>
+
+#define ciL (sizeof(t_uint)) /* chars in limb */
+#define biL (ciL << 3) /* bits in limb */
+#define biH (ciL << 2) /* half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ */
+#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
+#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+
+/*
+ * Initialize one MPI
+ */
+void mpi_init( mpi *X )
+{
+ if( X == NULL )
+ return;
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Unallocate one MPI
+ */
+void mpi_free( mpi *X )
+{
+ if( X == NULL )
+ return;
+
+ if( X->p != NULL )
+ {
+ memset( X->p, 0, X->n * ciL );
+ free( X->p );
+ }
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mpi_grow( mpi *X, size_t nblimbs )
+{
+ t_uint *p;
+
+ if( nblimbs > POLARSSL_MPI_MAX_LIMBS )
+ return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+ if( X->n < nblimbs )
+ {
+ if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
+ return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+ memset( p, 0, nblimbs * ciL );
+
+ if( X->p != NULL )
+ {
+ memcpy( p, X->p, X->n * ciL );
+ memset( X->p, 0, X->n * ciL );
+ free( X->p );
+ }
+
+ X->n = nblimbs;
+ X->p = p;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mpi_copy( mpi *X, const mpi *Y )
+{
+ int ret;
+ size_t i;
+
+ if( X == Y )
+ return( 0 );
+
+ for( i = Y->n - 1; i > 0; i-- )
+ if( Y->p[i] != 0 )
+ break;
+ i++;
+
+ X->s = Y->s;
+
+ MPI_CHK( mpi_grow( X, i ) );
+
+ memset( X->p, 0, X->n * ciL );
+ memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y )
+{
+ mpi T;
+
+ memcpy( &T, X, sizeof( mpi ) );
+ memcpy( X, Y, sizeof( mpi ) );
+ memcpy( Y, &T, sizeof( mpi ) );
+}
+
+/*
+ * Set value from integer
+ */
+int mpi_lset( mpi *X, t_sint z )
+{
+ int ret;
+
+ MPI_CHK( mpi_grow( X, 1 ) );
+ memset( X->p, 0, X->n * ciL );
+
+ X->p[0] = ( z < 0 ) ? -z : z;
+ X->s = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Get a specific bit
+ */
+int mpi_get_bit( mpi *X, size_t pos )
+{
+ if( X->n * biL <= pos )
+ return( 0 );
+
+ return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
+}
+
+/*
+ * Set a bit to a specific value of 0 or 1
+ */
+int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
+{
+ int ret = 0;
+ size_t off = pos / biL;
+ size_t idx = pos % biL;
+
+ if( val != 0 && val != 1 )
+ return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
+
+ if( X->n * biL <= pos )
+ {
+ if( val == 0 )
+ return ( 0 );
+
+ MPI_CHK( mpi_grow( X, off + 1 ) );
+ }
+
+ X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Return the number of least significant bits
+ */
+size_t mpi_lsb( const mpi *X )
+{
+ size_t i, j, count = 0;
+
+ for( i = 0; i < X->n; i++ )
+ for( j = 0; j < biL; j++, count++ )
+ if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+ return( count );
+
+ return( 0 );
+}
+
+/*
+ * Return the number of most significant bits
+ */
+size_t mpi_msb( const mpi *X )
+{
+ size_t i, j;
+
+ for( i = X->n - 1; i > 0; i-- )
+ if( X->p[i] != 0 )
+ break;
+
+ for( j = biL; j > 0; j-- )
+ if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 )
+ break;
+
+ return( ( i * biL ) + j );
+}
+
+/*
+ * Return the total size in bytes
+ */
+size_t mpi_size( const mpi *X )
+{
+ return( ( mpi_msb( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( t_uint *d, int radix, char c )
+{
+ *d = 255;
+
+ if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+ if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+ if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+ if( *d >= (t_uint) radix )
+ return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
+
+ return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mpi_read_string( mpi *X, int radix, const char *s )
+{
+ int ret;
+ size_t i, j, slen, n;
+ t_uint d;
+ mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &T );
+
+ slen = strlen( s );
+
+ if( radix == 16 )
+ {
+ n = BITS_TO_LIMBS( slen << 2 );
+
+ MPI_CHK( mpi_grow( X, n ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = slen, j = 0; i > 0; i--, j++ )
+ {
+ if( i == 1 && s[i - 1] == '-' )
+ {
+ X->s = -1;
+ break;
+ }
+
+ MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
+ X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = 0; i < slen; i++ )
+ {
+ if( i == 0 && s[i] == '-' )
+ {
+ X->s = -1;
+ continue;
+ }
+
+ MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+ MPI_CHK( mpi_mul_int( &T, X, radix ) );
+
+ if( X->s == 1 )
+ {
+ MPI_CHK( mpi_add_int( X, &T, d ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_int( X, &T, d ) );
+ }
+ }
+ }
+
+cleanup:
+
+ mpi_free( &T );
+
+ return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mpi *X, int radix, char **p )
+{
+ int ret;
+ t_uint r;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ MPI_CHK( mpi_mod_int( &r, X, radix ) );
+ MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
+
+ if( mpi_cmp_int( X, 0 ) != 0 )
+ MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+ if( r < 10 )
+ *(*p)++ = (char)( r + 0x30 );
+ else
+ *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
+{
+ int ret = 0;
+ size_t n;
+ char *p;
+ mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ n = mpi_msb( X );
+ if( radix >= 4 ) n >>= 1;
+ if( radix >= 16 ) n >>= 1;
+ n += 3;
+
+ if( *slen < n )
+ {
+ *slen = n;
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+ }
+
+ p = s;
+ mpi_init( &T );
+
+ if( X->s == -1 )
+ *p++ = '-';
+
+ if( radix == 16 )
+ {
+ int c;
+ size_t i, j, k;
+
+ for( i = X->n, k = 0; i > 0; i-- )
+ {
+ for( j = ciL; j > 0; j-- )
+ {
+ c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
+
+ if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
+ continue;
+
+ p += sprintf( p, "%02X", c );
+ k = 1;
+ }
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_copy( &T, X ) );
+
+ if( T.s == -1 )
+ T.s = 1;
+
+ MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+ }
+
+ *p++ = '\0';
+ *slen = p - s;
+
+cleanup:
+
+ mpi_free( &T );
+
+ return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Read X from an opened file
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin )
+{
+ t_uint d;
+ size_t slen;
+ char *p;
+ /*
+ * Buffer should have space for (short) label and decimal formatted MPI,
+ * newline characters and '\0'
+ */
+ char s[ POLARSSL_MPI_READ_BUFFER_SIZE ];
+
+ memset( s, 0, sizeof( s ) );
+ if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+ return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+
+ slen = strlen( s );
+ if( slen == sizeof( s ) - 2 )
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+ if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+ if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+ p = s + slen;
+ while( --p >= s )
+ if( mpi_get_digit( &d, radix, *p ) != 0 )
+ break;
+
+ return( mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
+{
+ int ret;
+ size_t n, slen, plen;
+ /*
+ * Buffer should have space for minus sign, hexified MPI and '\0'
+ */
+ char s[ 2 * POLARSSL_MPI_MAX_SIZE + 2 ];
+
+ n = sizeof( s );
+ memset( s, 0, n );
+ n -= 2;
+
+ MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) );
+
+ if( p == NULL ) p = "";
+
+ plen = strlen( p );
+ slen = strlen( s );
+ s[slen++] = '\r';
+ s[slen++] = '\n';
+
+ if( fout != NULL )
+ {
+ if( fwrite( p, 1, plen, fout ) != plen ||
+ fwrite( s, 1, slen, fout ) != slen )
+ return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+ }
+ else
+ printf( "%s%s", p, s );
+
+cleanup:
+
+ return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen )
+{
+ int ret;
+ size_t i, j, n;
+
+ for( n = 0; n < buflen; n++ )
+ if( buf[n] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i = buflen, j = 0; i > n; i--, j++ )
+ X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3);
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen )
+{
+ size_t i, j, n;
+
+ n = mpi_size( X );
+
+ if( buflen < n )
+ return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+ memset( buf, 0, buflen );
+
+ for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+ buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+ return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mpi_shift_l( mpi *X, size_t count )
+{
+ int ret;
+ size_t i, v0, t1;
+ t_uint r0 = 0, r1;
+
+ v0 = count / (biL );
+ t1 = count & (biL - 1);
+
+ i = mpi_msb( X ) + count;
+
+ if( X->n * biL < i )
+ MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+ ret = 0;
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = X->n; i > v0; i-- )
+ X->p[i - 1] = X->p[i - v0 - 1];
+
+ for( ; i > 0; i-- )
+ X->p[i - 1] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( t1 > 0 )
+ {
+ for( i = v0; i < X->n; i++ )
+ {
+ r1 = X->p[i] >> (biL - t1);
+ X->p[i] <<= t1;
+ X->p[i] |= r0;
+ r0 = r1;
+ }
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mpi_shift_r( mpi *X, size_t count )
+{
+ size_t i, v0, v1;
+ t_uint r0 = 0, r1;
+
+ v0 = count / biL;
+ v1 = count & (biL - 1);
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = 0; i < X->n - v0; i++ )
+ X->p[i] = X->p[i + v0];
+
+ for( ; i < X->n; i++ )
+ X->p[i] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( v1 > 0 )
+ {
+ for( i = X->n; i > 0; i-- )
+ {
+ r1 = X->p[i - 1] << (biL - v1);
+ X->p[i - 1] >>= v1;
+ X->p[i - 1] |= r0;
+ r0 = r1;
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y )
+{
+ size_t i, j;
+
+ for( i = X->n; i > 0; i-- )
+ if( X->p[i - 1] != 0 )
+ break;
+
+ for( j = Y->n; j > 0; j-- )
+ if( Y->p[j - 1] != 0 )
+ break;
+
+ if( i == 0 && j == 0 )
+ return( 0 );
+
+ if( i > j ) return( 1 );
+ if( j > i ) return( -1 );
+
+ for( ; i > 0; i-- )
+ {
+ if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
+ if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y )
+{
+ size_t i, j;
+
+ for( i = X->n; i > 0; i-- )
+ if( X->p[i - 1] != 0 )
+ break;
+
+ for( j = Y->n; j > 0; j-- )
+ if( Y->p[j - 1] != 0 )
+ break;
+
+ if( i == 0 && j == 0 )
+ return( 0 );
+
+ if( i > j ) return( X->s );
+ if( j > i ) return( -Y->s );
+
+ if( X->s > 0 && Y->s < 0 ) return( 1 );
+ if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+ for( ; i > 0; i-- )
+ {
+ if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
+ if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_int( const mpi *X, t_sint z )
+{
+ mpi Y;
+ t_uint p[1];
+
+ *p = ( z < 0 ) ? -z : z;
+ Y.s = ( z < 0 ) ? -1 : 1;
+ Y.n = 1;
+ Y.p = p;
+
+ return( mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B| (HAC 14.7)
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, j;
+ t_uint *o, *p, c;
+
+ if( X == B )
+ {
+ const mpi *T = A; A = X; B = T;
+ }
+
+ if( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned additions.
+ */
+ X->s = 1;
+
+ for( j = B->n; j > 0; j-- )
+ if( B->p[j - 1] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, j ) );
+
+ o = B->p; p = X->p; c = 0;
+
+ for( i = 0; i < j; i++, o++, p++ )
+ {
+ *p += c; c = ( *p < c );
+ *p += *o; c += ( *p < *o );
+ }
+
+ while( c != 0 )
+ {
+ if( i >= X->n )
+ {
+ MPI_CHK( mpi_grow( X, i + 1 ) );
+ p = X->p + i;
+ }
+
+ *p += c; c = ( *p < c ); i++;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Helper for mpi substraction
+ */
+static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d )
+{
+ size_t i;
+ t_uint c, z;
+
+ for( i = c = 0; i < n; i++, s++, d++ )
+ {
+ z = ( *d < c ); *d -= c;
+ c = ( *d < *s ) + z; *d -= *s;
+ }
+
+ while( c != 0 )
+ {
+ z = ( *d < c ); *d -= c;
+ c = z; i++; d++;
+ }
+}
+
+/*
+ * Unsigned substraction: X = |A| - |B| (HAC 14.9)
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
+{
+ mpi TB;
+ int ret;
+ size_t n;
+
+ if( mpi_cmp_abs( A, B ) < 0 )
+ return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
+
+ mpi_init( &TB );
+
+ if( X == B )
+ {
+ MPI_CHK( mpi_copy( &TB, B ) );
+ B = &TB;
+ }
+
+ if( X != A )
+ MPI_CHK( mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned substractions.
+ */
+ X->s = 1;
+
+ ret = 0;
+
+ for( n = B->n; n > 0; n-- )
+ if( B->p[n - 1] != 0 )
+ break;
+
+ mpi_sub_hlp( n, B->p, X->p );
+
+cleanup:
+
+ mpi_free( &TB );
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s < 0 )
+ {
+ if( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed substraction: X = A - B
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s > 0 )
+ {
+ if( mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mpi_add_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed substraction: X = A - b
+ */
+int mpi_sub_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mpi multiplication
+ */
+static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
+{
+ t_uint c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_HUIT
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#else
+ for( ; i >= 16; i -= 16 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#endif
+
+ t++;
+
+ do {
+ *d += c; c = ( *d < c ); d++;
+ }
+ while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B (HAC 14.12)
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, j;
+ mpi TA, TB;
+
+ mpi_init( &TA ); mpi_init( &TB );
+
+ if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
+ if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
+
+ for( i = A->n; i > 0; i-- )
+ if( A->p[i - 1] != 0 )
+ break;
+
+ for( j = B->n; j > 0; j-- )
+ if( B->p[j - 1] != 0 )
+ break;
+
+ MPI_CHK( mpi_grow( X, i + j ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ for( i++; j > 0; j-- )
+ mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
+
+ X->s = A->s * B->s;
+
+cleanup:
+
+ mpi_free( &TB ); mpi_free( &TA );
+
+ return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ _B.s = 1;
+ _B.n = 1;
+ _B.p = p;
+ p[0] = b;
+
+ return( mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Division by mpi: A = Q * B + R (HAC 14.20)
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t i, n, t, k;
+ mpi X, Y, Z, T1, T2;
+
+ if( mpi_cmp_int( B, 0 ) == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
+ mpi_init( &T1 ); mpi_init( &T2 );
+
+ if( mpi_cmp_abs( A, B ) < 0 )
+ {
+ if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
+ if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
+ return( 0 );
+ }
+
+ MPI_CHK( mpi_copy( &X, A ) );
+ MPI_CHK( mpi_copy( &Y, B ) );
+ X.s = Y.s = 1;
+
+ MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
+ MPI_CHK( mpi_lset( &Z, 0 ) );
+ MPI_CHK( mpi_grow( &T1, 2 ) );
+ MPI_CHK( mpi_grow( &T2, 3 ) );
+
+ k = mpi_msb( &Y ) % biL;
+ if( k < biL - 1 )
+ {
+ k = biL - 1 - k;
+ MPI_CHK( mpi_shift_l( &X, k ) );
+ MPI_CHK( mpi_shift_l( &Y, k ) );
+ }
+ else k = 0;
+
+ n = X.n - 1;
+ t = Y.n - 1;
+ mpi_shift_l( &Y, biL * (n - t) );
+
+ while( mpi_cmp_mpi( &X, &Y ) >= 0 )
+ {
+ Z.p[n - t]++;
+ mpi_sub_mpi( &X, &X, &Y );
+ }
+ mpi_shift_r( &Y, biL * (n - t) );
+
+ for( i = n; i > t ; i-- )
+ {
+ if( X.p[i] >= Y.p[t] )
+ Z.p[i - t - 1] = ~0;
+ else
+ {
+#if defined(POLARSSL_HAVE_LONGLONG)
+ t_udbl r;
+
+ r = (t_udbl) X.p[i] << biL;
+ r |= (t_udbl) X.p[i - 1];
+ r /= Y.p[t];
+ if( r > ((t_udbl) 1 << biL) - 1)
+ r = ((t_udbl) 1 << biL) - 1;
+
+ Z.p[i - t - 1] = (t_uint) r;
+#else
+ /*
+ * __udiv_qrnnd_c, from gmp/longlong.h
+ */
+ t_uint q0, q1, r0, r1;
+ t_uint d0, d1, d, m;
+
+ d = Y.p[t];
+ d0 = ( d << biH ) >> biH;
+ d1 = ( d >> biH );
+
+ q1 = X.p[i] / d1;
+ r1 = X.p[i] - d1 * q1;
+ r1 <<= biH;
+ r1 |= ( X.p[i - 1] >> biH );
+
+ m = q1 * d0;
+ if( r1 < m )
+ {
+ q1--, r1 += d;
+ while( r1 >= d && r1 < m )
+ q1--, r1 += d;
+ }
+ r1 -= m;
+
+ q0 = r1 / d1;
+ r0 = r1 - d1 * q0;
+ r0 <<= biH;
+ r0 |= ( X.p[i - 1] << biH ) >> biH;
+
+ m = q0 * d0;
+ if( r0 < m )
+ {
+ q0--, r0 += d;
+ while( r0 >= d && r0 < m )
+ q0--, r0 += d;
+ }
+ r0 -= m;
+
+ Z.p[i - t - 1] = ( q1 << biH ) | q0;
+#endif
+ }
+
+ Z.p[i - t - 1]++;
+ do
+ {
+ Z.p[i - t - 1]--;
+
+ MPI_CHK( mpi_lset( &T1, 0 ) );
+ T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+ T1.p[1] = Y.p[t];
+ MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+ MPI_CHK( mpi_lset( &T2, 0 ) );
+ T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+ T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+ T2.p[2] = X.p[i];
+ }
+ while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+ MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
+
+ if( mpi_cmp_int( &X, 0 ) < 0 )
+ {
+ MPI_CHK( mpi_copy( &T1, &Y ) );
+ MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+ MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
+ Z.p[i - t - 1]--;
+ }
+ }
+
+ if( Q != NULL )
+ {
+ mpi_copy( Q, &Z );
+ Q->s = A->s * B->s;
+ }
+
+ if( R != NULL )
+ {
+ mpi_shift_r( &X, k );
+ mpi_copy( R, &X );
+
+ R->s = A->s;
+ if( mpi_cmp_int( R, 0 ) == 0 )
+ R->s = 1;
+ }
+
+cleanup:
+
+ mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
+ mpi_free( &T1 ); mpi_free( &T2 );
+
+ return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ *
+ * Returns 0 if successful
+ * 1 if memory allocation failed
+ * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
+{
+ mpi _B;
+ t_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
+{
+ int ret;
+
+ if( mpi_cmp_int( B, 0 ) < 0 )
+ return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+ MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
+
+ while( mpi_cmp_int( R, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( R, R, B ) );
+
+ while( mpi_cmp_mpi( R, B ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
+{
+ size_t i;
+ t_uint x, y, z;
+
+ if( b == 0 )
+ return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+ if( b < 0 )
+ return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+ /*
+ * handle trivial cases
+ */
+ if( b == 1 )
+ {
+ *r = 0;
+ return( 0 );
+ }
+
+ if( b == 2 )
+ {
+ *r = A->p[0] & 1;
+ return( 0 );
+ }
+
+ /*
+ * general case
+ */
+ for( i = A->n, y = 0; i > 0; i-- )
+ {
+ x = A->p[i - 1];
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+
+ x <<= biH;
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+ }
+
+ /*
+ * If A is negative, then the current y represents a negative value.
+ * Flipping it to the positive side.
+ */
+ if( A->s < 0 && y != 0 )
+ y = b - y;
+
+ *r = y;
+
+ return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( t_uint *mm, const mpi *N )
+{
+ t_uint x, m0 = N->p[0];
+
+ x = m0;
+ x += ( ( m0 + 2 ) & 4 ) << 1;
+ x *= ( 2 - ( m0 * x ) );
+
+ if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
+ if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
+ if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
+
+ *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
+ */
+static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
+{
+ size_t i, n, m;
+ t_uint u0, u1, *d;
+
+ memset( T->p, 0, T->n * ciL );
+
+ d = T->p;
+ n = N->n;
+ m = ( B->n < n ) ? B->n : n;
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * T = (T + u0*B + u1*N) / 2^biL
+ */
+ u0 = A->p[i];
+ u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+ mpi_mul_hlp( m, B->p, d, u0 );
+ mpi_mul_hlp( n, N->p, d, u1 );
+
+ *d++ = u0; d[n + 1] = 0;
+ }
+
+ memcpy( A->p, d, (n + 1) * ciL );
+
+ if( mpi_cmp_abs( A, N ) >= 0 )
+ mpi_sub_hlp( n, N->p, A->p );
+ else
+ /* prevent timing attacks */
+ mpi_sub_hlp( n, A->p, T->p );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T )
+{
+ t_uint z = 1;
+ mpi U;
+
+ U.n = U.s = z;
+ U.p = &z;
+
+ mpi_montmul( A, &U, N, mm, T );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
+{
+ int ret;
+ size_t wbits, wsize, one = 1;
+ size_t i, j, nblimbs;
+ size_t bufsize, nbits;
+ t_uint ei, mm, state;
+ mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ];
+
+ if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ /*
+ * Init temps and window size
+ */
+ mpi_montg_init( &mm, N );
+ mpi_init( &RR ); mpi_init( &T );
+ memset( W, 0, sizeof( W ) );
+
+ i = mpi_msb( E );
+
+ wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+ ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
+
+ if( wsize > POLARSSL_MPI_WINDOW_SIZE )
+ wsize = POLARSSL_MPI_WINDOW_SIZE;
+
+ j = N->n + 1;
+ MPI_CHK( mpi_grow( X, j ) );
+ MPI_CHK( mpi_grow( &W[1], j ) );
+ MPI_CHK( mpi_grow( &T, j * 2 ) );
+
+ /*
+ * If 1st call, pre-compute R^2 mod N
+ */
+ if( _RR == NULL || _RR->p == NULL )
+ {
+ MPI_CHK( mpi_lset( &RR, 1 ) );
+ MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
+ MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
+
+ if( _RR != NULL )
+ memcpy( _RR, &RR, sizeof( mpi ) );
+ }
+ else
+ memcpy( &RR, _RR, sizeof( mpi ) );
+
+ /*
+ * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+ */
+ if( mpi_cmp_mpi( A, N ) >= 0 )
+ mpi_mod_mpi( &W[1], A, N );
+ else mpi_copy( &W[1], A );
+
+ mpi_montmul( &W[1], &RR, N, mm, &T );
+
+ /*
+ * X = R^2 * R^-1 mod N = R mod N
+ */
+ MPI_CHK( mpi_copy( X, &RR ) );
+ mpi_montred( X, N, mm, &T );
+
+ if( wsize > 1 )
+ {
+ /*
+ * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+ */
+ j = one << (wsize - 1);
+
+ MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[j], &W[1] ) );
+
+ for( i = 0; i < wsize - 1; i++ )
+ mpi_montmul( &W[j], &W[j], N, mm, &T );
+
+ /*
+ * W[i] = W[i - 1] * W[1]
+ */
+ for( i = j + 1; i < (one << wsize); i++ )
+ {
+ MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
+ MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
+
+ mpi_montmul( &W[i], &W[1], N, mm, &T );
+ }
+ }
+
+ nblimbs = E->n;
+ bufsize = 0;
+ nbits = 0;
+ wbits = 0;
+ state = 0;
+
+ while( 1 )
+ {
+ if( bufsize == 0 )
+ {
+ if( nblimbs-- == 0 )
+ break;
+
+ bufsize = sizeof( t_uint ) << 3;
+ }
+
+ bufsize--;
+
+ ei = (E->p[nblimbs] >> bufsize) & 1;
+
+ /*
+ * skip leading 0s
+ */
+ if( ei == 0 && state == 0 )
+ continue;
+
+ if( ei == 0 && state == 1 )
+ {
+ /*
+ * out of window, square X
+ */
+ mpi_montmul( X, X, N, mm, &T );
+ continue;
+ }
+
+ /*
+ * add ei to current window
+ */
+ state = 2;
+
+ nbits++;
+ wbits |= (ei << (wsize - nbits));
+
+ if( nbits == wsize )
+ {
+ /*
+ * X = X^wsize R^-1 mod N
+ */
+ for( i = 0; i < wsize; i++ )
+ mpi_montmul( X, X, N, mm, &T );
+
+ /*
+ * X = X * W[wbits] R^-1 mod N
+ */
+ mpi_montmul( X, &W[wbits], N, mm, &T );
+
+ state--;
+ nbits = 0;
+ wbits = 0;
+ }
+ }
+
+ /*
+ * process the remaining bits
+ */
+ for( i = 0; i < nbits; i++ )
+ {
+ mpi_montmul( X, X, N, mm, &T );
+
+ wbits <<= 1;
+
+ if( (wbits & (one << wsize)) != 0 )
+ mpi_montmul( X, &W[1], N, mm, &T );
+ }
+
+ /*
+ * X = A^E * R * R^-1 mod N = A^E mod N
+ */
+ mpi_montred( X, N, mm, &T );
+
+cleanup:
+
+ for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
+ mpi_free( &W[i] );
+
+ mpi_free( &W[1] ); mpi_free( &T );
+
+ if( _RR == NULL )
+ mpi_free( &RR );
+
+ return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
+{
+ int ret;
+ size_t lz, lzt;
+ mpi TG, TA, TB;
+
+ mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB );
+
+ MPI_CHK( mpi_copy( &TA, A ) );
+ MPI_CHK( mpi_copy( &TB, B ) );
+
+ lz = mpi_lsb( &TA );
+ lzt = mpi_lsb( &TB );
+
+ if ( lzt < lz )
+ lz = lzt;
+
+ MPI_CHK( mpi_shift_r( &TA, lz ) );
+ MPI_CHK( mpi_shift_r( &TB, lz ) );
+
+ TA.s = TB.s = 1;
+
+ while( mpi_cmp_int( &TA, 0 ) != 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
+ MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
+
+ if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
+ MPI_CHK( mpi_shift_r( &TA, 1 ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
+ MPI_CHK( mpi_shift_r( &TB, 1 ) );
+ }
+ }
+
+ MPI_CHK( mpi_shift_l( &TB, lz ) );
+ MPI_CHK( mpi_copy( G, &TB ) );
+
+cleanup:
+
+ mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB );
+
+ return( ret );
+}
+
+int mpi_fill_random( mpi *X, size_t size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+
+ MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
+ MPI_CHK( mpi_lset( X, 0 ) );
+
+ MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
+
+cleanup:
+ return( ret );
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
+{
+ int ret;
+ mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+ if( mpi_cmp_int( N, 0 ) <= 0 )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 );
+ mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV );
+ mpi_init( &V1 ); mpi_init( &V2 );
+
+ MPI_CHK( mpi_gcd( &G, A, N ) );
+
+ if( mpi_cmp_int( &G, 1 ) != 0 )
+ {
+ ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+ goto cleanup;
+ }
+
+ MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
+ MPI_CHK( mpi_copy( &TU, &TA ) );
+ MPI_CHK( mpi_copy( &TB, N ) );
+ MPI_CHK( mpi_copy( &TV, N ) );
+
+ MPI_CHK( mpi_lset( &U1, 1 ) );
+ MPI_CHK( mpi_lset( &U2, 0 ) );
+ MPI_CHK( mpi_lset( &V1, 0 ) );
+ MPI_CHK( mpi_lset( &V2, 1 ) );
+
+ do
+ {
+ while( ( TU.p[0] & 1 ) == 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TU, 1 ) );
+
+ if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+ {
+ MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
+ MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
+ }
+
+ MPI_CHK( mpi_shift_r( &U1, 1 ) );
+ MPI_CHK( mpi_shift_r( &U2, 1 ) );
+ }
+
+ while( ( TV.p[0] & 1 ) == 0 )
+ {
+ MPI_CHK( mpi_shift_r( &TV, 1 ) );
+
+ if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+ {
+ MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
+ MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
+ }
+
+ MPI_CHK( mpi_shift_r( &V1, 1 ) );
+ MPI_CHK( mpi_shift_r( &V2, 1 ) );
+ }
+
+ if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
+ {
+ MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
+ MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
+ MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
+ MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
+ MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
+ }
+ }
+ while( mpi_cmp_int( &TU, 0 ) != 0 );
+
+ while( mpi_cmp_int( &V1, 0 ) < 0 )
+ MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
+
+ while( mpi_cmp_mpi( &V1, N ) >= 0 )
+ MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
+
+ MPI_CHK( mpi_copy( X, &V1 ) );
+
+cleanup:
+
+ mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 );
+ mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV );
+ mpi_free( &V1 ); mpi_free( &V2 );
+
+ return( ret );
+}
+
+static const int small_prime[] =
+{
+ 3, 5, 7, 11, 13, 17, 19, 23,
+ 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97,
+ 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179,
+ 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269,
+ 271, 277, 281, 283, 293, 307, 311, 313,
+ 317, 331, 337, 347, 349, 353, 359, 367,
+ 373, 379, 383, 389, 397, 401, 409, 419,
+ 421, 431, 433, 439, 443, 449, 457, 461,
+ 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571,
+ 577, 587, 593, 599, 601, 607, 613, 617,
+ 619, 631, 641, 643, 647, 653, 659, 661,
+ 673, 677, 683, 691, 701, 709, 719, 727,
+ 733, 739, 743, 751, 757, 761, 769, 773,
+ 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883,
+ 887, 907, 911, 919, 929, 937, 941, 947,
+ 953, 967, 971, 977, 983, 991, 997, -103
+};
+
+/*
+ * Miller-Rabin primality test (HAC 4.24)
+ */
+int mpi_is_prime( mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret, xs;
+ size_t i, j, n, s;
+ mpi W, R, T, A, RR;
+
+ if( mpi_cmp_int( X, 0 ) == 0 ||
+ mpi_cmp_int( X, 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+ if( mpi_cmp_int( X, 2 ) == 0 )
+ return( 0 );
+
+ mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
+ mpi_init( &RR );
+
+ xs = X->s; X->s = 1;
+
+ /*
+ * test trivial factors first
+ */
+ if( ( X->p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+ for( i = 0; small_prime[i] > 0; i++ )
+ {
+ t_uint r;
+
+ if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
+ return( 0 );
+
+ MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
+
+ if( r == 0 )
+ return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+ }
+
+ /*
+ * W = |X| - 1
+ * R = W >> lsb( W )
+ */
+ MPI_CHK( mpi_sub_int( &W, X, 1 ) );
+ s = mpi_lsb( &W );
+ MPI_CHK( mpi_copy( &R, &W ) );
+ MPI_CHK( mpi_shift_r( &R, s ) );
+
+ i = mpi_msb( X );
+ /*
+ * HAC, table 4.4
+ */
+ n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
+ ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
+ ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * pick a random A, 1 < A < |X| - 1
+ */
+ MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+
+ if( mpi_cmp_mpi( &A, &W ) >= 0 )
+ {
+ j = mpi_msb( &A ) - mpi_msb( &W );
+ MPI_CHK( mpi_shift_r( &A, j + 1 ) );
+ }
+ A.p[0] |= 3;
+
+ /*
+ * A = A^R mod |X|
+ */
+ MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+ if( mpi_cmp_mpi( &A, &W ) == 0 ||
+ mpi_cmp_int( &A, 1 ) == 0 )
+ continue;
+
+ j = 1;
+ while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
+ {
+ /*
+ * A = A * A mod |X|
+ */
+ MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
+ MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
+
+ if( mpi_cmp_int( &A, 1 ) == 0 )
+ break;
+
+ j++;
+ }
+
+ /*
+ * not prime if A != |X| - 1 or A == 1
+ */
+ if( mpi_cmp_mpi( &A, &W ) != 0 ||
+ mpi_cmp_int( &A, 1 ) == 0 )
+ {
+ ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+ break;
+ }
+ }
+
+cleanup:
+
+ X->s = xs;
+
+ mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
+ mpi_free( &RR );
+
+ return( ret );
+}
+
+/*
+ * Prime number generation
+ */
+int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ size_t k, n;
+ mpi Y;
+
+ if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
+ return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+ mpi_init( &Y );
+
+ n = BITS_TO_LIMBS( nbits );
+
+ MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
+
+ k = mpi_msb( X );
+ if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
+ if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
+
+ X->p[0] |= 3;
+
+ if( dh_flag == 0 )
+ {
+ while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
+ {
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ MPI_CHK( mpi_add_int( X, X, 2 ) );
+ }
+ }
+ else
+ {
+ MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
+ MPI_CHK( mpi_shift_r( &Y, 1 ) );
+
+ while( 1 )
+ {
+ if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
+ {
+ if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
+ break;
+
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+ }
+
+ if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ MPI_CHK( mpi_add_int( &Y, X, 1 ) );
+ MPI_CHK( mpi_add_int( X, X, 2 ) );
+ MPI_CHK( mpi_shift_r( &Y, 1 ) );
+ }
+ }
+
+cleanup:
+
+ mpi_free( &Y );
+
+ return( ret );
+}
+
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+
+#define GCD_PAIR_COUNT 3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+ { 693, 609, 21 },
+ { 1764, 868, 28 },
+ { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mpi_self_test( int verbose )
+{
+ int ret, i;
+ mpi A, E, N, X, Y, U, V;
+
+ mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X );
+ mpi_init( &Y ); mpi_init( &U ); mpi_init( &V );
+
+ MPI_CHK( mpi_read_string( &A, 16,
+ "EFE021C2645FD1DC586E69184AF4A31E" \
+ "D5F53E93B5F123FA41680867BA110131" \
+ "944FE7952E2517337780CB0DB80E61AA" \
+ "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+ MPI_CHK( mpi_read_string( &E, 16,
+ "B2E7EFD37075B9F03FF989C7C5051C20" \
+ "34D2A323810251127E7BF8625A4F49A5" \
+ "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+ "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+ MPI_CHK( mpi_read_string( &N, 16,
+ "0066A198186C18C10B2F5ED9B522752A" \
+ "9830B69916E535C8F047518A889A43A5" \
+ "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+ MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "602AB7ECA597A3D6B56FF9829A5E8B85" \
+ "9E857EA95A03512E2BAE7391688D264A" \
+ "A5663B0341DB9CCFD2C4C5F421FEC814" \
+ "8001B72E848A38CAE1C65F78E56ABDEF" \
+ "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+ "ECF677152EF804370C1A305CAF3B5BF1" \
+ "30879B56C61DE584A0F53A2447A51E" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #1 (mul_mpi): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "256567336059E52CAE22925474705F39A94" ) );
+
+ MPI_CHK( mpi_read_string( &V, 16,
+ "6613F26162223DF488E9CD48CC132C7A" \
+ "0AC93C701B001B092E4E5B9F73BCD27B" \
+ "9EE50D0657C77F374E903CDFA4C642" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #2 (div_mpi): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 ||
+ mpi_cmp_mpi( &Y, &V ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "36E139AEA55215609D2816998ED020BB" \
+ "BD96C37890F65171D948E9BC7CBAA4D9" \
+ "325D24D6A3C12710F10A09FA08AB87" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #3 (exp_mod): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+#if defined(POLARSSL_GENPRIME)
+ MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
+
+ MPI_CHK( mpi_read_string( &U, 16,
+ "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+ "C3DBA76456363A10869622EAC2DD84EC" \
+ "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+ if( verbose != 0 )
+ printf( " MPI test #4 (inv_mod): " );
+
+ if( mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+#endif
+
+ if( verbose != 0 )
+ printf( " MPI test #5 (simple gcd): " );
+
+ for ( i = 0; i < GCD_PAIR_COUNT; i++)
+ {
+ MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
+ MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+ MPI_CHK( mpi_gcd( &A, &X, &Y ) );
+
+ if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed at %d\n", i );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+cleanup:
+
+ if( ret != 0 && verbose != 0 )
+ printf( "Unexpected error, return code = %08X\n", ret );
+
+ mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
+ mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( ret );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/camellia.c b/polarssl/src/library/camellia.c
new file mode 100644
index 0000000..34b8f29
--- /dev/null
+++ b/polarssl/src/library/camellia.c
@@ -0,0 +1,1032 @@
+/*
+ * Camellia implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The Camellia block cipher was designed by NTT and Mitsubishi Electric
+ * Corporation.
+ *
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+#include "polarssl/camellia.h"
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+static const unsigned char SIGMA_CHARS[6][8] =
+{
+ { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
+ { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 },
+ { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe },
+ { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c },
+ { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d },
+ { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd }
+};
+
+#if defined(POLARSSL_CAMELLIA_SMALL_MEMORY)
+
+static const unsigned char FSb[256] =
+{
+ 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
+ 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
+ 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
+ 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77,
+ 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
+ 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215,
+ 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
+ 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80,
+ 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
+ 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148,
+ 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226,
+ 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
+ 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
+ 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
+ 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
+ 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
+#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
+#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
+
+#else
+
+static const unsigned char FSb[256] =
+{
+ 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65,
+ 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189,
+ 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26,
+ 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77,
+ 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153,
+ 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215,
+ 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,
+ 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80,
+ 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210,
+ 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148,
+ 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226,
+ 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46,
+ 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89,
+ 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,
+ 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164,
+ 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158
+};
+
+static const unsigned char FSb2[256] =
+{
+ 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130,
+ 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123,
+ 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52,
+ 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154,
+ 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51,
+ 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175,
+ 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68,
+ 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160,
+ 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165,
+ 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41,
+ 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197,
+ 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92,
+ 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178,
+ 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245,
+ 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73,
+ 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61
+};
+
+static const unsigned char FSb3[256] =
+{
+ 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160,
+ 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222,
+ 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13,
+ 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166,
+ 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204,
+ 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235,
+ 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17,
+ 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40,
+ 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105,
+ 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74,
+ 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
+ 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23,
+ 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172,
+ 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125,
+ 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82,
+ 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79
+};
+
+static const unsigned char FSb4[256] =
+{
+ 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146,
+ 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108,
+ 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4,
+ 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105,
+ 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221,
+ 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99,
+ 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141,
+ 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128,
+ 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189,
+ 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77,
+ 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215,
+ 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80,
+ 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148,
+ 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46,
+ 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250,
+ 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) FSb2[(n)]
+#define SBOX3(n) FSb3[(n)]
+#define SBOX4(n) FSb4[(n)]
+
+#endif
+
+static const unsigned char shifts[2][4][4] =
+{
+ {
+ { 1, 1, 1, 1 }, /* KL */
+ { 0, 0, 0, 0 }, /* KR */
+ { 1, 1, 1, 1 }, /* KA */
+ { 0, 0, 0, 0 } /* KB */
+ },
+ {
+ { 1, 0, 1, 1 }, /* KL */
+ { 1, 1, 0, 1 }, /* KR */
+ { 1, 1, 1, 0 }, /* KA */
+ { 1, 1, 0, 1 } /* KB */
+ }
+};
+
+static const signed char indexes[2][4][20] =
+{
+ {
+ { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39,
+ 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */
+ { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17,
+ 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */
+ },
+ {
+ { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1,
+ -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
+ { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17,
+ 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */
+ { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,
+ 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */
+ { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21,
+ 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */
+ }
+};
+
+static const signed char transposes[2][20] =
+{
+ {
+ 21, 22, 23, 20,
+ -1, -1, -1, -1,
+ 18, 19, 16, 17,
+ 11, 8, 9, 10,
+ 15, 12, 13, 14
+ },
+ {
+ 25, 26, 27, 24,
+ 29, 30, 31, 28,
+ 18, 19, 16, 17,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1
+ }
+};
+
+/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */
+#define ROTL(DEST, SRC, SHIFT) \
+{ \
+ (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \
+ (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \
+ (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \
+ (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \
+}
+
+#define FL(XL, XR, KL, KR) \
+{ \
+ (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \
+ (XL) = ((XR) | (KR)) ^ (XL); \
+}
+
+#define FLInv(YL, YR, KL, KR) \
+{ \
+ (YL) = ((YR) | (KR)) ^ (YL); \
+ (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \
+}
+
+#define SHIFT_AND_PLACE(INDEX, OFFSET) \
+{ \
+ TK[0] = KC[(OFFSET) * 4 + 0]; \
+ TK[1] = KC[(OFFSET) * 4 + 1]; \
+ TK[2] = KC[(OFFSET) * 4 + 2]; \
+ TK[3] = KC[(OFFSET) * 4 + 3]; \
+ \
+ for ( i = 1; i <= 4; i++ ) \
+ if (shifts[(INDEX)][(OFFSET)][i -1]) \
+ ROTL(TK + i * 4, TK, (15 * i) % 32); \
+ \
+ for ( i = 0; i < 20; i++ ) \
+ if (indexes[(INDEX)][(OFFSET)][i] != -1) { \
+ RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \
+ } \
+}
+
+static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2])
+{
+ uint32_t I0, I1;
+ I0 = x[0] ^ k[0];
+ I1 = x[1] ^ k[1];
+
+ I0 = (SBOX1((I0 >> 24) & 0xFF) << 24) |
+ (SBOX2((I0 >> 16) & 0xFF) << 16) |
+ (SBOX3((I0 >> 8) & 0xFF) << 8) |
+ (SBOX4((I0 ) & 0xFF) );
+ I1 = (SBOX2((I1 >> 24) & 0xFF) << 24) |
+ (SBOX3((I1 >> 16) & 0xFF) << 16) |
+ (SBOX4((I1 >> 8) & 0xFF) << 8) |
+ (SBOX1((I1 ) & 0xFF) );
+
+ I0 ^= (I1 << 8) | (I1 >> 24);
+ I1 ^= (I0 << 16) | (I0 >> 16);
+ I0 ^= (I1 >> 8) | (I1 << 24);
+ I1 ^= (I0 >> 8) | (I0 << 24);
+
+ z[0] ^= I1;
+ z[1] ^= I0;
+}
+
+/*
+ * Camellia key schedule (encryption)
+ */
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int idx;
+ size_t i;
+ uint32_t *RK;
+ unsigned char t[64];
+ uint32_t SIGMA[6][2];
+ uint32_t KC[16];
+ uint32_t TK[20];
+
+ RK = ctx->rk;
+
+ memset(t, 0, 64);
+ memset(RK, 0, sizeof(ctx->rk));
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 3; idx = 0; break;
+ case 192:
+ case 256: ctx->nr = 4; idx = 1; break;
+ default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+ }
+
+ for( i = 0; i < keysize / 8; ++i)
+ t[i] = key[i];
+
+ if (keysize == 192) {
+ for (i = 0; i < 8; i++)
+ t[24 + i] = ~t[16 + i];
+ }
+
+ /*
+ * Prepare SIGMA values
+ */
+ for (i = 0; i < 6; i++) {
+ GET_ULONG_BE(SIGMA[i][0], SIGMA_CHARS[i], 0);
+ GET_ULONG_BE(SIGMA[i][1], SIGMA_CHARS[i], 4);
+ }
+
+ /*
+ * Key storage in KC
+ * Order: KL, KR, KA, KB
+ */
+ memset(KC, 0, sizeof(KC));
+
+ /* Store KL, KR */
+ for (i = 0; i < 8; i++)
+ GET_ULONG_BE(KC[i], t, i * 4);
+
+ /* Generate KA */
+ for( i = 0; i < 4; ++i)
+ KC[8 + i] = KC[i] ^ KC[4 + i];
+
+ camellia_feistel(KC + 8, SIGMA[0], KC + 10);
+ camellia_feistel(KC + 10, SIGMA[1], KC + 8);
+
+ for( i = 0; i < 4; ++i)
+ KC[8 + i] ^= KC[i];
+
+ camellia_feistel(KC + 8, SIGMA[2], KC + 10);
+ camellia_feistel(KC + 10, SIGMA[3], KC + 8);
+
+ if (keysize > 128) {
+ /* Generate KB */
+ for( i = 0; i < 4; ++i)
+ KC[12 + i] = KC[4 + i] ^ KC[8 + i];
+
+ camellia_feistel(KC + 12, SIGMA[4], KC + 14);
+ camellia_feistel(KC + 14, SIGMA[5], KC + 12);
+ }
+
+ /*
+ * Generating subkeys
+ */
+
+ /* Manipulating KL */
+ SHIFT_AND_PLACE(idx, 0);
+
+ /* Manipulating KR */
+ if (keysize > 128) {
+ SHIFT_AND_PLACE(idx, 1);
+ }
+
+ /* Manipulating KA */
+ SHIFT_AND_PLACE(idx, 2);
+
+ /* Manipulating KB */
+ if (keysize > 128) {
+ SHIFT_AND_PLACE(idx, 3);
+ }
+
+ /* Do transpositions */
+ for ( i = 0; i < 20; i++ ) {
+ if (transposes[idx][i] != -1) {
+ RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Camellia key schedule (decryption)
+ */
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int idx;
+ size_t i;
+ camellia_context cty;
+ uint32_t *RK;
+ uint32_t *SK;
+ int ret;
+
+ switch( keysize )
+ {
+ case 128: ctx->nr = 3; idx = 0; break;
+ case 192:
+ case 256: ctx->nr = 4; idx = 1; break;
+ default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+ }
+
+ RK = ctx->rk;
+
+ ret = camellia_setkey_enc(&cty, key, keysize);
+ if( ret != 0 )
+ return( ret );
+
+ SK = cty.rk + 24 * 2 + 8 * idx * 2;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4)
+ {
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ }
+
+ SK -= 2;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ memset( &cty, 0, sizeof( camellia_context ) );
+
+ return( 0 );
+}
+
+/*
+ * Camellia-ECB block encryption/decryption
+ */
+int camellia_crypt_ecb( camellia_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int NR;
+ uint32_t *RK, X[4];
+
+ ( (void) mode );
+
+ NR = ctx->nr;
+ RK = ctx->rk;
+
+ GET_ULONG_BE( X[0], input, 0 );
+ GET_ULONG_BE( X[1], input, 4 );
+ GET_ULONG_BE( X[2], input, 8 );
+ GET_ULONG_BE( X[3], input, 12 );
+
+ X[0] ^= *RK++;
+ X[1] ^= *RK++;
+ X[2] ^= *RK++;
+ X[3] ^= *RK++;
+
+ while (NR) {
+ --NR;
+ camellia_feistel(X, RK, X + 2);
+ RK += 2;
+ camellia_feistel(X + 2, RK, X);
+ RK += 2;
+ camellia_feistel(X, RK, X + 2);
+ RK += 2;
+ camellia_feistel(X + 2, RK, X);
+ RK += 2;
+ camellia_feistel(X, RK, X + 2);
+ RK += 2;
+ camellia_feistel(X + 2, RK, X);
+ RK += 2;
+
+ if (NR) {
+ FL(X[0], X[1], RK[0], RK[1]);
+ RK += 2;
+ FLInv(X[2], X[3], RK[0], RK[1]);
+ RK += 2;
+ }
+ }
+
+ X[2] ^= *RK++;
+ X[3] ^= *RK++;
+ X[0] ^= *RK++;
+ X[1] ^= *RK++;
+
+ PUT_ULONG_BE( X[2], output, 0 );
+ PUT_ULONG_BE( X[3], output, 4 );
+ PUT_ULONG_BE( X[0], output, 8 );
+ PUT_ULONG_BE( X[1], output, 12 );
+
+ return( 0 );
+}
+
+/*
+ * Camellia-CBC buffer encryption/decryption
+ */
+int camellia_crypt_cbc( camellia_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[16];
+
+ if( length % 16 )
+ return( POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
+
+ if( mode == CAMELLIA_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 16 );
+ camellia_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ camellia_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+/*
+ * Camellia-CFB128 buffer encryption/decryption
+ */
+int camellia_crypt_cfb128( camellia_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == CAMELLIA_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = (n + 1) & 0x0F;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR buffer encryption/decryption
+ */
+int camellia_crypt_ctr( camellia_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter, stream_block );
+
+ for( i = 16; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = (n + 1) & 0x0F;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * Camellia test vectors from:
+ *
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt
+ * (For each bitlength: Key 0, Nr 39)
+ */
+#define CAMELLIA_TESTS_ECB 2
+
+static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
+{
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+};
+
+static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =
+{
+ {
+ { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+ 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+ { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,
+ 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }
+ },
+ {
+ { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+ 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+ { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,
+ 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }
+ },
+ {
+ { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+ 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+ { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,
+ 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }
+ }
+};
+
+#define CAMELLIA_TESTS_CBC 3
+
+static const unsigned char camellia_test_cbc_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+ ,
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
+ ,
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char camellia_test_cbc_iv[16] =
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
+;
+
+static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
+{
+ { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },
+ { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },
+ { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }
+
+};
+
+static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =
+{
+ {
+ { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
+ 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },
+ { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,
+ 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },
+ { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,
+ 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }
+ },
+ {
+ { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
+ 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },
+ { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,
+ 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },
+ { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,
+ 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }
+ },
+ {
+ { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
+ 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },
+ { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,
+ 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },
+ { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,
+ 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }
+ }
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc5528.html
+ */
+
+static const unsigned char camellia_test_ctr_key[3][16] =
+{
+ { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+ 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+ { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+ 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+ { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+ 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char camellia_test_ctr_nonce_counter[3][16] =
+{
+ { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+ 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+ 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char camellia_test_ctr_pt[3][48] =
+{
+ { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char camellia_test_ctr_ct[3][48] =
+{
+ { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,
+ 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },
+ { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,
+ 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,
+ 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,
+ 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },
+ { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,
+ 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,
+ 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,
+ 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,
+ 0xDF, 0x50, 0x86, 0x96 }
+};
+
+static const int camellia_test_ctr_len[3] =
+ { 16, 32, 36 };
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int camellia_self_test( int verbose )
+{
+ int i, j, u, v;
+ unsigned char key[32];
+ unsigned char buf[64];
+ unsigned char src[16];
+ unsigned char dst[16];
+ unsigned char iv[16];
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ size_t offset, len;
+ unsigned char nonce_counter[16];
+ unsigned char stream_block[16];
+#endif
+
+ camellia_context ctx;
+
+ memset( key, 0, 32 );
+
+ for (j = 0; j < 6; j++) {
+ u = j >> 1;
+ v = j & 1;
+
+ if( verbose != 0 )
+ printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
+ (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
+
+ for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
+ memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u);
+
+ if (v == CAMELLIA_DECRYPT) {
+ camellia_setkey_dec(&ctx, key, 128 + u * 64);
+ memcpy(src, camellia_test_ecb_cipher[u][i], 16);
+ memcpy(dst, camellia_test_ecb_plain[i], 16);
+ } else { /* CAMELLIA_ENCRYPT */
+ camellia_setkey_enc(&ctx, key, 128 + u * 64);
+ memcpy(src, camellia_test_ecb_plain[i], 16);
+ memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
+ }
+
+ camellia_crypt_ecb(&ctx, v, src, buf);
+
+ if( memcmp( buf, dst, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ /*
+ * CBC mode
+ */
+ for( j = 0; j < 6; j++ )
+ {
+ u = j >> 1;
+ v = j & 1;
+
+ if( verbose != 0 )
+ printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
+ ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( src, camellia_test_cbc_iv, 16);
+ memcpy( dst, camellia_test_cbc_iv, 16);
+ memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u);
+
+ if (v == CAMELLIA_DECRYPT) {
+ camellia_setkey_dec(&ctx, key, 128 + u * 64);
+ } else {
+ camellia_setkey_enc(&ctx, key, 128 + u * 64);
+ }
+
+ for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
+
+ if (v == CAMELLIA_DECRYPT) {
+ memcpy( iv , src, 16 );
+ memcpy(src, camellia_test_cbc_cipher[u][i], 16);
+ memcpy(dst, camellia_test_cbc_plain[i], 16);
+ } else { /* CAMELLIA_ENCRYPT */
+ memcpy( iv , dst, 16 );
+ memcpy(src, camellia_test_cbc_plain[i], 16);
+ memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
+ }
+
+ camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
+
+ if( memcmp( buf, dst, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ /*
+ * CTR mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " CAMELLIA-CTR-128 (%s): ",
+ ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
+ memcpy( key, camellia_test_ctr_key[u], 16 );
+
+ offset = 0;
+ camellia_setkey_enc( &ctx, key, 128 );
+
+ if( v == CAMELLIA_DECRYPT )
+ {
+ len = camellia_test_ctr_len[u];
+ memcpy( buf, camellia_test_ctr_ct[u], len );
+
+ camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ len = camellia_test_ctr_len[u];
+ memcpy( buf, camellia_test_ctr_pt[u], len );
+
+ camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+
+ if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+ return ( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/certs.c b/polarssl/src/library/certs.c
new file mode 100644
index 0000000..e2d07f7
--- /dev/null
+++ b/polarssl/src/library/certs.c
@@ -0,0 +1,196 @@
+/*
+ * X.509 test certificates
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CERTS_C)
+
+const char test_ca_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n"
+"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n"
+"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n"
+"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n"
+"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n"
+"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n"
+"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n"
+"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n"
+"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n"
+"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n"
+"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n"
+"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n"
+"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n"
+"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n"
+"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n"
+"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_ca_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"Proc-Type: 4,ENCRYPTED\r\n"
+"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n"
+"\r\n"
+"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n"
+"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n"
+"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n"
+"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n"
+"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n"
+"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n"
+"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n"
+"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n"
+"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n"
+"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n"
+"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n"
+"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n"
+"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n"
+"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n"
+"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n"
+"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n"
+"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n"
+"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n"
+"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n"
+"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n"
+"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n"
+"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n"
+"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n"
+"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n"
+"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_ca_pwd[] = "PolarSSLTest";
+
+const char test_srv_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN\r\n"
+"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/\r\n"
+"uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD\r\n"
+"d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf\r\n"
+"CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr\r\n"
+"lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w\r\n"
+"bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB\r\n"
+"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf\r\n"
+"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
+"AQEAvc+WwZUemsJu2IiI2Cp6liA+UAvIx98dQe3kZs2zAoF9VwQbXcYzWQ/BILkj\r\n"
+"NImKbPL9x0g2jIDn4ZvGYFywMwIO/d++YbwYiQw42/v7RiMy94zBPnzeHi86dy/0\r\n"
+"jpOOJUx3IXRsGLdyjb/1T11klcFqGnARiK+8VYolMPP6afKvLXX7K4kiUpsFQhUp\r\n"
+"E5VeM5pV1Mci2ETOJau2cO40FJvI/C9W/wR+GAArMaw2fxG77E3laaa0LAOlexM6\r\n"
+"A4KOb5f5cGTM5Ih6tEF5FVq3/9vzNIYMa1FqzacBLZF8zSHYLEimXBdzjBoN4qDU\r\n"
+"/WzRyYRBRjAI49mzHX6raleqnw==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_srv_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"MIIEogIBAAKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/uOhFkNvuiBZS0/FDUEeW\r\n"
+"Ellkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFDd185fAkER4KwVzlw7aPs\r\n"
+"FRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVfCrFTxjB+FTms+Vruf5Ke\r\n"
+"pgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTrlZvc/kFeF6babFtpzAK6\r\n"
+"FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9wbp7OvViJ4lNZnm5akmXi\r\n"
+"iD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQABAoIBABaJ9eiRQq4Ypv+w\r\n"
+"UTcVpLC0oTueWzcpor1i1zjG4Vzqe/Ok2FqyGToGKMlFK7Hwwa+LEyeJ3xyV5yd4\r\n"
+"v1Mw9bDZFdJC1eCBjoUAHtX6k9HOE0Vd6woVQ4Vi6OPI1g7B5Mnr/58rNrnN6TMs\r\n"
+"x58NF6euecwTU811QJrZtLbX7j2Cr28yB2Vs8qyYlHwVw5jbDOv43D7vU5gmlIDN\r\n"
+"0JQRuWAnOuPzZNoJr4SfJKqHNGxYYY6pHZ1s0dOTLIDb/B8KQWapA2kRmZyid2EH\r\n"
+"nwzgLbAsHJCf+bQnhXjXuxtUsrcIL8noZLazlOMxwNEammglVWW23Ud/QRnFgJg5\r\n"
+"UgcAcRECgYEA19uYetht5qmwdJ+12oC6zeO+vXLcyD9gon23T5J6w2YThld7/OW0\r\n"
+"oArQJGgkAdaq0pcTyOIjtTQVMFygdVmCEJmxh/3RutPcTeydqW9fphKDMej32J8e\r\n"
+"GniGmNGiclbcfNOS8E5TGp445yZb9P1+7AHng16bGg3Ykj5EA4G+HCcCgYEAyHAl\r\n"
+"//ekk8YjQElm+8izLtFkymIK0aCtEe9C/RIRhFYBeFaotC5dStNhBOncn4ovMAPD\r\n"
+"lX/92yDi9OP8PPLN3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n"
+"LYl3YWr2h3EGKICT03kEoTkiDBvCeOpW7cCGl2cCgYBD5whoXHz1+ptPlI4YVjZt\r\n"
+"Xh86aU+ajpVPiEyJ84I6xXmO4SZXv8q6LaycR0ZMbcL+zBelMb4Z2nBv7jNrtuR7\r\n"
+"ZF28cdPv+YVr3esaybZE/73VjXup4SQPH6r3l7qKTVi+y6+FeJ4b2Xn8/MwgnT23\r\n"
+"8EFrye7wmzpthrjOgZnUMQKBgE9Lhsz/5J0Nis6Y+2Pqn3CLKEukg9Ewtqdct2y0\r\n"
+"5Dcta0F3TyCRIxlCDKTL/BslqMtfAdY4H268UO0+8IAQMn9boqzBrHIgs/pvc5kx\r\n"
+"TbKHmw2wtWR6vYersBKVgVpbCGSRssDYHGFu1n74qM4HJ/RGcR1zI9QUe1gopSFD\r\n"
+"xDtLAoGAVAdWvrqDwgoL2hHW3scGpxdE/ygJDOwHnf+1B9goKAOP5lf2FJaiAxf3\r\n"
+"ectoPOgZbCmm/iiDmigu703ld3O+VoCLDD4qx3R+KyALL78gtVJYzSRiKhzgCZ3g\r\n"
+"mKsIVRBq4IfwiwyMNG2BYZQAwbSDjjPtn/kPBduPzPj7eriByhI=\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_cli_crt[] =
+"-----BEGIN CERTIFICATE-----\r\n"
+"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
+"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n"
+"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n"
+"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n"
+"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n"
+"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n"
+"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n"
+"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n"
+"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n"
+"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
+"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n"
+"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n"
+"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n"
+"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n"
+"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n"
+"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+const char test_cli_key[] =
+"-----BEGIN RSA PRIVATE KEY-----\r\n"
+"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n"
+"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n"
+"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n"
+"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n"
+"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n"
+"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n"
+"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n"
+"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n"
+"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n"
+"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n"
+"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n"
+"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n"
+"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n"
+"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n"
+"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n"
+"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n"
+"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n"
+"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n"
+"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n"
+"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n"
+"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n"
+"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n"
+"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n"
+"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n"
+"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n"
+"-----END RSA PRIVATE KEY-----\r\n";
+
+const char test_dhm_params[] =
+"-----BEGIN DH PARAMETERS-----\r\n"
+"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
+"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
+"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
+"-----END DH PARAMETERS-----\r\n";
+
+#endif
diff --git a/polarssl/src/library/cipher.c b/polarssl/src/library/cipher.c
new file mode 100644
index 0000000..0d1258b
--- /dev/null
+++ b/polarssl/src/library/cipher.c
@@ -0,0 +1,557 @@
+/**
+ * \file cipher.c
+ *
+ * \brief Generic cipher wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CIPHER_C)
+
+#include "polarssl/cipher.h"
+#include "polarssl/cipher_wrap.h"
+
+#include <stdlib.h>
+
+#if defined _MSC_VER && !defined strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+static const int supported_ciphers[] = {
+
+#if defined(POLARSSL_AES_C)
+ POLARSSL_CIPHER_AES_128_CBC,
+ POLARSSL_CIPHER_AES_192_CBC,
+ POLARSSL_CIPHER_AES_256_CBC,
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ POLARSSL_CIPHER_AES_128_CFB128,
+ POLARSSL_CIPHER_AES_192_CFB128,
+ POLARSSL_CIPHER_AES_256_CFB128,
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ POLARSSL_CIPHER_AES_128_CTR,
+ POLARSSL_CIPHER_AES_192_CTR,
+ POLARSSL_CIPHER_AES_256_CTR,
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif /* defined(POLARSSL_AES_C) */
+
+#if defined(POLARSSL_CAMELLIA_C)
+ POLARSSL_CIPHER_CAMELLIA_128_CBC,
+ POLARSSL_CIPHER_CAMELLIA_192_CBC,
+ POLARSSL_CIPHER_CAMELLIA_256_CBC,
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+ POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ POLARSSL_CIPHER_CAMELLIA_128_CTR,
+ POLARSSL_CIPHER_CAMELLIA_192_CTR,
+ POLARSSL_CIPHER_CAMELLIA_256_CTR,
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif /* defined(POLARSSL_CAMELLIA_C) */
+
+#if defined(POLARSSL_DES_C)
+ POLARSSL_CIPHER_DES_CBC,
+ POLARSSL_CIPHER_DES_EDE_CBC,
+ POLARSSL_CIPHER_DES_EDE3_CBC,
+#endif /* defined(POLARSSL_DES_C) */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ POLARSSL_CIPHER_NULL,
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ 0
+};
+
+const int *cipher_list( void )
+{
+ return supported_ciphers;
+}
+
+const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
+{
+ /* Find static cipher information */
+ switch ( cipher_type )
+ {
+#if defined(POLARSSL_AES_C)
+ case POLARSSL_CIPHER_AES_128_CBC:
+ return &aes_128_cbc_info;
+ case POLARSSL_CIPHER_AES_192_CBC:
+ return &aes_192_cbc_info;
+ case POLARSSL_CIPHER_AES_256_CBC:
+ return &aes_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ case POLARSSL_CIPHER_AES_128_CFB128:
+ return &aes_128_cfb128_info;
+ case POLARSSL_CIPHER_AES_192_CFB128:
+ return &aes_192_cfb128_info;
+ case POLARSSL_CIPHER_AES_256_CFB128:
+ return &aes_256_cfb128_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ case POLARSSL_CIPHER_AES_128_CTR:
+ return &aes_128_ctr_info;
+ case POLARSSL_CIPHER_AES_192_CTR:
+ return &aes_192_ctr_info;
+ case POLARSSL_CIPHER_AES_256_CTR:
+ return &aes_256_ctr_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ case POLARSSL_CIPHER_CAMELLIA_128_CBC:
+ return &camellia_128_cbc_info;
+ case POLARSSL_CIPHER_CAMELLIA_192_CBC:
+ return &camellia_192_cbc_info;
+ case POLARSSL_CIPHER_CAMELLIA_256_CBC:
+ return &camellia_256_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ case POLARSSL_CIPHER_CAMELLIA_128_CFB128:
+ return &camellia_128_cfb128_info;
+ case POLARSSL_CIPHER_CAMELLIA_192_CFB128:
+ return &camellia_192_cfb128_info;
+ case POLARSSL_CIPHER_CAMELLIA_256_CFB128:
+ return &camellia_256_cfb128_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ case POLARSSL_CIPHER_CAMELLIA_128_CTR:
+ return &camellia_128_ctr_info;
+ case POLARSSL_CIPHER_CAMELLIA_192_CTR:
+ return &camellia_192_ctr_info;
+ case POLARSSL_CIPHER_CAMELLIA_256_CTR:
+ return &camellia_256_ctr_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#endif
+
+#if defined(POLARSSL_DES_C)
+ case POLARSSL_CIPHER_DES_CBC:
+ return &des_cbc_info;
+ case POLARSSL_CIPHER_DES_EDE_CBC:
+ return &des_ede_cbc_info;
+ case POLARSSL_CIPHER_DES_EDE3_CBC:
+ return &des_ede3_cbc_info;
+#endif
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ case POLARSSL_CIPHER_NULL:
+ return &null_cipher_info;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ default:
+ return NULL;
+ }
+}
+
+const cipher_info_t *cipher_info_from_string( const char *cipher_name )
+{
+ if( NULL == cipher_name )
+ return NULL;
+
+ /* Get the appropriate cipher information */
+#if defined(POLARSSL_CAMELLIA_C)
+ if( !strcasecmp( "CAMELLIA-128-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CBC );
+ if( !strcasecmp( "CAMELLIA-192-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CBC );
+ if( !strcasecmp( "CAMELLIA-256-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CBC );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ if( !strcasecmp( "CAMELLIA-128-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CFB128 );
+ if( !strcasecmp( "CAMELLIA-192-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CFB128 );
+ if( !strcasecmp( "CAMELLIA-256-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CFB128 );
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ if( !strcasecmp( "CAMELLIA-128-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CTR );
+ if( !strcasecmp( "CAMELLIA-192-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CTR );
+ if( !strcasecmp( "CAMELLIA-256-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CTR );
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+#endif
+
+#if defined(POLARSSL_AES_C)
+ if( !strcasecmp( "AES-128-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CBC );
+ if( !strcasecmp( "AES-192-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CBC );
+ if( !strcasecmp( "AES-256-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CBC );
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ if( !strcasecmp( "AES-128-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CFB128 );
+ if( !strcasecmp( "AES-192-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CFB128 );
+ if( !strcasecmp( "AES-256-CFB128", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CFB128 );
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ if( !strcasecmp( "AES-128-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CTR );
+ if( !strcasecmp( "AES-192-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CTR );
+ if( !strcasecmp( "AES-256-CTR", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CTR );
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+#endif
+
+#if defined(POLARSSL_DES_C)
+ if( !strcasecmp( "DES-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_DES_CBC );
+ if( !strcasecmp( "DES-EDE-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE_CBC );
+ if( !strcasecmp( "DES-EDE3-CBC", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE3_CBC );
+#endif
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( !strcasecmp( "NULL", cipher_name ) )
+ return cipher_info_from_type( POLARSSL_CIPHER_NULL );
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ return NULL;
+}
+
+int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
+{
+ if( NULL == cipher_info || NULL == ctx )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ memset( ctx, 0, sizeof( cipher_context_t ) );
+
+ if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
+ return POLARSSL_ERR_CIPHER_ALLOC_FAILED;
+
+ ctx->cipher_info = cipher_info;
+
+ return 0;
+}
+
+int cipher_free_ctx( cipher_context_t *ctx )
+{
+ if( ctx == NULL || ctx->cipher_info == NULL )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
+
+ return 0;
+}
+
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
+ int key_length, const operation_t operation )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ ctx->key_length = key_length;
+ ctx->operation = operation;
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
+ return 0;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ /*
+ * For CFB128 and CTR mode always use the encryption key schedule
+ */
+ if( POLARSSL_ENCRYPT == operation ||
+ POLARSSL_MODE_CFB128 == ctx->cipher_info->mode ||
+ POLARSSL_MODE_CTR == ctx->cipher_info->mode )
+ {
+ return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
+ ctx->key_length );
+ }
+
+ if( POLARSSL_DECRYPT == operation )
+ return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
+ ctx->key_length );
+
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+}
+
+int cipher_reset( cipher_context_t *ctx, const unsigned char *iv )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ ctx->unprocessed_len = 0;
+
+ memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );
+
+ return 0;
+}
+
+int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen )
+{
+ int ret;
+ size_t copy_len = 0;
+
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ||
+ input == output )
+ {
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+ }
+
+ *olen = 0;
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
+ {
+ memcpy( output, input, ilen );
+ *olen = ilen;
+ return 0;
+ }
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+ if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )
+ {
+ /*
+ * If there is not enough data for a full block, cache it.
+ */
+ if( ( ctx->operation == POLARSSL_DECRYPT &&
+ ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) ||
+ ( ctx->operation == POLARSSL_ENCRYPT &&
+ ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) )
+ {
+ memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+ ilen );
+
+ ctx->unprocessed_len += ilen;
+ return 0;
+ }
+
+ /*
+ * Process cached data first
+ */
+ if( ctx->unprocessed_len != 0 )
+ {
+ copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len;
+
+ memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+ copy_len );
+
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
+ ctx->unprocessed_data, output ) ) )
+ {
+ return ret;
+ }
+
+ *olen += cipher_get_block_size( ctx );
+ output += cipher_get_block_size( ctx );
+ ctx->unprocessed_len = 0;
+
+ input += copy_len;
+ ilen -= copy_len;
+ }
+
+ /*
+ * Cache final, incomplete block
+ */
+ if( 0 != ilen )
+ {
+ copy_len = ilen % cipher_get_block_size( ctx );
+ if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT )
+ copy_len = cipher_get_block_size(ctx);
+
+ memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
+ copy_len );
+
+ ctx->unprocessed_len += copy_len;
+ ilen -= copy_len;
+ }
+
+ /*
+ * Process remaining full blocks
+ */
+ if( ilen )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, ilen, ctx->iv, input, output ) ) )
+ {
+ return ret;
+ }
+ *olen += ilen;
+ }
+
+ return 0;
+ }
+
+ if( ctx->cipher_info->mode == POLARSSL_MODE_CFB128 )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->cfb128_func( ctx->cipher_ctx,
+ ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
+ input, output ) ) )
+ {
+ return ret;
+ }
+
+ *olen = ilen;
+
+ return 0;
+ }
+
+ if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
+ ilen, &ctx->unprocessed_len, ctx->iv,
+ ctx->unprocessed_data, input, output ) ) )
+ {
+ return ret;
+ }
+
+ *olen = ilen;
+
+ return 0;
+ }
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+static void add_pkcs_padding( unsigned char *output, size_t output_len,
+ size_t data_len )
+{
+ size_t padding_len = output_len - data_len;
+ unsigned char i = 0;
+
+ for( i = 0; i < padding_len; i++ )
+ output[data_len + i] = (unsigned char) padding_len;
+}
+
+static int get_pkcs_padding( unsigned char *input, unsigned int input_len,
+ size_t *data_len)
+{
+ unsigned int i, padding_len = 0;
+
+ if( NULL == input || NULL == data_len )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ padding_len = input[input_len - 1];
+
+ if( padding_len > input_len )
+ return POLARSSL_ERR_CIPHER_INVALID_PADDING;
+
+ for( i = input_len - padding_len; i < input_len; i++ )
+ if( input[i] != padding_len )
+ return POLARSSL_ERR_CIPHER_INVALID_PADDING;
+
+ *data_len = input_len - padding_len;
+
+ return 0;
+}
+
+int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen)
+{
+ int ret = 0;
+
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+ return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+ *olen = 0;
+
+ if( POLARSSL_MODE_CFB128 == ctx->cipher_info->mode ||
+ POLARSSL_MODE_CTR == ctx->cipher_info->mode ||
+ POLARSSL_MODE_NULL == ctx->cipher_info->mode )
+ {
+ return 0;
+ }
+
+ if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
+ {
+ if( POLARSSL_ENCRYPT == ctx->operation )
+ {
+ add_pkcs_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ),
+ ctx->unprocessed_len );
+ }
+ else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len )
+ {
+ /* For decrypt operations, expect a full block */
+ return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+ }
+
+ /* cipher block */
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
+ ctx->unprocessed_data, output ) ) )
+ {
+ return ret;
+ }
+
+ /* Set output size for decryption */
+ if( POLARSSL_DECRYPT == ctx->operation )
+ return get_pkcs_padding( output, cipher_get_block_size( ctx ), olen );
+
+ /* Set output size for encryption */
+ *olen = cipher_get_block_size( ctx );
+ return 0;
+ }
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+#define ASSERT(x) if (!(x)) { \
+ printf( "failed with %i at %s\n", value, (#x) ); \
+ return( 1 ); \
+}
+/*
+ * Checkup routine
+ */
+
+int cipher_self_test( int verbose )
+{
+ ((void) verbose);
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/cipher_wrap.c b/polarssl/src/library/cipher_wrap.c
new file mode 100644
index 0000000..99e5092
--- /dev/null
+++ b/polarssl/src/library/cipher_wrap.c
@@ -0,0 +1,595 @@
+/**
+ * \file md_wrap.c
+ *
+ * \brief Generic cipher wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CIPHER_C)
+
+#include "polarssl/cipher_wrap.h"
+
+#if defined(POLARSSL_AES_C)
+#include "polarssl/aes.h"
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+#include "polarssl/camellia.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_AES_C)
+
+int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input, output );
+}
+
+int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+ size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv, input, output );
+#else
+ ((void) ctx);
+ ((void) operation);
+ ((void) length);
+ ((void) iv_off);
+ ((void) iv);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int aes_crypt_ctr_wrap( void *ctx, size_t length,
+ size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ return aes_crypt_ctr( (aes_context *) ctx, length, nc_off, nonce_counter,
+ stream_block, input, output );
+#else
+ ((void) ctx);
+ ((void) length);
+ ((void) nc_off);
+ ((void) nonce_counter);
+ ((void) stream_block);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return aes_setkey_dec( (aes_context *) ctx, key, key_length );
+}
+
+int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return aes_setkey_enc( (aes_context *) ctx, key, key_length );
+}
+
+static void * aes_ctx_alloc( void )
+{
+ return malloc( sizeof( aes_context ) );
+}
+
+static void aes_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const cipher_base_t aes_info = {
+ POLARSSL_CIPHER_ID_AES,
+ aes_crypt_cbc_wrap,
+ aes_crypt_cfb128_wrap,
+ aes_crypt_ctr_wrap,
+ aes_setkey_enc_wrap,
+ aes_setkey_dec_wrap,
+ aes_ctx_alloc,
+ aes_ctx_free
+};
+
+const cipher_info_t aes_128_cbc_info = {
+ POLARSSL_CIPHER_AES_128_CBC,
+ POLARSSL_MODE_CBC,
+ 128,
+ "AES-128-CBC",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_192_cbc_info = {
+ POLARSSL_CIPHER_AES_192_CBC,
+ POLARSSL_MODE_CBC,
+ 192,
+ "AES-192-CBC",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_256_cbc_info = {
+ POLARSSL_CIPHER_AES_256_CBC,
+ POLARSSL_MODE_CBC,
+ 256,
+ "AES-256-CBC",
+ 16,
+ 16,
+ &aes_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t aes_128_cfb128_info = {
+ POLARSSL_CIPHER_AES_128_CFB128,
+ POLARSSL_MODE_CFB128,
+ 128,
+ "AES-128-CFB128",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_192_cfb128_info = {
+ POLARSSL_CIPHER_AES_192_CFB128,
+ POLARSSL_MODE_CFB128,
+ 192,
+ "AES-192-CFB128",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_256_cfb128_info = {
+ POLARSSL_CIPHER_AES_256_CFB128,
+ POLARSSL_MODE_CFB128,
+ 256,
+ "AES-256-CFB128",
+ 16,
+ 16,
+ &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t aes_128_ctr_info = {
+ POLARSSL_CIPHER_AES_128_CTR,
+ POLARSSL_MODE_CTR,
+ 128,
+ "AES-128-CTR",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_192_ctr_info = {
+ POLARSSL_CIPHER_AES_192_CTR,
+ POLARSSL_MODE_CTR,
+ 192,
+ "AES-192-CTR",
+ 16,
+ 16,
+ &aes_info
+};
+
+const cipher_info_t aes_256_ctr_info = {
+ POLARSSL_CIPHER_AES_256_CTR,
+ POLARSSL_MODE_CTR,
+ 256,
+ "AES-256-CTR",
+ 16,
+ 16,
+ &aes_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+
+int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv, input, output );
+}
+
+int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+ size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+ return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length, iv_off, iv, input, output );
+#else
+ ((void) ctx);
+ ((void) operation);
+ ((void) length);
+ ((void) iv_off);
+ ((void) iv);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int camellia_crypt_ctr_wrap( void *ctx, size_t length,
+ size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+ return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off, nonce_counter,
+ stream_block, input, output );
+#else
+ ((void) ctx);
+ ((void) length);
+ ((void) nc_off);
+ ((void) nonce_counter);
+ ((void) stream_block);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return camellia_setkey_dec( (camellia_context *) ctx, key, key_length );
+}
+
+int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return camellia_setkey_enc( (camellia_context *) ctx, key, key_length );
+}
+
+static void * camellia_ctx_alloc( void )
+{
+ return malloc( sizeof( camellia_context ) );
+}
+
+static void camellia_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const cipher_base_t camellia_info = {
+ POLARSSL_CIPHER_ID_CAMELLIA,
+ camellia_crypt_cbc_wrap,
+ camellia_crypt_cfb128_wrap,
+ camellia_crypt_ctr_wrap,
+ camellia_setkey_enc_wrap,
+ camellia_setkey_dec_wrap,
+ camellia_ctx_alloc,
+ camellia_ctx_free
+};
+
+const cipher_info_t camellia_128_cbc_info = {
+ POLARSSL_CIPHER_CAMELLIA_128_CBC,
+ POLARSSL_MODE_CBC,
+ 128,
+ "CAMELLIA-128-CBC",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_192_cbc_info = {
+ POLARSSL_CIPHER_CAMELLIA_192_CBC,
+ POLARSSL_MODE_CBC,
+ 192,
+ "CAMELLIA-192-CBC",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_256_cbc_info = {
+ POLARSSL_CIPHER_CAMELLIA_256_CBC,
+ POLARSSL_MODE_CBC,
+ 256,
+ "CAMELLIA-256-CBC",
+ 16,
+ 16,
+ &camellia_info
+};
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+const cipher_info_t camellia_128_cfb128_info = {
+ POLARSSL_CIPHER_CAMELLIA_128_CFB128,
+ POLARSSL_MODE_CFB128,
+ 128,
+ "CAMELLIA-128-CFB128",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_192_cfb128_info = {
+ POLARSSL_CIPHER_CAMELLIA_192_CFB128,
+ POLARSSL_MODE_CFB128,
+ 192,
+ "CAMELLIA-192-CFB128",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_256_cfb128_info = {
+ POLARSSL_CIPHER_CAMELLIA_256_CFB128,
+ POLARSSL_MODE_CFB128,
+ 256,
+ "CAMELLIA-256-CFB128",
+ 16,
+ 16,
+ &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+const cipher_info_t camellia_128_ctr_info = {
+ POLARSSL_CIPHER_CAMELLIA_128_CTR,
+ POLARSSL_MODE_CTR,
+ 128,
+ "CAMELLIA-128-CTR",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_192_ctr_info = {
+ POLARSSL_CIPHER_CAMELLIA_192_CTR,
+ POLARSSL_MODE_CTR,
+ 192,
+ "CAMELLIA-192-CTR",
+ 16,
+ 16,
+ &camellia_info
+};
+
+const cipher_info_t camellia_256_ctr_info = {
+ POLARSSL_CIPHER_CAMELLIA_256_CTR,
+ POLARSSL_MODE_CTR,
+ 256,
+ "CAMELLIA-256-CTR",
+ 16,
+ 16,
+ &camellia_info
+};
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+
+#endif
+
+#if defined(POLARSSL_DES_C)
+
+int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input, output );
+}
+
+int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input, output );
+}
+
+int des_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
+ size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ ((void) ctx);
+ ((void) operation);
+ ((void) length);
+ ((void) iv_off);
+ ((void) iv);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+int des_crypt_ctr_wrap( void *ctx, size_t length,
+ size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+ ((void) ctx);
+ ((void) length);
+ ((void) nc_off);
+ ((void) nonce_counter);
+ ((void) stream_block);
+ ((void) input);
+ ((void) output);
+
+ return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+}
+
+
+int des_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des_setkey_dec( (des_context *) ctx, key );
+}
+
+int des_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des_setkey_enc( (des_context *) ctx, key );
+}
+
+int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des3_set2key_dec( (des3_context *) ctx, key );
+}
+
+int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des3_set2key_enc( (des3_context *) ctx, key );
+}
+
+int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des3_set3key_dec( (des3_context *) ctx, key );
+}
+
+int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ ((void) key_length);
+
+ return des3_set3key_enc( (des3_context *) ctx, key );
+}
+
+static void * des_ctx_alloc( void )
+{
+ return malloc( sizeof( des_context ) );
+}
+
+static void * des3_ctx_alloc( void )
+{
+ return malloc( sizeof( des3_context ) );
+}
+
+static void des_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const cipher_base_t des_info = {
+ POLARSSL_CIPHER_ID_DES,
+ des_crypt_cbc_wrap,
+ des_crypt_cfb128_wrap,
+ des_crypt_ctr_wrap,
+ des_setkey_enc_wrap,
+ des_setkey_dec_wrap,
+ des_ctx_alloc,
+ des_ctx_free
+};
+
+const cipher_info_t des_cbc_info = {
+ POLARSSL_CIPHER_DES_CBC,
+ POLARSSL_MODE_CBC,
+ POLARSSL_KEY_LENGTH_DES,
+ "DES-CBC",
+ 8,
+ 8,
+ &des_info
+};
+
+const cipher_base_t des_ede_info = {
+ POLARSSL_CIPHER_ID_DES,
+ des3_crypt_cbc_wrap,
+ des_crypt_cfb128_wrap,
+ des_crypt_ctr_wrap,
+ des3_set2key_enc_wrap,
+ des3_set2key_dec_wrap,
+ des3_ctx_alloc,
+ des_ctx_free
+};
+
+const cipher_info_t des_ede_cbc_info = {
+ POLARSSL_CIPHER_DES_EDE_CBC,
+ POLARSSL_MODE_CBC,
+ POLARSSL_KEY_LENGTH_DES_EDE,
+ "DES-EDE-CBC",
+ 16,
+ 16,
+ &des_ede_info
+};
+
+const cipher_base_t des_ede3_info = {
+ POLARSSL_CIPHER_ID_DES,
+ des3_crypt_cbc_wrap,
+ des_crypt_cfb128_wrap,
+ des_crypt_ctr_wrap,
+ des3_set3key_enc_wrap,
+ des3_set3key_dec_wrap,
+ des3_ctx_alloc,
+ des_ctx_free
+};
+
+const cipher_info_t des_ede3_cbc_info = {
+ POLARSSL_CIPHER_DES_EDE3_CBC,
+ POLARSSL_MODE_CBC,
+ POLARSSL_KEY_LENGTH_DES_EDE3,
+ "DES-EDE3-CBC",
+ 8,
+ 8,
+ &des_ede3_info
+};
+#endif
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+static void * null_ctx_alloc( void )
+{
+ return (void *) 1;
+}
+
+
+static void null_ctx_free( void *ctx )
+{
+ ((void) ctx);
+}
+
+const cipher_base_t null_base_info = {
+ POLARSSL_CIPHER_ID_NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ null_ctx_alloc,
+ null_ctx_free
+};
+
+const cipher_info_t null_cipher_info = {
+ POLARSSL_CIPHER_NULL,
+ POLARSSL_MODE_NULL,
+ 0,
+ "NULL",
+ 1,
+ 1,
+ &null_base_info
+};
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#endif
diff --git a/polarssl/src/library/ctr_drbg.c b/polarssl/src/library/ctr_drbg.c
new file mode 100644
index 0000000..1de7f05
--- /dev/null
+++ b/polarssl/src/library/ctr_drbg.c
@@ -0,0 +1,562 @@
+/*
+ * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The NIST SP 800-90 DRBGs are described in the following publucation.
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_CTR_DRBG_C)
+
+#include "polarssl/ctr_drbg.h"
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+/*
+ * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
+ * tests to succeed (which require known length fixed entropy)
+ */
+int ctr_drbg_init_entropy_len(
+ ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len,
+ size_t entropy_len )
+{
+ int ret;
+ unsigned char key[CTR_DRBG_KEYSIZE];
+
+ memset( ctx, 0, sizeof(ctr_drbg_context) );
+ memset( key, 0, CTR_DRBG_KEYSIZE );
+
+ ctx->f_entropy = f_entropy;
+ ctx->p_entropy = p_entropy;
+
+ ctx->entropy_len = entropy_len;
+ ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;
+
+ /*
+ * Initialize with an empty key
+ */
+ aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );
+
+ if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+int ctr_drbg_init( ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len )
+{
+ return( ctr_drbg_init_entropy_len( ctx, f_entropy, p_entropy, custom, len,
+ CTR_DRBG_ENTROPY_LEN ) );
+}
+
+void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
+{
+ ctx->prediction_resistance = resistance;
+}
+
+void ctr_drbg_set_entropy_len( ctr_drbg_context *ctx, size_t len )
+{
+ ctx->entropy_len = len;
+}
+
+void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx, int interval )
+{
+ ctx->reseed_interval = interval;
+}
+
+int block_cipher_df( unsigned char *output,
+ const unsigned char *data, size_t data_len )
+{
+ unsigned char buf[CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16];
+ unsigned char tmp[CTR_DRBG_SEEDLEN];
+ unsigned char key[CTR_DRBG_KEYSIZE];
+ unsigned char chain[CTR_DRBG_BLOCKSIZE];
+ unsigned char *p = buf, *iv;
+ aes_context aes_ctx;
+
+ int i, j, buf_len, use_len;
+
+ memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
+
+ /*
+ * Construct IV (16 bytes) and S in buffer
+ * IV = Counter (in 32-bits) padded to 16 with zeroes
+ * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
+ * data || 0x80
+ * (Total is padded to a multiple of 16-bytes with zeroes)
+ */
+ p = buf + CTR_DRBG_BLOCKSIZE;
+ *p++ = ( data_len >> 24 ) & 0xff;
+ *p++ = ( data_len >> 16 ) & 0xff;
+ *p++ = ( data_len >> 8 ) & 0xff;
+ *p++ = ( data_len ) & 0xff;
+ p += 3;
+ *p++ = CTR_DRBG_SEEDLEN;
+ memcpy( p, data, data_len );
+ p[data_len] = 0x80;
+
+ buf_len = CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
+
+ for( i = 0; i < CTR_DRBG_KEYSIZE; i++ )
+ key[i] = i;
+
+ aes_setkey_enc( &aes_ctx, key, CTR_DRBG_KEYBITS );
+
+ /*
+ * Reduce data to POLARSSL_CTR_DRBG_SEEDLEN bytes of data
+ */
+ for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+ {
+ p = buf;
+ memset( chain, 0, CTR_DRBG_BLOCKSIZE );
+ use_len = buf_len;
+
+ while( use_len > 0 )
+ {
+ for( i = 0; i < CTR_DRBG_BLOCKSIZE; i++ )
+ chain[i] ^= p[i];
+ p += CTR_DRBG_BLOCKSIZE;
+ use_len -= CTR_DRBG_BLOCKSIZE;
+
+ aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, chain, chain );
+ }
+
+ memcpy( tmp + j, chain, CTR_DRBG_BLOCKSIZE );
+
+ /*
+ * Update IV
+ */
+ buf[3]++;
+ }
+
+ /*
+ * Do final encryption with reduced data
+ */
+ aes_setkey_enc( &aes_ctx, tmp, CTR_DRBG_KEYBITS );
+ iv = tmp + CTR_DRBG_KEYSIZE;
+ p = output;
+
+ for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+ {
+ aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, iv, iv );
+ memcpy( p, iv, CTR_DRBG_BLOCKSIZE );
+ p += CTR_DRBG_BLOCKSIZE;
+ }
+
+ return( 0 );
+}
+
+int ctr_drbg_update_internal( ctr_drbg_context *ctx,
+ const unsigned char data[CTR_DRBG_SEEDLEN] )
+{
+ unsigned char tmp[CTR_DRBG_SEEDLEN];
+ unsigned char *p = tmp;
+ int i, j;
+
+ memset( tmp, 0, CTR_DRBG_SEEDLEN );
+
+ for( j = 0; j < CTR_DRBG_SEEDLEN; j += CTR_DRBG_BLOCKSIZE )
+ {
+ /*
+ * Increase counter
+ */
+ for( i = CTR_DRBG_BLOCKSIZE; i >= 0; i-- )
+ if( ++ctx->counter[i - 1] != 0 )
+ break;
+
+ /*
+ * Crypt counter block
+ */
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, p );
+
+ p += CTR_DRBG_BLOCKSIZE;
+ }
+
+ for( i = 0; i < CTR_DRBG_SEEDLEN; i++ )
+ tmp[i] ^= data[i];
+
+ /*
+ * Update key and counter
+ */
+ aes_setkey_enc( &ctx->aes_ctx, tmp, CTR_DRBG_KEYBITS );
+ memcpy( ctx->counter, tmp + CTR_DRBG_KEYSIZE, CTR_DRBG_BLOCKSIZE );
+
+ return( 0 );
+}
+
+void ctr_drbg_update( ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len )
+{
+ unsigned char add_input[CTR_DRBG_SEEDLEN];
+
+ if( add_len > 0 )
+ {
+ block_cipher_df( add_input, additional, add_len );
+ ctr_drbg_update_internal( ctx, add_input );
+ }
+}
+
+int ctr_drbg_reseed( ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t len )
+{
+ unsigned char seed[CTR_DRBG_MAX_SEED_INPUT];
+ size_t seedlen = 0;
+
+ if( ctx->entropy_len + len > CTR_DRBG_MAX_SEED_INPUT )
+ return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
+
+ /*
+ * Gather enropy_len bytes of entropy to seed state
+ */
+ if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
+ ctx->entropy_len ) )
+ {
+ return( POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+ }
+
+ seedlen += ctx->entropy_len;
+
+ /*
+ * Add additional data
+ */
+ if( additional && len )
+ {
+ memcpy( seed + seedlen, additional, len );
+ seedlen += len;
+ }
+
+ /*
+ * Reduce to 384 bits
+ */
+ block_cipher_df( seed, seed, seedlen );
+
+ /*
+ * Update state
+ */
+ ctr_drbg_update_internal( ctx, seed );
+ ctx->reseed_counter = 1;
+
+ return( 0 );
+}
+
+int ctr_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t output_len,
+ const unsigned char *additional, size_t add_len )
+{
+ int ret = 0;
+ ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
+ unsigned char add_input[CTR_DRBG_SEEDLEN];
+ unsigned char *p = output;
+ unsigned char tmp[CTR_DRBG_BLOCKSIZE];
+ int i;
+ size_t use_len;
+
+ if( output_len > CTR_DRBG_MAX_REQUEST )
+ return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );
+
+ if( add_len > CTR_DRBG_MAX_INPUT )
+ return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ memset( add_input, 0, CTR_DRBG_SEEDLEN );
+
+ if( ctx->reseed_counter > ctx->reseed_interval ||
+ ctx->prediction_resistance )
+ {
+ if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+ return( ret );
+
+ add_len = 0;
+ }
+
+ if( add_len > 0 )
+ {
+ block_cipher_df( add_input, additional, add_len );
+ ctr_drbg_update_internal( ctx, add_input );
+ }
+
+ while( output_len > 0 )
+ {
+ /*
+ * Increase counter
+ */
+ for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+ if( ++ctx->counter[i - 1] != 0 )
+ break;
+
+ /*
+ * Crypt counter block
+ */
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
+
+ use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
+ /*
+ * Copy random block to destination
+ */
+ memcpy( p, tmp, use_len );
+ p += use_len;
+ output_len -= use_len;
+ }
+
+ ctr_drbg_update_internal( ctx, add_input );
+
+ ctx->reseed_counter++;
+
+ return( 0 );
+}
+
+int ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
+{
+ return ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
+{
+ int ret;
+ FILE *f;
+ unsigned char buf[ CTR_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "wb" ) ) == NULL )
+ return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+ if( ( ret = ctr_drbg_random( ctx, buf, CTR_DRBG_MAX_INPUT ) ) != 0 )
+ return( ret );
+
+ if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+
+int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
+{
+ FILE *f;
+ size_t n;
+ unsigned char buf[ CTR_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+ fseek( f, 0, SEEK_END );
+ n = (size_t) ftell( f );
+ fseek( f, 0, SEEK_SET );
+
+ if( n > CTR_DRBG_MAX_INPUT )
+ return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ if( fread( buf, 1, n, f ) != n )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
+ }
+
+ ctr_drbg_update( ctx, buf, n );
+
+ fclose( f );
+
+ return( ctr_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+unsigned char entropy_source_pr[96] =
+ { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
+ 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
+ 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
+ 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
+ 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
+ 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
+ 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
+ 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
+ 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
+ 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
+ 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
+ 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
+
+unsigned char entropy_source_nopr[64] =
+ { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
+ 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
+ 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
+ 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
+ 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
+ 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
+ 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
+ 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
+
+unsigned char nonce_pers_pr[16] =
+ { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
+ 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
+
+unsigned char nonce_pers_nopr[16] =
+ { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
+ 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+
+unsigned char result_pr[16] =
+ { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
+ 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
+
+unsigned char result_nopr[16] =
+ { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
+ 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+
+int test_offset;
+int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, size_t len )
+{
+ unsigned char *p = data;
+ memcpy( buf, p + test_offset, len );
+ test_offset += 32;
+ return( 0 );
+}
+
+/*
+ * Checkup routine
+ */
+int ctr_drbg_self_test( int verbose )
+{
+ ctr_drbg_context ctx;
+ unsigned char buf[16];
+
+ /*
+ * Based on a NIST CTR_DRBG test vector (PR = True)
+ */
+ if( verbose != 0 )
+ printf( " CTR_DRBG (PR = TRUE) : " );
+
+ test_offset = 0;
+ if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+ ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
+
+ if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ /*
+ * Based on a NIST CTR_DRBG test vector (PR = FALSE)
+ */
+ if( verbose != 0 )
+ printf( " CTR_DRBG (PR = FALSE): " );
+
+ test_offset = 0;
+ if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( memcmp( buf, result_nopr, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+#endif
+
+#endif
diff --git a/polarssl/src/library/debug.c b/polarssl/src/library/debug.c
new file mode 100644
index 0000000..687e194
--- /dev/null
+++ b/polarssl/src/library/debug.c
@@ -0,0 +1,238 @@
+/*
+ * Debugging routines
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_DEBUG_C)
+
+#include "polarssl/debug.h"
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#if defined _MSC_VER && !defined snprintf
+#define snprintf _snprintf
+#endif
+
+#if defined _MSC_VER && !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif
+
+char *debug_fmt( const char *format, ... )
+{
+ va_list argp;
+ static char str[512];
+ int maxlen = sizeof( str ) - 1;
+
+ va_start( argp, format );
+ vsnprintf( str, maxlen, format, argp );
+ va_end( argp );
+
+ str[maxlen] = '\0';
+ return( str );
+}
+
+void debug_print_msg( const ssl_context *ssl, int level,
+ const char *file, int line, const char *text )
+{
+ char str[512];
+ int maxlen = sizeof( str ) - 1;
+
+ if( ssl->f_dbg == NULL )
+ return;
+
+ snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text );
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+}
+
+void debug_print_ret( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, int ret )
+{
+ char str[512];
+ int maxlen = sizeof( str ) - 1;
+
+ if( ssl->f_dbg == NULL )
+ return;
+
+ snprintf( str, maxlen, "%s(%04d): %s() returned %d (0x%x)\n",
+ file, line, text, ret, ret );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+}
+
+void debug_print_buf( const ssl_context *ssl, int level,
+ const char *file, int line, const char *text,
+ unsigned char *buf, size_t len )
+{
+ char str[512];
+ size_t i, maxlen = sizeof( str ) - 1;
+
+ if( ssl->f_dbg == NULL )
+ return;
+
+ snprintf( str, maxlen, "%s(%04d): dumping '%s' (%d bytes)\n",
+ file, line, text, (unsigned int) len );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+
+ for( i = 0; i < len; i++ )
+ {
+ if( i >= 4096 )
+ break;
+
+ if( i % 16 == 0 )
+ {
+ if( i > 0 )
+ ssl->f_dbg( ssl->p_dbg, level, "\n" );
+
+ snprintf( str, maxlen, "%s(%04d): %04x: ", file, line,
+ (unsigned int) i );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+ }
+
+ snprintf( str, maxlen, " %02x", (unsigned int) buf[i] );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+ }
+
+ if( len > 0 )
+ ssl->f_dbg( ssl->p_dbg, level, "\n" );
+}
+
+void debug_print_mpi( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const mpi *X )
+{
+ char str[512];
+ int j, k, maxlen = sizeof( str ) - 1, zeros = 1;
+ size_t i, n;
+
+ if( ssl->f_dbg == NULL || X == NULL )
+ return;
+
+ for( n = X->n - 1; n > 0; n-- )
+ if( X->p[n] != 0 )
+ break;
+
+ for( j = ( sizeof(t_uint) << 3 ) - 1; j >= 0; j-- )
+ if( ( ( X->p[n] >> j ) & 1 ) != 0 )
+ break;
+
+ snprintf( str, maxlen, "%s(%04d): value of '%s' (%lu bits) is:\n",
+ file, line, text,
+ (unsigned long) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+
+ for( i = n + 1, j = 0; i > 0; i-- )
+ {
+ if( zeros && X->p[i - 1] == 0 )
+ continue;
+
+ for( k = sizeof( t_uint ) - 1; k >= 0; k-- )
+ {
+ if( zeros && ( ( X->p[i - 1] >> (k << 3) ) & 0xFF ) == 0 )
+ continue;
+ else
+ zeros = 0;
+
+ if( j % 16 == 0 )
+ {
+ if( j > 0 )
+ ssl->f_dbg( ssl->p_dbg, level, "\n" );
+
+ snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+ }
+
+ snprintf( str, maxlen, " %02x", (unsigned int)
+ ( X->p[i - 1] >> (k << 3) ) & 0xFF );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+
+ j++;
+ }
+
+ }
+
+ if( zeros == 1 )
+ {
+ snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+ ssl->f_dbg( ssl->p_dbg, level, " 00" );
+ }
+
+ ssl->f_dbg( ssl->p_dbg, level, "\n" );
+}
+
+void debug_print_crt( const ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const x509_cert *crt )
+{
+ char str[1024], prefix[64];
+ int i = 0, maxlen = sizeof( prefix ) - 1;
+
+ if( ssl->f_dbg == NULL || crt == NULL )
+ return;
+
+ snprintf( prefix, maxlen, "%s(%04d): ", file, line );
+ prefix[maxlen] = '\0';
+ maxlen = sizeof( str ) - 1;
+
+ while( crt != NULL )
+ {
+ char buf[1024];
+ x509parse_cert_info( buf, sizeof( buf ) - 1, prefix, crt );
+
+ snprintf( str, maxlen, "%s(%04d): %s #%d:\n%s",
+ file, line, text, ++i, buf );
+
+ str[maxlen] = '\0';
+ ssl->f_dbg( ssl->p_dbg, level, str );
+
+ debug_print_mpi( ssl, level, file, line,
+ "crt->rsa.N", &crt->rsa.N );
+
+ debug_print_mpi( ssl, level, file, line,
+ "crt->rsa.E", &crt->rsa.E );
+
+ crt = crt->next;
+ }
+}
+
+#endif
diff --git a/polarssl/src/library/des.c b/polarssl/src/library/des.c
new file mode 100644
index 0000000..b40baf8
--- /dev/null
+++ b/polarssl/src/library/des.c
@@ -0,0 +1,993 @@
+/*
+ * FIPS-46-3 compliant Triple-DES implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * DES, on which TDES is based, was originally designed by Horst Feistel
+ * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
+ *
+ * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_DES_C)
+
+#include "polarssl/des.h"
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * Expanded DES S-boxes
+ */
+static const unsigned long SB1[64] =
+{
+ 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
+};
+
+static const unsigned long SB2[64] =
+{
+ 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
+};
+
+static const unsigned long SB3[64] =
+{
+ 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
+};
+
+static const unsigned long SB4[64] =
+{
+ 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
+};
+
+static const unsigned long SB5[64] =
+{
+ 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
+};
+
+static const unsigned long SB6[64] =
+{
+ 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
+};
+
+static const unsigned long SB7[64] =
+{
+ 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
+};
+
+static const unsigned long SB8[64] =
+{
+ 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
+};
+
+/*
+ * PC1: left and right halves bit-swap
+ */
+static const unsigned long LHs[16] =
+{
+ 0x00000000, 0x00000001, 0x00000100, 0x00000101,
+ 0x00010000, 0x00010001, 0x00010100, 0x00010101,
+ 0x01000000, 0x01000001, 0x01000100, 0x01000101,
+ 0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const unsigned long RHs[16] =
+{
+ 0x00000000, 0x01000000, 0x00010000, 0x01010000,
+ 0x00000100, 0x01000100, 0x00010100, 0x01010100,
+ 0x00000001, 0x01000001, 0x00010001, 0x01010001,
+ 0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+/*
+ * Initial Permutation macro
+ */
+#define DES_IP(X,Y) \
+{ \
+ T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
+ T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
+ T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
+ T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
+ Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
+ T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
+ X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
+}
+
+/*
+ * Final Permutation macro
+ */
+#define DES_FP(X,Y) \
+{ \
+ X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
+ T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
+ Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
+ T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
+ T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
+ T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
+ T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
+}
+
+/*
+ * DES round macro
+ */
+#define DES_ROUND(X,Y) \
+{ \
+ T = *SK++ ^ X; \
+ Y ^= SB8[ (T ) & 0x3F ] ^ \
+ SB6[ (T >> 8) & 0x3F ] ^ \
+ SB4[ (T >> 16) & 0x3F ] ^ \
+ SB2[ (T >> 24) & 0x3F ]; \
+ \
+ T = *SK++ ^ ((X << 28) | (X >> 4)); \
+ Y ^= SB7[ (T ) & 0x3F ] ^ \
+ SB5[ (T >> 8) & 0x3F ] ^ \
+ SB3[ (T >> 16) & 0x3F ] ^ \
+ SB1[ (T >> 24) & 0x3F ]; \
+}
+
+#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
+
+static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
+ 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+ 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+ 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+ 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+ 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+ 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+ 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+ 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+ 254 };
+
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < DES_KEY_SIZE; i++ )
+ key[i] = odd_parity_table[key[i] / 2];
+}
+
+/*
+ * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < DES_KEY_SIZE; i++ )
+ if ( key[i] != odd_parity_table[key[i] / 2] )
+ return( 1 );
+
+ return( 0 );
+}
+
+/*
+ * Table of weak and semi-weak keys
+ *
+ * Source: http://en.wikipedia.org/wiki/Weak_key
+ *
+ * Weak:
+ * Alternating ones + zeros (0x0101010101010101)
+ * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
+ * '0xE0E0E0E0F1F1F1F1'
+ * '0x1F1F1F1F0E0E0E0E'
+ *
+ * Semi-weak:
+ * 0x011F011F010E010E and 0x1F011F010E010E01
+ * 0x01E001E001F101F1 and 0xE001E001F101F101
+ * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
+ * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
+ * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
+ * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
+ *
+ */
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
+{
+ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+ { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+ { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+ { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+ { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+ { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+ { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+ { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+ { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+ { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+ { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+ { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+ { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+ { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+ { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < WEAK_KEY_COUNT; i++ )
+ if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0)
+ return( 1 );
+
+ return( 0 );
+}
+
+static void des_setkey( unsigned long SK[32], const unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+ unsigned long X, Y, T;
+
+ GET_ULONG_BE( X, key, 0 );
+ GET_ULONG_BE( Y, key, 4 );
+
+ /*
+ * Permuted Choice 1
+ */
+ T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
+ T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
+
+ X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
+ | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
+ | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+ | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+ Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
+ | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
+ | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+ | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+ X &= 0x0FFFFFFF;
+ Y &= 0x0FFFFFFF;
+
+ /*
+ * calculate subkeys
+ */
+ for( i = 0; i < 16; i++ )
+ {
+ if( i < 2 || i == 8 || i == 15 )
+ {
+ X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
+ Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
+ }
+ else
+ {
+ X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
+ Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
+ }
+
+ *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
+ | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+ | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
+ | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
+ | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
+ | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
+ | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
+ | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
+ | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+ | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+ | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+ *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+ | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+ | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
+ | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+ | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
+ | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
+ | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
+ | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
+ | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
+ | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
+ | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+ }
+}
+
+/*
+ * DES key schedule (56-bit, encryption)
+ */
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+ des_setkey( ctx->sk, key );
+
+ return( 0 );
+}
+
+/*
+ * DES key schedule (56-bit, decryption)
+ */
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
+{
+ int i;
+
+ des_setkey( ctx->sk, key );
+
+ for( i = 0; i < 16; i += 2 )
+ {
+ SWAP( ctx->sk[i ], ctx->sk[30 - i] );
+ SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+ }
+
+ return( 0 );
+}
+
+static void des3_set2key( unsigned long esk[96],
+ unsigned long dsk[96],
+ const unsigned char key[DES_KEY_SIZE*2] )
+{
+ int i;
+
+ des_setkey( esk, key );
+ des_setkey( dsk + 32, key + 8 );
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ dsk[i ] = esk[30 - i];
+ dsk[i + 1] = esk[31 - i];
+
+ esk[i + 32] = dsk[62 - i];
+ esk[i + 33] = dsk[63 - i];
+
+ esk[i + 64] = esk[i ];
+ esk[i + 65] = esk[i + 1];
+
+ dsk[i + 64] = dsk[i ];
+ dsk[i + 65] = dsk[i + 1];
+ }
+}
+
+/*
+ * Triple-DES key schedule (112-bit, encryption)
+ */
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
+{
+ unsigned long sk[96];
+
+ des3_set2key( ctx->sk, sk, key );
+ memset( sk, 0, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (112-bit, decryption)
+ */
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
+{
+ unsigned long sk[96];
+
+ des3_set2key( sk, ctx->sk, key );
+ memset( sk, 0, sizeof( sk ) );
+
+ return( 0 );
+}
+
+static void des3_set3key( unsigned long esk[96],
+ unsigned long dsk[96],
+ const unsigned char key[24] )
+{
+ int i;
+
+ des_setkey( esk, key );
+ des_setkey( dsk + 32, key + 8 );
+ des_setkey( esk + 64, key + 16 );
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ dsk[i ] = esk[94 - i];
+ dsk[i + 1] = esk[95 - i];
+
+ esk[i + 32] = dsk[62 - i];
+ esk[i + 33] = dsk[63 - i];
+
+ dsk[i + 64] = esk[30 - i];
+ dsk[i + 65] = esk[31 - i];
+ }
+}
+
+/*
+ * Triple-DES key schedule (168-bit, encryption)
+ */
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
+{
+ unsigned long sk[96];
+
+ des3_set3key( ctx->sk, sk, key );
+ memset( sk, 0, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (168-bit, decryption)
+ */
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
+{
+ unsigned long sk[96];
+
+ des3_set3key( sk, ctx->sk, key );
+ memset( sk, 0, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * DES-ECB block encryption/decryption
+ */
+int des_crypt_ecb( des_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] )
+{
+ int i;
+ unsigned long X, Y, T, *SK;
+
+ SK = ctx->sk;
+
+ GET_ULONG_BE( X, input, 0 );
+ GET_ULONG_BE( Y, input, 4 );
+
+ DES_IP( X, Y );
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ DES_FP( Y, X );
+
+ PUT_ULONG_BE( Y, output, 0 );
+ PUT_ULONG_BE( X, output, 4 );
+
+ return( 0 );
+}
+
+/*
+ * DES-CBC buffer encryption/decryption
+ */
+int des_crypt_cbc( des_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[8];
+
+ if( length % 8 )
+ return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+ if( mode == DES_ENCRYPT )
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ des_crypt_ecb( ctx, output, output );
+ memcpy( iv, output, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+ else /* DES_DECRYPT */
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 8 );
+ des_crypt_ecb( ctx, input, output );
+
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * 3DES-ECB block encryption/decryption
+ */
+int des3_crypt_ecb( des3_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] )
+{
+ int i;
+ unsigned long X, Y, T, *SK;
+
+ SK = ctx->sk;
+
+ GET_ULONG_BE( X, input, 0 );
+ GET_ULONG_BE( Y, input, 4 );
+
+ DES_IP( X, Y );
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( X, Y );
+ DES_ROUND( Y, X );
+ }
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ DES_FP( Y, X );
+
+ PUT_ULONG_BE( Y, output, 0 );
+ PUT_ULONG_BE( X, output, 4 );
+
+ return( 0 );
+}
+
+/*
+ * 3DES-CBC buffer encryption/decryption
+ */
+int des3_crypt_cbc( des3_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[8];
+
+ if( length % 8 )
+ return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH );
+
+ if( mode == DES_ENCRYPT )
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ des3_crypt_ecb( ctx, output, output );
+ memcpy( iv, output, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+ else /* DES_DECRYPT */
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 8 );
+ des3_crypt_ecb( ctx, input, output );
+
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * DES and 3DES test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
+ */
+static const unsigned char des3_test_keys[24] =
+{
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+ 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+ 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+static const unsigned char des3_test_iv[8] =
+{
+ 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
+static const unsigned char des3_test_buf[8] =
+{
+ 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char des3_test_ecb_dec[3][8] =
+{
+ { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+ { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+ { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+static const unsigned char des3_test_ecb_enc[3][8] =
+{
+ { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+ { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+ { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+static const unsigned char des3_test_cbc_dec[3][8] =
+{
+ { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
+ { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
+ { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+};
+
+static const unsigned char des3_test_cbc_enc[3][8] =
+{
+ { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
+ { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
+ { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+};
+
+/*
+ * Checkup routine
+ */
+int des_self_test( int verbose )
+{
+ int i, j, u, v;
+ des_context ctx;
+ des3_context ctx3;
+ unsigned char key[24];
+ unsigned char buf[8];
+ unsigned char prv[8];
+ unsigned char iv[8];
+
+ memset( key, 0, 24 );
+
+ /*
+ * ECB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " DES%c-ECB-%3d (%s): ",
+ ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+ ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( buf, des3_test_buf, 8 );
+
+ switch( i )
+ {
+ case 0:
+ des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
+ break;
+
+ case 1:
+ des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
+ break;
+
+ case 2:
+ des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
+ break;
+
+ case 3:
+ des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
+ break;
+
+ case 4:
+ des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
+ break;
+
+ case 5:
+ des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
+ break;
+
+ default:
+ return( 1 );
+ }
+
+ for( j = 0; j < 10000; j++ )
+ {
+ if( u == 0 )
+ des_crypt_ecb( &ctx, buf, buf );
+ else
+ des3_crypt_ecb( &ctx3, buf, buf );
+ }
+
+ if( ( v == DES_DECRYPT &&
+ memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
+ ( v != DES_DECRYPT &&
+ memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ /*
+ * CBC mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ printf( " DES%c-CBC-%3d (%s): ",
+ ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+ ( v == DES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, des3_test_iv, 8 );
+ memcpy( prv, des3_test_iv, 8 );
+ memcpy( buf, des3_test_buf, 8 );
+
+ switch( i )
+ {
+ case 0:
+ des_setkey_dec( &ctx, (unsigned char *) des3_test_keys );
+ break;
+
+ case 1:
+ des_setkey_enc( &ctx, (unsigned char *) des3_test_keys );
+ break;
+
+ case 2:
+ des3_set2key_dec( &ctx3, (unsigned char *) des3_test_keys );
+ break;
+
+ case 3:
+ des3_set2key_enc( &ctx3, (unsigned char *) des3_test_keys );
+ break;
+
+ case 4:
+ des3_set3key_dec( &ctx3, (unsigned char *) des3_test_keys );
+ break;
+
+ case 5:
+ des3_set3key_enc( &ctx3, (unsigned char *) des3_test_keys );
+ break;
+
+ default:
+ return( 1 );
+ }
+
+ if( v == DES_DECRYPT )
+ {
+ for( j = 0; j < 10000; j++ )
+ {
+ if( u == 0 )
+ des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+ else
+ des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+ }
+ }
+ else
+ {
+ for( j = 0; j < 10000; j++ )
+ {
+ unsigned char tmp[8];
+
+ if( u == 0 )
+ des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+ else
+ des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+
+ memcpy( tmp, prv, 8 );
+ memcpy( prv, buf, 8 );
+ memcpy( buf, tmp, 8 );
+ }
+
+ memcpy( buf, prv, 8 );
+ }
+
+ if( ( v == DES_DECRYPT &&
+ memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
+ ( v != DES_DECRYPT &&
+ memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/dhm.c b/polarssl/src/library/dhm.c
new file mode 100644
index 0000000..4a59571
--- /dev/null
+++ b/polarssl/src/library/dhm.c
@@ -0,0 +1,296 @@
+/*
+ * Diffie-Hellman-Merkle key exchange
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * Reference:
+ *
+ * http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_DHM_C)
+
+#include "polarssl/dhm.h"
+
+/*
+ * helper to validate the mpi size and import it
+ */
+static int dhm_read_bignum( mpi *X,
+ unsigned char **p,
+ const unsigned char *end )
+{
+ int ret, n;
+
+ if( end - *p < 2 )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ n = ( (*p)[0] << 8 ) | (*p)[1];
+ (*p) += 2;
+
+ if( (int)( end - *p ) < n )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
+ return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED + ret );
+
+ (*p) += n;
+
+ return( 0 );
+}
+
+/*
+ * Verify sanity of parameter with regards to P
+ *
+ * Parameter should be: 2 <= public_param <= P - 2
+ *
+ * For more information on the attack, see:
+ * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
+ * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
+ */
+static int dhm_check_range( const mpi *param, const mpi *P )
+{
+ mpi L, U;
+ int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA;
+
+ mpi_init( &L ); mpi_init( &U );
+ mpi_lset( &L, 2 );
+ mpi_sub_int( &U, P, 2 );
+
+ if( mpi_cmp_mpi( param, &L ) >= 0 &&
+ mpi_cmp_mpi( param, &U ) <= 0 )
+ {
+ ret = 0;
+ }
+
+ mpi_free( &L ); mpi_free( &U );
+
+ return( ret );
+}
+
+/*
+ * Parse the ServerKeyExchange parameters
+ */
+int dhm_read_params( dhm_context *ctx,
+ unsigned char **p,
+ const unsigned char *end )
+{
+ int ret;
+
+ memset( ctx, 0, sizeof( dhm_context ) );
+
+ if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
+ ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
+ ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
+ return( ret );
+
+ if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
+ return( ret );
+
+ ctx->len = mpi_size( &ctx->P );
+
+ if( end - *p < 2 )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ return( 0 );
+}
+
+/*
+ * Setup and write the ServerKeyExchange parameters
+ */
+int dhm_make_params( dhm_context *ctx, int x_size,
+ unsigned char *output, size_t *olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret, count = 0;
+ size_t n1, n2, n3;
+ unsigned char *p;
+
+ /*
+ * Generate X as large as possible ( < P )
+ */
+ do
+ {
+ mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
+
+ while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
+ mpi_shift_r( &ctx->X, 1 );
+
+ if( count++ > 10 )
+ return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED );
+ }
+ while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
+
+ /*
+ * Calculate GX = G^X mod P
+ */
+ MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
+ &ctx->P , &ctx->RP ) );
+
+ if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
+ return( ret );
+
+ /*
+ * export P, G, GX
+ */
+#define DHM_MPI_EXPORT(X,n) \
+ MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
+ *p++ = (unsigned char)( n >> 8 ); \
+ *p++ = (unsigned char)( n ); p += n;
+
+ n1 = mpi_size( &ctx->P );
+ n2 = mpi_size( &ctx->G );
+ n3 = mpi_size( &ctx->GX );
+
+ p = output;
+ DHM_MPI_EXPORT( &ctx->P , n1 );
+ DHM_MPI_EXPORT( &ctx->G , n2 );
+ DHM_MPI_EXPORT( &ctx->GX, n3 );
+
+ *olen = p - output;
+
+ ctx->len = n1;
+
+cleanup:
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Import the peer's public value G^Y
+ */
+int dhm_read_public( dhm_context *ctx,
+ const unsigned char *input, size_t ilen )
+{
+ int ret;
+
+ if( ctx == NULL || ilen < 1 || ilen > ctx->len )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
+ return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Create own private value X and export G^X
+ */
+int dhm_make_public( dhm_context *ctx, int x_size,
+ unsigned char *output, size_t olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret, count = 0;
+
+ if( ctx == NULL || olen < 1 || olen > ctx->len )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ /*
+ * generate X and calculate GX = G^X mod P
+ */
+ do
+ {
+ mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
+
+ while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
+ mpi_shift_r( &ctx->X, 1 );
+
+ if( count++ > 10 )
+ return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED );
+ }
+ while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
+
+ MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
+ &ctx->P , &ctx->RP ) );
+
+ if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
+ return( ret );
+
+ MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
+
+cleanup:
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Derive and export the shared secret (G^Y)^X mod P
+ */
+int dhm_calc_secret( dhm_context *ctx,
+ unsigned char *output, size_t *olen )
+{
+ int ret;
+
+ if( ctx == NULL || *olen < ctx->len )
+ return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
+
+ MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
+ &ctx->P, &ctx->RP ) );
+
+ if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
+ return( ret );
+
+ *olen = mpi_size( &ctx->K );
+
+ MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
+
+cleanup:
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Free the components of a DHM key
+ */
+void dhm_free( dhm_context *ctx )
+{
+ mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
+ mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
+ mpi_free( &ctx->P );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
+int dhm_self_test( int verbose )
+{
+ return( verbose++ );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/entropy.c b/polarssl/src/library/entropy.c
new file mode 100644
index 0000000..9662454
--- /dev/null
+++ b/polarssl/src/library/entropy.c
@@ -0,0 +1,204 @@
+/*
+ * Entropy accumulator implementation
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ENTROPY_C)
+
+#include "polarssl/entropy.h"
+#include "polarssl/entropy_poll.h"
+
+#if defined(POLARSSL_HAVEGE_C)
+#include "polarssl/havege.h"
+#endif
+
+#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
+
+void entropy_init( entropy_context *ctx )
+{
+ memset( ctx, 0, sizeof(entropy_context) );
+
+ sha4_starts( &ctx->accumulator, 0 );
+#if defined(POLARSSL_HAVEGE_C)
+ havege_init( &ctx->havege_data );
+#endif
+
+#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+ entropy_add_source( ctx, platform_entropy_poll, NULL,
+ ENTROPY_MIN_PLATFORM );
+#endif
+#if defined(POLARSSL_TIMING_C)
+ entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
+#endif
+#if defined(POLARSSL_HAVEGE_C)
+ entropy_add_source( ctx, havege_poll, &ctx->havege_data,
+ ENTROPY_MIN_HAVEGE );
+#endif
+#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
+}
+
+int entropy_add_source( entropy_context *ctx,
+ f_source_ptr f_source, void *p_source,
+ size_t threshold )
+{
+ int index = ctx->source_count;
+
+ if( index >= ENTROPY_MAX_SOURCES )
+ return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
+
+ ctx->source[index].f_source = f_source;
+ ctx->source[index].p_source = p_source;
+ ctx->source[index].threshold = threshold;
+
+ ctx->source_count++;
+
+ return( 0 );
+}
+
+/*
+ * Entropy accumulator update
+ */
+int entropy_update( entropy_context *ctx, unsigned char source_id,
+ const unsigned char *data, size_t len )
+{
+ unsigned char header[2];
+ unsigned char tmp[ENTROPY_BLOCK_SIZE];
+ size_t use_len = len;
+ const unsigned char *p = data;
+
+ if( use_len > ENTROPY_BLOCK_SIZE )
+ {
+ sha4( data, len, tmp, 0 );
+
+ p = tmp;
+ use_len = ENTROPY_BLOCK_SIZE;
+ }
+
+ header[0] = source_id;
+ header[1] = use_len & 0xFF;
+
+ sha4_update( &ctx->accumulator, header, 2 );
+ sha4_update( &ctx->accumulator, p, use_len );
+
+ return( 0 );
+}
+
+int entropy_update_manual( entropy_context *ctx,
+ const unsigned char *data, size_t len )
+{
+ return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
+}
+
+/*
+ * Run through the different sources to add entropy to our accumulator
+ */
+int entropy_gather( entropy_context *ctx )
+{
+ int ret, i;
+ unsigned char buf[ENTROPY_MAX_GATHER];
+ size_t olen;
+
+ if( ctx->source_count == 0 )
+ return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
+
+ /*
+ * Run through our entropy sources
+ */
+ for( i = 0; i < ctx->source_count; i++ )
+ {
+ olen = 0;
+ if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
+ buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /*
+ * Add if we actually gathered something
+ */
+ if( olen > 0 )
+ {
+ entropy_update( ctx, (unsigned char) i, buf, olen );
+ ctx->source[i].size += olen;
+ }
+ }
+
+ return( 0 );
+}
+
+int entropy_func( void *data, unsigned char *output, size_t len )
+{
+ int ret, count = 0, i, reached;
+ entropy_context *ctx = (entropy_context *) data;
+ unsigned char buf[ENTROPY_BLOCK_SIZE];
+
+ if( len > ENTROPY_BLOCK_SIZE )
+ return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+
+ /*
+ * Always gather extra entropy before a call
+ */
+ do
+ {
+ if( count++ > ENTROPY_MAX_LOOP )
+ return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+
+ if( ( ret = entropy_gather( ctx ) ) != 0 )
+ return( ret );
+
+ reached = 0;
+
+ for( i = 0; i < ctx->source_count; i++ )
+ if( ctx->source[i].size >= ctx->source[i].threshold )
+ reached++;
+ }
+ while( reached != ctx->source_count );
+
+ memset( buf, 0, ENTROPY_BLOCK_SIZE );
+
+ sha4_finish( &ctx->accumulator, buf );
+
+ /*
+ * Perform second SHA-512 on entropy
+ */
+ sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
+
+ /*
+ * Reset accumulator and counters and recycle existing entropy
+ */
+ memset( &ctx->accumulator, 0, sizeof( sha4_context ) );
+ sha4_starts( &ctx->accumulator, 0 );
+ sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
+
+ for( i = 0; i < ctx->source_count; i++ )
+ ctx->source[i].size = 0;
+
+ memcpy( output, buf, len );
+
+ return( 0 );
+}
+
+#endif
diff --git a/polarssl/src/library/entropy_poll.c b/polarssl/src/library/entropy_poll.c
new file mode 100644
index 0000000..a0c9b7b
--- /dev/null
+++ b/polarssl/src/library/entropy_poll.c
@@ -0,0 +1,136 @@
+/*
+ * Platform-specific and custom entropy polling functions
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ENTROPY_C)
+
+#include "polarssl/entropy.h"
+#include "polarssl/entropy_poll.h"
+
+#if defined(POLARSSL_TIMING_C)
+#include "polarssl/timing.h"
+#endif
+#if defined(POLARSSL_HAVEGE_C)
+#include "polarssl/havege.h"
+#endif
+
+#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
+#if defined(_WIN32)
+
+#include <windows.h>
+#if !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x0400
+#endif
+#include <wincrypt.h>
+
+int platform_entropy_poll( void *data, unsigned char *output, size_t len,
+ size_t *olen )
+{
+ HCRYPTPROV provider;
+ ((void) data);
+ *olen = 0;
+
+ if( CryptAcquireContext( &provider, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
+ {
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+ }
+
+ if( CryptGenRandom( provider, len, output ) == FALSE )
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+ CryptReleaseContext( provider, 0 );
+ *olen = len;
+
+ return( 0 );
+}
+#else
+
+#include <stdio.h>
+
+int platform_entropy_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ FILE *file;
+ size_t ret;
+ ((void) data);
+
+ *olen = 0;
+
+ file = fopen( "/dev/urandom", "rb" );
+ if( file == NULL )
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+ ret = fread( output, 1, len, file );
+ if( ret != len )
+ {
+ fclose( file );
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+ }
+
+ fclose( file );
+ *olen = len;
+
+ return( 0 );
+}
+#endif
+#endif
+
+#if defined(POLARSSL_TIMING_C)
+int hardclock_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ unsigned long timer = hardclock();
+ ((void) data);
+ *olen = 0;
+
+ if( len < sizeof(unsigned long) )
+ return( 0 );
+
+ memcpy( output, &timer, sizeof(unsigned long) );
+ *olen = sizeof(unsigned long);
+
+ return( 0 );
+}
+#endif
+
+#if defined(POLARSSL_HAVEGE_C)
+int havege_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ havege_state *hs = (havege_state *) data;
+ *olen = 0;
+
+ if( havege_random( hs, output, len ) != 0 )
+ return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+
+ *olen = len;
+
+ return( 0 );
+}
+#endif
+
+#endif /* POLARSSL_ENTROPY_C */
diff --git a/polarssl/src/library/error.c b/polarssl/src/library/error.c
new file mode 100644
index 0000000..61ff9c7
--- /dev/null
+++ b/polarssl/src/library/error.c
@@ -0,0 +1,525 @@
+/*
+ * Error message information
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_ERROR_C)
+
+#if defined(POLARSSL_AES_C)
+#include "polarssl/aes.h"
+#endif
+
+#if defined(POLARSSL_BASE64_C)
+#include "polarssl/base64.h"
+#endif
+
+#if defined(POLARSSL_BIGNUM_C)
+#include "polarssl/bignum.h"
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+#include "polarssl/camellia.h"
+#endif
+
+#if defined(POLARSSL_CIPHER_C)
+#include "polarssl/cipher.h"
+#endif
+
+#if defined(POLARSSL_CTR_DRBG_C)
+#include "polarssl/ctr_drbg.h"
+#endif
+
+#if defined(POLARSSL_DES_C)
+#include "polarssl/des.h"
+#endif
+
+#if defined(POLARSSL_DHM_C)
+#include "polarssl/dhm.h"
+#endif
+
+#if defined(POLARSSL_ENTROPY_C)
+#include "polarssl/entropy.h"
+#endif
+
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
+#if defined(POLARSSL_MD_C)
+#include "polarssl/md.h"
+#endif
+
+#if defined(POLARSSL_MD2_C)
+#include "polarssl/md2.h"
+#endif
+
+#if defined(POLARSSL_MD4_C)
+#include "polarssl/md4.h"
+#endif
+
+#if defined(POLARSSL_MD5_C)
+#include "polarssl/md5.h"
+#endif
+
+#if defined(POLARSSL_NET_C)
+#include "polarssl/net.h"
+#endif
+
+#if defined(POLARSSL_PADLOCK_C)
+#include "polarssl/padlock.h"
+#endif
+
+#if defined(POLARSSL_PEM_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_RSA_C)
+#include "polarssl/rsa.h"
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+#include "polarssl/sha1.h"
+#endif
+
+#if defined(POLARSSL_SHA2_C)
+#include "polarssl/sha2.h"
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+#include "polarssl/sha4.h"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C)
+#include "polarssl/ssl.h"
+#endif
+
+#if defined(POLARSSL_X509_PARSE_C)
+#include "polarssl/x509.h"
+#endif
+
+#if defined(POLARSSL_XTEA_C)
+#include "polarssl/xtea.h"
+#endif
+
+
+#include <string.h>
+
+#if defined _MSC_VER && !defined snprintf
+#define snprintf _snprintf
+#endif
+
+void error_strerror( int ret, char *buf, size_t buflen )
+{
+ size_t len;
+ int use_ret;
+
+ memset( buf, 0x00, buflen );
+
+ if( ret < 0 )
+ ret = -ret;
+
+ if( ret & 0xFF80 )
+ {
+ use_ret = ret & 0xFF80;
+
+ // High level error codes
+ //
+#if defined(POLARSSL_CIPHER_C)
+ if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "CIPHER - The selected feature is not available" );
+ if( use_ret == -(POLARSSL_ERR_CIPHER_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "CIPHER - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_CIPHER_ALLOC_FAILED) )
+ snprintf( buf, buflen, "CIPHER - Failed to allocate memory" );
+ if( use_ret == -(POLARSSL_ERR_CIPHER_INVALID_PADDING) )
+ snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" );
+ if( use_ret == -(POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED) )
+ snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" );
+#endif /* POLARSSL_CIPHER_C */
+
+#if defined(POLARSSL_DHM_C)
+ if( use_ret == -(POLARSSL_ERR_DHM_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "DHM - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_DHM_READ_PARAMS_FAILED) )
+ snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" );
+ if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED) )
+ snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" );
+ if( use_ret == -(POLARSSL_ERR_DHM_READ_PUBLIC_FAILED) )
+ snprintf( buf, buflen, "DHM - Reading of the public values failed" );
+ if( use_ret == -(POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED) )
+ snprintf( buf, buflen, "DHM - Makeing of the public value failed" );
+ if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) )
+ snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" );
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_MD_C)
+ if( use_ret == -(POLARSSL_ERR_MD_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "MD - The selected feature is not available" );
+ if( use_ret == -(POLARSSL_ERR_MD_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "MD - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_MD_ALLOC_FAILED) )
+ snprintf( buf, buflen, "MD - Failed to allocate memory" );
+ if( use_ret == -(POLARSSL_ERR_MD_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "MD - Opening or reading of file failed" );
+#endif /* POLARSSL_MD_C */
+
+#if defined(POLARSSL_PEM_C)
+ if( use_ret == -(POLARSSL_ERR_PEM_NO_HEADER_PRESENT) )
+ snprintf( buf, buflen, "PEM - No PEM header found" );
+ if( use_ret == -(POLARSSL_ERR_PEM_INVALID_DATA) )
+ snprintf( buf, buflen, "PEM - PEM string is not as expected" );
+ if( use_ret == -(POLARSSL_ERR_PEM_MALLOC_FAILED) )
+ snprintf( buf, buflen, "PEM - Failed to allocate memory" );
+ if( use_ret == -(POLARSSL_ERR_PEM_INVALID_ENC_IV) )
+ snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" );
+ if( use_ret == -(POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG) )
+ snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" );
+ if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_REQUIRED) )
+ snprintf( buf, buflen, "PEM - Private key password can't be empty" );
+ if( use_ret == -(POLARSSL_ERR_PEM_PASSWORD_MISMATCH) )
+ snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" );
+ if( use_ret == -(POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" );
+#endif /* POLARSSL_PEM_C */
+
+#if defined(POLARSSL_RSA_C)
+ if( use_ret == -(POLARSSL_ERR_RSA_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "RSA - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_RSA_INVALID_PADDING) )
+ snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" );
+ if( use_ret == -(POLARSSL_ERR_RSA_KEY_GEN_FAILED) )
+ snprintf( buf, buflen, "RSA - Something failed during generation of a key" );
+ if( use_ret == -(POLARSSL_ERR_RSA_KEY_CHECK_FAILED) )
+ snprintf( buf, buflen, "RSA - Key failed to pass the libraries validity check" );
+ if( use_ret == -(POLARSSL_ERR_RSA_PUBLIC_FAILED) )
+ snprintf( buf, buflen, "RSA - The public key operation failed" );
+ if( use_ret == -(POLARSSL_ERR_RSA_PRIVATE_FAILED) )
+ snprintf( buf, buflen, "RSA - The private key operation failed" );
+ if( use_ret == -(POLARSSL_ERR_RSA_VERIFY_FAILED) )
+ snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" );
+ if( use_ret == -(POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE) )
+ snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" );
+ if( use_ret == -(POLARSSL_ERR_RSA_RNG_FAILED) )
+ snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" );
+#endif /* POLARSSL_RSA_C */
+
+#if defined(POLARSSL_SSL_TLS_C)
+ if( use_ret == -(POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "SSL - The requested feature is not available" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "SSL - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_SSL_INVALID_MAC) )
+ snprintf( buf, buflen, "SSL - Verification of the message MAC failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_INVALID_RECORD) )
+ snprintf( buf, buflen, "SSL - An invalid SSL record was received" );
+ if( use_ret == -(POLARSSL_ERR_SSL_CONN_EOF) )
+ snprintf( buf, buflen, "SSL - The connection indicated an EOF" );
+ if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_CIPHER) )
+ snprintf( buf, buflen, "SSL - An unknown cipher was received" );
+ if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) )
+ snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" );
+ if( use_ret == -(POLARSSL_ERR_SSL_NO_SESSION_FOUND) )
+ snprintf( buf, buflen, "SSL - No session to recover was found" );
+ if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) )
+ snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" );
+ if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) )
+ snprintf( buf, buflen, "SSL - DESCRIPTION MISSING" );
+ if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED) )
+ snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" );
+ if( use_ret == -(POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED) )
+ snprintf( buf, buflen, "SSL - The own private key is not set, but needed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED) )
+ snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" );
+ if( use_ret == -(POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE) )
+ snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" );
+ if( use_ret == -(POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE) )
+ snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" );
+ if( use_ret == -(POLARSSL_ERR_SSL_PEER_VERIFY_FAILED) )
+ snprintf( buf, buflen, "SSL - Verification of our peer failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) )
+ snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO) )
+ snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO) )
+ snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE) )
+ snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) )
+ snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) )
+ snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) )
+ snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) )
+ snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP) )
+ snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Read Public" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS) )
+ snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM Calculate Secret" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) )
+ snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) )
+ snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_BAD_HS_FINISHED) )
+ snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" );
+ if( use_ret == -(POLARSSL_ERR_SSL_MALLOC_FAILED) )
+ snprintf( buf, buflen, "SSL - Memory allocation failed" );
+#endif /* POLARSSL_SSL_TLS_C */
+
+#if defined(POLARSSL_X509_PARSE_C)
+ if( use_ret == -(POLARSSL_ERR_X509_FEATURE_UNAVAILABLE) )
+ snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PEM) )
+ snprintf( buf, buflen, "X509 - The PEM-encoded certificate contains invalid elements, e.g. invalid character" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_FORMAT) )
+ snprintf( buf, buflen, "X509 - The certificate format is invalid, e.g. different type expected" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_VERSION) )
+ snprintf( buf, buflen, "X509 - The certificate version element is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SERIAL) )
+ snprintf( buf, buflen, "X509 - The serial tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_ALG) )
+ snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_NAME) )
+ snprintf( buf, buflen, "X509 - The name tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_DATE) )
+ snprintf( buf, buflen, "X509 - The date tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_PUBKEY) )
+ snprintf( buf, buflen, "X509 - The pubkey tag or value is invalid (only RSA is supported)" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE) )
+ snprintf( buf, buflen, "X509 - The signature tag or value invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS) )
+ snprintf( buf, buflen, "X509 - The extension tag or value is invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION) )
+ snprintf( buf, buflen, "X509 - Certificate or CRL has an unsupported version number" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG) )
+ snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" );
+ if( use_ret == -(POLARSSL_ERR_X509_UNKNOWN_PK_ALG) )
+ snprintf( buf, buflen, "X509 - Key algorithm is unsupported (only RSA is supported)" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_SIG_MISMATCH) )
+ snprintf( buf, buflen, "X509 - Certificate signature algorithms do not match. (see \\c ::x509_cert sig_oid)" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_VERIFY_FAILED) )
+ snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" );
+ if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_VERSION) )
+ snprintf( buf, buflen, "X509 - Unsupported RSA key version" );
+ if( use_ret == -(POLARSSL_ERR_X509_KEY_INVALID_FORMAT) )
+ snprintf( buf, buflen, "X509 - Invalid RSA key tag or value" );
+ if( use_ret == -(POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT) )
+ snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" );
+ if( use_ret == -(POLARSSL_ERR_X509_INVALID_INPUT) )
+ snprintf( buf, buflen, "X509 - Input invalid" );
+ if( use_ret == -(POLARSSL_ERR_X509_MALLOC_FAILED) )
+ snprintf( buf, buflen, "X509 - Allocation of memory failed" );
+ if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "X509 - Read/write of file failed" );
+#endif /* POLARSSL_X509_PARSE_C */
+
+ if( strlen( buf ) == 0 )
+ snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
+ }
+
+ use_ret = ret & ~0xFF80;
+
+ if( use_ret == 0 )
+ return;
+
+ // If high level code is present, make a concatenation between both
+ // error strings.
+ //
+ len = strlen( buf );
+
+ if( len > 0 )
+ {
+ if( buflen - len < 5 )
+ return;
+
+ snprintf( buf + len, buflen - len, " : " );
+
+ buf += len + 3;
+ buflen -= len + 3;
+ }
+
+ // Low level error codes
+ //
+#if defined(POLARSSL_AES_C)
+ if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) )
+ snprintf( buf, buflen, "AES - Invalid key length" );
+ if( use_ret == -(POLARSSL_ERR_AES_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "AES - Invalid data input length" );
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+ if( use_ret == -(POLARSSL_ERR_ASN1_OUT_OF_DATA) )
+ snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_UNEXPECTED_TAG) )
+ snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_LENGTH) )
+ snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_LENGTH_MISMATCH) )
+ snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_INVALID_DATA) )
+ snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_MALLOC_FAILED) )
+ snprintf( buf, buflen, "ASN1 - Memory allocation failed" );
+ if( use_ret == -(POLARSSL_ERR_ASN1_BUF_TOO_SMALL) )
+ snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" );
+#endif /* POLARSSL_ASN1_PARSE_C */
+
+#if defined(POLARSSL_BASE64_C)
+ if( use_ret == -(POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL) )
+ snprintf( buf, buflen, "BASE64 - Output buffer too small" );
+ if( use_ret == -(POLARSSL_ERR_BASE64_INVALID_CHARACTER) )
+ snprintf( buf, buflen, "BASE64 - Invalid character in input" );
+#endif /* POLARSSL_BASE64_C */
+
+#if defined(POLARSSL_BIGNUM_C)
+ if( use_ret == -(POLARSSL_ERR_MPI_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" );
+ if( use_ret == -(POLARSSL_ERR_MPI_BAD_INPUT_DATA) )
+ snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" );
+ if( use_ret == -(POLARSSL_ERR_MPI_INVALID_CHARACTER) )
+ snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" );
+ if( use_ret == -(POLARSSL_ERR_MPI_BUFFER_TOO_SMALL) )
+ snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" );
+ if( use_ret == -(POLARSSL_ERR_MPI_NEGATIVE_VALUE) )
+ snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" );
+ if( use_ret == -(POLARSSL_ERR_MPI_DIVISION_BY_ZERO) )
+ snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" );
+ if( use_ret == -(POLARSSL_ERR_MPI_NOT_ACCEPTABLE) )
+ snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" );
+ if( use_ret == -(POLARSSL_ERR_MPI_MALLOC_FAILED) )
+ snprintf( buf, buflen, "BIGNUM - Memory allocation failed" );
+#endif /* POLARSSL_BIGNUM_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+ if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH) )
+ snprintf( buf, buflen, "CAMELLIA - Invalid key length" );
+ if( use_ret == -(POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_CTR_DRBG_C)
+ if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) )
+ snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" );
+ if( use_ret == -(POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG) )
+ snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" );
+ if( use_ret == -(POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG) )
+ snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" );
+ if( use_ret == -(POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" );
+#endif /* POLARSSL_CTR_DRBG_C */
+
+#if defined(POLARSSL_DES_C)
+ if( use_ret == -(POLARSSL_ERR_DES_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "DES - The data input has an invalid length" );
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ENTROPY_C)
+ if( use_ret == -(POLARSSL_ERR_ENTROPY_SOURCE_FAILED) )
+ snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" );
+ if( use_ret == -(POLARSSL_ERR_ENTROPY_MAX_SOURCES) )
+ snprintf( buf, buflen, "ENTROPY - No more sources can be added" );
+ if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) )
+ snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" );
+#endif /* POLARSSL_ENTROPY_C */
+
+#if defined(POLARSSL_GCM_C)
+ if( use_ret == -(POLARSSL_ERR_GCM_AUTH_FAILED) )
+ snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
+ if( use_ret == -(POLARSSL_ERR_GCM_BAD_INPUT) )
+ snprintf( buf, buflen, "GCM - Bad input parameters to function" );
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_MD2_C)
+ if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "MD2 - Read/write error in file" );
+#endif /* POLARSSL_MD2_C */
+
+#if defined(POLARSSL_MD4_C)
+ if( use_ret == -(POLARSSL_ERR_MD4_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "MD4 - Read/write error in file" );
+#endif /* POLARSSL_MD4_C */
+
+#if defined(POLARSSL_MD5_C)
+ if( use_ret == -(POLARSSL_ERR_MD5_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "MD5 - Read/write error in file" );
+#endif /* POLARSSL_MD5_C */
+
+#if defined(POLARSSL_NET_C)
+ if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) )
+ snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" );
+ if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) )
+ snprintf( buf, buflen, "NET - Failed to open a socket" );
+ if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) )
+ snprintf( buf, buflen, "NET - The connection to the given server / port failed" );
+ if( use_ret == -(POLARSSL_ERR_NET_BIND_FAILED) )
+ snprintf( buf, buflen, "NET - Binding of the socket failed" );
+ if( use_ret == -(POLARSSL_ERR_NET_LISTEN_FAILED) )
+ snprintf( buf, buflen, "NET - Could not listen on the socket" );
+ if( use_ret == -(POLARSSL_ERR_NET_ACCEPT_FAILED) )
+ snprintf( buf, buflen, "NET - Could not accept the incoming connection" );
+ if( use_ret == -(POLARSSL_ERR_NET_RECV_FAILED) )
+ snprintf( buf, buflen, "NET - Reading information from the socket failed" );
+ if( use_ret == -(POLARSSL_ERR_NET_SEND_FAILED) )
+ snprintf( buf, buflen, "NET - Sending information through the socket failed" );
+ if( use_ret == -(POLARSSL_ERR_NET_CONN_RESET) )
+ snprintf( buf, buflen, "NET - Connection was reset by peer" );
+ if( use_ret == -(POLARSSL_ERR_NET_WANT_READ) )
+ snprintf( buf, buflen, "NET - Connection requires a read call" );
+ if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) )
+ snprintf( buf, buflen, "NET - Connection requires a write call" );
+#endif /* POLARSSL_NET_C */
+
+#if defined(POLARSSL_PADLOCK_C)
+ if( use_ret == -(POLARSSL_ERR_PADLOCK_DATA_MISALIGNED) )
+ snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
+#endif /* POLARSSL_PADLOCK_C */
+
+#if defined(POLARSSL_SHA1_C)
+ if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "SHA1 - Read/write error in file" );
+#endif /* POLARSSL_SHA1_C */
+
+#if defined(POLARSSL_SHA2_C)
+ if( use_ret == -(POLARSSL_ERR_SHA2_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "SHA2 - Read/write error in file" );
+#endif /* POLARSSL_SHA2_C */
+
+#if defined(POLARSSL_SHA4_C)
+ if( use_ret == -(POLARSSL_ERR_SHA4_FILE_IO_ERROR) )
+ snprintf( buf, buflen, "SHA4 - Read/write error in file" );
+#endif /* POLARSSL_SHA4_C */
+
+#if defined(POLARSSL_XTEA_C)
+ if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) )
+ snprintf( buf, buflen, "XTEA - The data input has an invalid length" );
+#endif /* POLARSSL_XTEA_C */
+
+ if( strlen( buf ) != 0 )
+ return;
+
+ snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
+}
+
+#endif /* POLARSSL_VERBOSE_ERROR */
diff --git a/polarssl/src/library/gcm.c b/polarssl/src/library/gcm.c
new file mode 100644
index 0000000..616f724
--- /dev/null
+++ b/polarssl/src/library/gcm.c
@@ -0,0 +1,653 @@
+/*
+ * NIST SP800-38D compliant GCM implementation
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+ */
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_GCM_C)
+
+#include "polarssl/gcm.h"
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+static void gcm_gen_table( gcm_context *ctx )
+{
+ int i, j;
+ uint64_t hi, lo;
+ uint64_t vl, vh;
+ unsigned char h[16];
+
+ memset( h, 0, 16 );
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, h, h );
+
+ ctx->HH[0] = 0;
+ ctx->HL[0] = 0;
+
+ GET_ULONG_BE( hi, h, 0 );
+ GET_ULONG_BE( lo, h, 4 );
+ vh = (uint64_t) hi << 32 | lo;
+
+ GET_ULONG_BE( hi, h, 8 );
+ GET_ULONG_BE( lo, h, 12 );
+ vl = (uint64_t) hi << 32 | lo;
+
+ ctx->HL[8] = vl;
+ ctx->HH[8] = vh;
+
+ for( i = 4; i > 0; i >>= 1 )
+ {
+ uint32_t T = ( vl & 1 ) ? 0xe1000000U : 0;
+ vl = ( vh << 63 ) | ( vl >> 1 );
+ vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
+
+ ctx->HL[i] = vl;
+ ctx->HH[i] = vh;
+ }
+
+ for (i = 2; i < 16; i <<= 1 )
+ {
+ uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
+ vh = *HiH;
+ vl = *HiL;
+ for( j = 1; j < i; j++ )
+ {
+ HiH[j] = vh ^ ctx->HH[j];
+ HiL[j] = vl ^ ctx->HL[j];
+ }
+ }
+
+}
+
+int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize )
+{
+ int ret;
+
+ memset( ctx, 0, sizeof(gcm_context) );
+
+ if( ( ret = aes_setkey_enc( &ctx->aes_ctx, key, keysize ) ) != 0 )
+ return( ret );
+
+ gcm_gen_table( ctx );
+
+ return( 0 );
+}
+
+static const uint64_t last4[16] =
+{
+ 0x0000, 0x1c20, 0x3840, 0x2460,
+ 0x7080, 0x6ca0, 0x48c0, 0x54e0,
+ 0xe100, 0xfd20, 0xd940, 0xc560,
+ 0x9180, 0x8da0, 0xa9c0, 0xb5e0
+};
+
+void gcm_mult( gcm_context *ctx, const unsigned char x[16], unsigned char output[16] )
+{
+ int i = 0;
+ unsigned char z[16];
+ unsigned char v[16];
+ unsigned char lo, hi, rem;
+ uint64_t zh, zl;
+
+ memset( z, 0x00, 16 );
+ memcpy( v, x, 16 );
+
+ lo = x[15] & 0xf;
+ hi = x[15] >> 4;
+
+ zh = ctx->HH[lo];
+ zl = ctx->HL[lo];
+
+ for( i = 15; i >= 0; i-- )
+ {
+ lo = x[i] & 0xf;
+ hi = x[i] >> 4;
+
+ if( i != 15 )
+ {
+ rem = zl & 0xf;
+ zl = ( zh << 60 ) | ( zl >> 4 );
+ zh = ( zh >> 4 );
+ zh ^= (uint64_t) last4[rem] << 48;
+ zh ^= ctx->HH[lo];
+ zl ^= ctx->HL[lo];
+
+ }
+
+ rem = zl & 0xf;
+ zl = ( zh << 60 ) | ( zl >> 4 );
+ zh = ( zh >> 4 );
+ zh ^= (uint64_t) last4[rem] << 48;
+ zh ^= ctx->HH[hi];
+ zl ^= ctx->HL[hi];
+ }
+
+ PUT_ULONG_BE( zh >> 32, output, 0 );
+ PUT_ULONG_BE( zh, output, 4 );
+ PUT_ULONG_BE( zl >> 32, output, 8 );
+ PUT_ULONG_BE( zl, output, 12 );
+}
+
+int gcm_crypt_and_tag( gcm_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t tag_len,
+ unsigned char *tag )
+{
+ unsigned char y[16];
+ unsigned char ectr[16];
+ unsigned char buf[16];
+ unsigned char work_buf[16];
+ size_t i;
+ const unsigned char *p;
+ unsigned char *out_p = output;
+ size_t use_len;
+ size_t orig_len = length * 8;
+ size_t orig_add_len = add_len * 8;
+ unsigned char **xor_p;
+
+ memset( y, 0x00, 16 );
+ memset( work_buf, 0x00, 16 );
+ memset( tag, 0x00, tag_len );
+ memset( buf, 0x00, 16 );
+
+ if( ( mode == GCM_DECRYPT && output <= input && ( input - output ) < 8 ) ||
+ ( output > input && (size_t) ( output - input ) < length ) )
+ {
+ return( POLARSSL_ERR_GCM_BAD_INPUT );
+ }
+
+ if( mode == GCM_ENCRYPT )
+ xor_p = (unsigned char **) &out_p;
+ else
+ xor_p = (unsigned char **) &p;
+
+ if( iv_len == 12 )
+ {
+ memcpy( y, iv, iv_len );
+ y[15] = 1;
+ }
+ else
+ {
+ memset( work_buf, 0x00, 16 );
+ PUT_ULONG_BE( iv_len * 8, work_buf, 12 );
+
+ p = iv;
+ while( iv_len > 0 )
+ {
+ use_len = ( iv_len < 16 ) ? iv_len : 16;
+
+ if( use_len == 16 )
+ {
+ ((uint64_t *) y)[0] ^= ((uint64_t *) p)[0];
+ ((uint64_t *) y)[1] ^= ((uint64_t *) p)[1];
+ }
+ else
+ for( i = 0; i < use_len; i++ )
+ y[i] ^= p[i];
+
+ gcm_mult( ctx, y, y );
+
+ iv_len -= use_len;
+ p += use_len;
+ }
+
+ ((uint64_t *) y)[0] ^= ((uint64_t *) work_buf)[0];
+ ((uint64_t *) y)[1] ^= ((uint64_t *) work_buf)[1];
+
+ gcm_mult( ctx, y, y );
+ }
+
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
+ memcpy( tag, ectr, tag_len );
+
+ p = add;
+ while( add_len > 0 )
+ {
+ use_len = ( add_len < 16 ) ? add_len : 16;
+
+ if( use_len == 16 )
+ {
+ ((uint64_t *) buf)[0] ^= ((uint64_t *) p)[0];
+ ((uint64_t *) buf)[1] ^= ((uint64_t *) p)[1];
+ }
+ else
+ for( i = 0; i < use_len; i++ )
+ buf[i] ^= p[i];
+
+ gcm_mult( ctx, buf, buf );
+
+ add_len -= use_len;
+ p += use_len;
+ }
+
+ p = input;
+ while( length > 0 )
+ {
+ use_len = ( length < 16 ) ? length : 16;
+
+ for( i = 16; i > 0; i-- )
+ if( ++y[i - 1] != 0 )
+ break;
+
+ aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
+
+ if( use_len == 16 )
+ {
+ ((uint64_t *) out_p)[0] = ((uint64_t *) ectr)[0] ^
+ ((uint64_t *) p)[0];
+ ((uint64_t *) buf)[0] ^= ((uint64_t *) (*xor_p))[0];
+
+ ((uint64_t *) out_p)[1] = ((uint64_t *) ectr)[1] ^
+ ((uint64_t *) p)[1];
+ ((uint64_t *) buf)[1] ^= ((uint64_t *) (*xor_p))[1];
+ }
+ else
+ for( i = 0; i < use_len; i++ )
+ {
+ out_p[i] = ectr[i] ^ p[i];
+ buf[i] ^= (*xor_p)[i];
+ }
+
+ gcm_mult( ctx, buf, buf );
+
+ length -= use_len;
+ p += use_len;
+ out_p += use_len;
+ }
+
+ if( orig_len || orig_add_len )
+ {
+ memset( work_buf, 0x00, 16 );
+
+ PUT_ULONG_BE( orig_add_len , work_buf, 4 );
+ PUT_ULONG_BE( orig_len , work_buf, 12 );
+
+ ((uint64_t *) buf)[0] ^= ((uint64_t *) work_buf)[0];
+ ((uint64_t *) buf)[1] ^= ((uint64_t *) work_buf)[1];
+
+ gcm_mult( ctx, buf, buf );
+
+ if( tag_len == 16 )
+ {
+ ((uint64_t *) tag)[0] ^= ((uint64_t *) buf)[0];
+ ((uint64_t *) tag)[1] ^= ((uint64_t *) buf)[1];
+ }
+ else
+ for( i = 0; i < tag_len; i++ )
+ tag[i] ^= buf[i];
+ }
+
+ return( 0 );
+}
+
+int gcm_auth_decrypt( gcm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *tag,
+ size_t tag_len,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ unsigned char check_tag[16];
+
+ gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag );
+
+ if( memcmp( check_tag, tag, tag_len ) == 0 )
+ return( 0 );
+
+ memset( output, 0, length );
+
+ return( POLARSSL_ERR_GCM_AUTH_FAILED );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * GCM test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
+ */
+#define MAX_TESTS 6
+
+int key_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 1 };
+
+unsigned char key[MAX_TESTS][32] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+};
+
+size_t iv_len[MAX_TESTS] =
+ { 12, 12, 12, 12, 8, 60 };
+
+int iv_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 2 };
+
+unsigned char iv[MAX_TESTS][64] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
+ 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
+ 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
+ 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
+ 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
+ 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
+ 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
+ 0xa6, 0x37, 0xb3, 0x9b },
+};
+
+size_t add_len[MAX_TESTS] =
+ { 0, 0, 0, 20, 20, 20 };
+
+int add_index[MAX_TESTS] =
+ { 0, 0, 0, 1, 1, 1 };
+
+unsigned char additional[MAX_TESTS][64] =
+{
+ { 0x00 },
+ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2 },
+};
+
+size_t pt_len[MAX_TESTS] =
+ { 0, 16, 64, 60, 60, 60 };
+
+int pt_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 1 };
+
+unsigned char pt[MAX_TESTS][64] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+};
+
+unsigned char ct[MAX_TESTS * 3][64] =
+{
+ { 0x00 },
+ { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+ 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
+ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
+ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91 },
+ { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
+ 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
+ 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
+ 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
+ 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
+ 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
+ 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
+ 0xc2, 0x3f, 0x45, 0x98 },
+ { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
+ 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
+ 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
+ 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
+ 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
+ 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
+ 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
+ 0x4c, 0x34, 0xae, 0xe5 },
+ { 0x00 },
+ { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+ 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
+ { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
+ { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10 },
+ { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
+ 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
+ 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
+ 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
+ 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
+ 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
+ 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
+ 0xa0, 0xf0, 0x62, 0xf7 },
+ { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
+ 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
+ 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
+ 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
+ 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
+ 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
+ 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
+ 0xe9, 0xb7, 0x37, 0x3b },
+ { 0x00 },
+ { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
+ 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
+ { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
+ { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62 },
+ { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
+ 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
+ 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
+ 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
+ 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
+ 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
+ 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
+ 0xf4, 0x7c, 0x9b, 0x1f },
+ { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
+ 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
+ 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
+ 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
+ 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
+ 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
+ 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
+ 0x44, 0xae, 0x7e, 0x3f },
+};
+
+unsigned char tag[MAX_TESTS * 3][16] =
+{
+ { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+ 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
+ { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+ 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
+ { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+ { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+ 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
+ { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
+ 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
+ { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
+ 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
+ { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
+ 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
+ { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+ 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
+ { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+ 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
+ { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+ 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
+ { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
+ 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
+ { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
+ 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
+ { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
+ 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
+ { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
+ 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
+ { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
+ 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
+ { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
+ 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
+ { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
+ 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
+ { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
+ 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
+};
+
+int gcm_self_test( int verbose )
+{
+ gcm_context ctx;
+ unsigned char buf[64];
+ unsigned char tag_buf[16];
+ int i, j, ret;
+
+ for( j = 0; j < 3; j++ )
+ {
+ int key_len = 128 + 64 * j;
+
+ for( i = 0; i < MAX_TESTS; i++ )
+ {
+ printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "enc" );
+ gcm_init( &ctx, key[key_index[i]], key_len );
+
+ ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
+ pt_len[i],
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i],
+ pt[pt_index[i]], buf, 16, tag_buf );
+
+ if( ret != 0 ||
+ memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+
+ printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "dec" );
+ gcm_init( &ctx, key[key_index[i]], key_len );
+
+ ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
+ pt_len[i],
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i],
+ ct[j * 6 + i], buf, 16, tag_buf );
+
+ if( ret != 0 ||
+ memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+ }
+
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/havege.c b/polarssl/src/library/havege.c
new file mode 100644
index 0000000..ff302c5
--- /dev/null
+++ b/polarssl/src/library/havege.c
@@ -0,0 +1,231 @@
+/**
+ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The HAVEGE RNG was designed by Andre Seznec in 2002.
+ *
+ * http://www.irisa.fr/caps/projects/hipsor/publi.php
+ *
+ * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_HAVEGE_C)
+
+#include "polarssl/havege.h"
+#include "polarssl/timing.h"
+
+#include <string.h>
+#include <time.h>
+
+/* ------------------------------------------------------------------------
+ * On average, one iteration accesses two 8-word blocks in the havege WALK
+ * table, and generates 16 words in the RES array.
+ *
+ * The data read in the WALK table is updated and permuted after each use.
+ * The result of the hardware clock counter read is used for this update.
+ *
+ * 25 conditional tests are present. The conditional tests are grouped in
+ * two nested groups of 12 conditional tests and 1 test that controls the
+ * permutation; on average, there should be 6 tests executed and 3 of them
+ * should be mispredicted.
+ * ------------------------------------------------------------------------
+ */
+
+#define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
+
+#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
+
+#define TST1_LEAVE U1++; }
+#define TST2_LEAVE U2++; }
+
+#define ONE_ITERATION \
+ \
+ PTEST = PT1 >> 20; \
+ \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
+ \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
+ \
+ PTX = (PT1 >> 18) & 7; \
+ PT1 &= 0x1FFF; \
+ PT2 &= 0x1FFF; \
+ CLK = (int) hardclock(); \
+ \
+ i = 0; \
+ A = &WALK[PT1 ]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
+ \
+ IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
+ *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
+ *B = IN ^ U1; \
+ *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
+ *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
+ \
+ if( PTEST & 1 ) SWAP( A, C ); \
+ \
+ IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
+ *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
+ *B = IN; CLK = (int) hardclock(); \
+ *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
+ *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 4]; \
+ B = &WALK[PT2 ^ 1]; \
+ \
+ PTEST = PT2 >> 1; \
+ \
+ PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
+ PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
+ PTY = (PT2 >> 10) & 7; \
+ \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
+ \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
+ \
+ C = &WALK[PT1 ^ 5]; \
+ D = &WALK[PT2 ^ 5]; \
+ \
+ RES[i++] ^= *A; \
+ RES[i++] ^= *B; \
+ RES[i++] ^= *C; \
+ RES[i++] ^= *D; \
+ \
+ IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
+ *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
+ *B = IN ^ U2; \
+ *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
+ *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
+ \
+ A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
+ B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
+ C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
+ D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
+ \
+ IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
+ *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
+ *B = IN; \
+ *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
+ *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
+ \
+ PT1 = ( RES[(i - 8) ^ PTX] ^ \
+ WALK[PT1 ^ PTX ^ 7] ) & (~1); \
+ PT1 ^= (PT2 ^ 0x10) & 0x10; \
+ \
+ for( n++, i = 0; i < 16; i++ ) \
+ hs->pool[n % COLLECT_SIZE] ^= RES[i];
+
+/*
+ * Entropy gathering function
+ */
+static void havege_fill( havege_state *hs )
+{
+ int i, n = 0;
+ int U1, U2, *A, *B, *C, *D;
+ int PT1, PT2, *WALK, RES[16];
+ int PTX, PTY, CLK, PTEST, IN;
+
+ WALK = hs->WALK;
+ PT1 = hs->PT1;
+ PT2 = hs->PT2;
+
+ PTX = U1 = 0;
+ PTY = U2 = 0;
+
+ memset( RES, 0, sizeof( RES ) );
+
+ while( n < COLLECT_SIZE * 4 )
+ {
+ ONE_ITERATION
+ ONE_ITERATION
+ ONE_ITERATION
+ ONE_ITERATION
+ }
+
+ hs->PT1 = PT1;
+ hs->PT2 = PT2;
+
+ hs->offset[0] = 0;
+ hs->offset[1] = COLLECT_SIZE / 2;
+}
+
+/*
+ * HAVEGE initialization
+ */
+void havege_init( havege_state *hs )
+{
+ memset( hs, 0, sizeof( havege_state ) );
+
+ havege_fill( hs );
+}
+
+/*
+ * HAVEGE rand function
+ */
+int havege_random( void *p_rng, unsigned char *buf, size_t len )
+{
+ int val;
+ size_t use_len;
+ havege_state *hs = (havege_state *) p_rng;
+ unsigned char *p = buf;
+
+ while( len > 0 )
+ {
+ use_len = len;
+ if( use_len > sizeof(int) )
+ use_len = sizeof(int);
+
+ if( hs->offset[1] >= COLLECT_SIZE )
+ havege_fill( hs );
+
+ val = hs->pool[hs->offset[0]++];
+ val ^= hs->pool[hs->offset[1]++];
+
+ memcpy( p, &val, use_len );
+
+ len -= use_len;
+ p += use_len;
+ }
+
+ return( 0 );
+}
+
+#endif
diff --git a/polarssl/src/library/md.c b/polarssl/src/library/md.c
new file mode 100644
index 0000000..96065c9
--- /dev/null
+++ b/polarssl/src/library/md.c
@@ -0,0 +1,297 @@
+/**
+ * \file md.c
+ *
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD_C)
+
+#include "polarssl/md.h"
+#include "polarssl/md_wrap.h"
+
+#include <stdlib.h>
+
+#if defined _MSC_VER && !defined strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+static const int supported_digests[] = {
+
+#if defined(POLARSSL_MD2_C)
+ POLARSSL_MD_MD2,
+#endif
+
+#if defined(POLARSSL_MD4_C)
+ POLARSSL_MD_MD4,
+#endif
+
+#if defined(POLARSSL_MD5_C)
+ POLARSSL_MD_MD5,
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+ POLARSSL_MD_SHA1,
+#endif
+
+#if defined(POLARSSL_SHA2_C)
+ POLARSSL_MD_SHA224,
+ POLARSSL_MD_SHA256,
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+ POLARSSL_MD_SHA384,
+ POLARSSL_MD_SHA512,
+#endif
+
+ 0
+};
+
+const int *md_list( void )
+{
+ return supported_digests;
+}
+
+const md_info_t *md_info_from_string( const char *md_name )
+{
+ if( NULL == md_name )
+ return NULL;
+
+ /* Get the appropriate digest information */
+#if defined(POLARSSL_MD2_C)
+ if( !strcasecmp( "MD2", md_name ) )
+ return md_info_from_type( POLARSSL_MD_MD2 );
+#endif
+#if defined(POLARSSL_MD4_C)
+ if( !strcasecmp( "MD4", md_name ) )
+ return md_info_from_type( POLARSSL_MD_MD4 );
+#endif
+#if defined(POLARSSL_MD5_C)
+ if( !strcasecmp( "MD5", md_name ) )
+ return md_info_from_type( POLARSSL_MD_MD5 );
+#endif
+#if defined(POLARSSL_SHA1_C)
+ if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA1 );
+#endif
+#if defined(POLARSSL_SHA2_C)
+ if( !strcasecmp( "SHA224", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA224 );
+ if( !strcasecmp( "SHA256", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA256 );
+#endif
+#if defined(POLARSSL_SHA4_C)
+ if( !strcasecmp( "SHA384", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA384 );
+ if( !strcasecmp( "SHA512", md_name ) )
+ return md_info_from_type( POLARSSL_MD_SHA512 );
+#endif
+ return NULL;
+}
+
+const md_info_t *md_info_from_type( md_type_t md_type )
+{
+ switch( md_type )
+ {
+#if defined(POLARSSL_MD2_C)
+ case POLARSSL_MD_MD2:
+ return &md2_info;
+#endif
+#if defined(POLARSSL_MD4_C)
+ case POLARSSL_MD_MD4:
+ return &md4_info;
+#endif
+#if defined(POLARSSL_MD5_C)
+ case POLARSSL_MD_MD5:
+ return &md5_info;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ case POLARSSL_MD_SHA1:
+ return &sha1_info;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ case POLARSSL_MD_SHA224:
+ return &sha224_info;
+ case POLARSSL_MD_SHA256:
+ return &sha256_info;
+#endif
+#if defined(POLARSSL_SHA4_C)
+ case POLARSSL_MD_SHA384:
+ return &sha384_info;
+ case POLARSSL_MD_SHA512:
+ return &sha512_info;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+int md_init_ctx( md_context_t *ctx, const md_info_t *md_info )
+{
+ if( md_info == NULL || ctx == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ memset( ctx, 0, sizeof( md_context_t ) );
+
+ if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
+ return POLARSSL_ERR_MD_ALLOC_FAILED;
+
+ ctx->md_info = md_info;
+
+ md_info->starts_func( ctx->md_ctx );
+
+ return 0;
+}
+
+int md_free_ctx( md_context_t *ctx )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->ctx_free_func( ctx->md_ctx );
+ ctx->md_ctx = NULL;
+
+ return 0;
+}
+
+int md_starts( md_context_t *ctx )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->starts_func( ctx->md_ctx );
+
+ return 0;
+}
+
+int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->update_func( ctx->md_ctx, input, ilen );
+
+ return 0;
+}
+
+int md_finish( md_context_t *ctx, unsigned char *output )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->finish_func( ctx->md_ctx, output );
+
+ return 0;
+}
+
+int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ if ( md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ md_info->digest_func( input, ilen, output );
+
+ return 0;
+}
+
+int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ int ret;
+#endif
+
+ if( md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+#if defined(POLARSSL_FS_IO)
+ ret = md_info->file_func( path, output );
+ if( ret != 0 )
+ return( POLARSSL_ERR_MD_FILE_IO_ERROR + ret );
+
+ return( ret );
+#else
+ ((void) path);
+ ((void) output);
+
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen);
+
+ return 0;
+}
+
+int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen );
+
+ return 0;
+}
+
+int md_hmac_finish( md_context_t *ctx, unsigned char *output)
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->hmac_finish_func( ctx->md_ctx, output);
+
+ return 0;
+}
+
+int md_hmac_reset( md_context_t *ctx )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ ctx->md_info->hmac_reset_func( ctx->md_ctx);
+
+ return 0;
+}
+
+int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ if( md_info == NULL )
+ return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+
+ md_info->hmac_func( key, keylen, input, ilen, output );
+
+ return 0;
+}
+
+#endif
diff --git a/polarssl/src/library/md2.c b/polarssl/src/library/md2.c
new file mode 100644
index 0000000..954aa07
--- /dev/null
+++ b/polarssl/src/library/md2.c
@@ -0,0 +1,364 @@
+/*
+ * RFC 1115/1319 compliant MD2 implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The MD2 algorithm was designed by Ron Rivest in 1989.
+ *
+ * http://www.ietf.org/rfc/rfc1115.txt
+ * http://www.ietf.org/rfc/rfc1319.txt
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD2_C)
+
+#include "polarssl/md2.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+static const unsigned char PI_SUBST[256] =
+{
+ 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
+ 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
+ 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
+ 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
+ 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
+ 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
+ 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
+ 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
+ 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
+ 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
+ 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
+ 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
+ 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
+ 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
+ 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
+ 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
+ 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
+ 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
+ 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
+ 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
+ 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
+ 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
+ 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
+ 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
+ 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
+ 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
+};
+
+/*
+ * MD2 context setup
+ */
+void md2_starts( md2_context *ctx )
+{
+ memset( ctx->cksum, 0, 16 );
+ memset( ctx->state, 0, 46 );
+ memset( ctx->buffer, 0, 16 );
+ ctx->left = 0;
+}
+
+static void md2_process( md2_context *ctx )
+{
+ int i, j;
+ unsigned char t = 0;
+
+ for( i = 0; i < 16; i++ )
+ {
+ ctx->state[i + 16] = ctx->buffer[i];
+ ctx->state[i + 32] =
+ (unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
+ }
+
+ for( i = 0; i < 18; i++ )
+ {
+ for( j = 0; j < 48; j++ )
+ {
+ ctx->state[j] = (unsigned char)
+ ( ctx->state[j] ^ PI_SUBST[t] );
+ t = ctx->state[j];
+ }
+
+ t = (unsigned char)( t + i );
+ }
+
+ t = ctx->cksum[15];
+
+ for( i = 0; i < 16; i++ )
+ {
+ ctx->cksum[i] = (unsigned char)
+ ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
+ t = ctx->cksum[i];
+ }
+}
+
+/*
+ * MD2 process buffer
+ */
+void md2_update( md2_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+
+ while( ilen > 0 )
+ {
+ if( ctx->left + ilen > 16 )
+ fill = 16 - ctx->left;
+ else
+ fill = ilen;
+
+ memcpy( ctx->buffer + ctx->left, input, fill );
+
+ ctx->left += fill;
+ input += fill;
+ ilen -= fill;
+
+ if( ctx->left == 16 )
+ {
+ ctx->left = 0;
+ md2_process( ctx );
+ }
+ }
+}
+
+/*
+ * MD2 final digest
+ */
+void md2_finish( md2_context *ctx, unsigned char output[16] )
+{
+ size_t i;
+ unsigned char x;
+
+ x = (unsigned char)( 16 - ctx->left );
+
+ for( i = ctx->left; i < 16; i++ )
+ ctx->buffer[i] = x;
+
+ md2_process( ctx );
+
+ memcpy( ctx->buffer, ctx->cksum, 16 );
+ md2_process( ctx );
+
+ memcpy( output, ctx->state, 16 );
+}
+
+/*
+ * output = MD2( input buffer )
+ */
+void md2( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+ md2_context ctx;
+
+ md2_starts( &ctx );
+ md2_update( &ctx, input, ilen );
+ md2_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md2_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD2( file contents )
+ */
+int md2_file( const char *path, unsigned char output[16] )
+{
+ FILE *f;
+ size_t n;
+ md2_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
+
+ md2_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ md2_update( &ctx, buf, n );
+
+ md2_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md2_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD2 HMAC context setup
+ */
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen )
+{
+ size_t i;
+ unsigned char sum[16];
+
+ if( keylen > 16 )
+ {
+ md2( key, keylen, sum );
+ keylen = 16;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 16 );
+ memset( ctx->opad, 0x5C, 16 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ md2_starts( ctx );
+ md2_update( ctx, ctx->ipad, 16 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD2 HMAC process buffer
+ */
+void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen )
+{
+ md2_update( ctx, input, ilen );
+}
+
+/*
+ * MD2 HMAC final digest
+ */
+void md2_hmac_finish( md2_context *ctx, unsigned char output[16] )
+{
+ unsigned char tmpbuf[16];
+
+ md2_finish( ctx, tmpbuf );
+ md2_starts( ctx );
+ md2_update( ctx, ctx->opad, 16 );
+ md2_update( ctx, tmpbuf, 16 );
+ md2_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD2 HMAC context reset
+ */
+void md2_hmac_reset( md2_context *ctx )
+{
+ md2_starts( ctx );
+ md2_update( ctx, ctx->ipad, 16 );
+}
+
+/*
+ * output = HMAC-MD2( hmac key, input buffer )
+ */
+void md2_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] )
+{
+ md2_context ctx;
+
+ md2_hmac_starts( &ctx, key, keylen );
+ md2_hmac_update( &ctx, input, ilen );
+ md2_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md2_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * RFC 1319 test vectors
+ */
+static const char md2_test_str[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012" \
+ "345678901234567890" }
+};
+
+static const unsigned char md2_test_sum[7][16] =
+{
+ { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
+ 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
+ { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
+ 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
+ { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
+ 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
+ { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
+ 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
+ { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
+ 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
+ { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
+ 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
+ { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
+ 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
+};
+
+/*
+ * Checkup routine
+ */
+int md2_self_test( int verbose )
+{
+ int i;
+ unsigned char md2sum[16];
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " MD2 test #%d: ", i + 1 );
+
+ md2( (unsigned char *) md2_test_str[i],
+ strlen( md2_test_str[i] ), md2sum );
+
+ if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/md4.c b/polarssl/src/library/md4.c
new file mode 100644
index 0000000..ad52e5e
--- /dev/null
+++ b/polarssl/src/library/md4.c
@@ -0,0 +1,460 @@
+/*
+ * RFC 1186/1320 compliant MD4 implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The MD4 algorithm was designed by Ron Rivest in 1990.
+ *
+ * http://www.ietf.org/rfc/rfc1186.txt
+ * http://www.ietf.org/rfc/rfc1320.txt
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD4_C)
+
+#include "polarssl/md4.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_ULONG_LE
+#define GET_ULONG_LE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] ) \
+ | ( (unsigned long) (b)[(i) + 1] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_ULONG_LE
+#define PUT_ULONG_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+}
+#endif
+
+/*
+ * MD4 context setup
+ */
+void md4_starts( md4_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+}
+
+static void md4_process( md4_context *ctx, const unsigned char data[64] )
+{
+ unsigned long X[16], A, B, C, D;
+
+ GET_ULONG_LE( X[ 0], data, 0 );
+ GET_ULONG_LE( X[ 1], data, 4 );
+ GET_ULONG_LE( X[ 2], data, 8 );
+ GET_ULONG_LE( X[ 3], data, 12 );
+ GET_ULONG_LE( X[ 4], data, 16 );
+ GET_ULONG_LE( X[ 5], data, 20 );
+ GET_ULONG_LE( X[ 6], data, 24 );
+ GET_ULONG_LE( X[ 7], data, 28 );
+ GET_ULONG_LE( X[ 8], data, 32 );
+ GET_ULONG_LE( X[ 9], data, 36 );
+ GET_ULONG_LE( X[10], data, 40 );
+ GET_ULONG_LE( X[11], data, 44 );
+ GET_ULONG_LE( X[12], data, 48 );
+ GET_ULONG_LE( X[13], data, 52 );
+ GET_ULONG_LE( X[14], data, 56 );
+ GET_ULONG_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+#define F(x, y, z) ((x & y) | ((~x) & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 1], 7 );
+ P( C, D, A, B, X[ 2], 11 );
+ P( B, C, D, A, X[ 3], 19 );
+ P( A, B, C, D, X[ 4], 3 );
+ P( D, A, B, C, X[ 5], 7 );
+ P( C, D, A, B, X[ 6], 11 );
+ P( B, C, D, A, X[ 7], 19 );
+ P( A, B, C, D, X[ 8], 3 );
+ P( D, A, B, C, X[ 9], 7 );
+ P( C, D, A, B, X[10], 11 );
+ P( B, C, D, A, X[11], 19 );
+ P( A, B, C, D, X[12], 3 );
+ P( D, A, B, C, X[13], 7 );
+ P( C, D, A, B, X[14], 11 );
+ P( B, C, D, A, X[15], 19 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) ((x & y) | (x & z) | (y & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 4], 5 );
+ P( C, D, A, B, X[ 8], 9 );
+ P( B, C, D, A, X[12], 13 );
+ P( A, B, C, D, X[ 1], 3 );
+ P( D, A, B, C, X[ 5], 5 );
+ P( C, D, A, B, X[ 9], 9 );
+ P( B, C, D, A, X[13], 13 );
+ P( A, B, C, D, X[ 2], 3 );
+ P( D, A, B, C, X[ 6], 5 );
+ P( C, D, A, B, X[10], 9 );
+ P( B, C, D, A, X[14], 13 );
+ P( A, B, C, D, X[ 3], 3 );
+ P( D, A, B, C, X[ 7], 5 );
+ P( C, D, A, B, X[11], 9 );
+ P( B, C, D, A, X[15], 13 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 8], 9 );
+ P( C, D, A, B, X[ 4], 11 );
+ P( B, C, D, A, X[12], 15 );
+ P( A, B, C, D, X[ 2], 3 );
+ P( D, A, B, C, X[10], 9 );
+ P( C, D, A, B, X[ 6], 11 );
+ P( B, C, D, A, X[14], 15 );
+ P( A, B, C, D, X[ 1], 3 );
+ P( D, A, B, C, X[ 9], 9 );
+ P( C, D, A, B, X[ 5], 11 );
+ P( B, C, D, A, X[13], 15 );
+ P( A, B, C, D, X[ 3], 3 );
+ P( D, A, B, C, X[11], 9 );
+ P( C, D, A, B, X[ 7], 11 );
+ P( B, C, D, A, X[15], 15 );
+
+#undef F
+#undef P
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+}
+
+/*
+ * MD4 process buffer
+ */
+void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ unsigned long left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (unsigned long) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (unsigned long) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+ md4_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ md4_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, ilen );
+ }
+}
+
+static const unsigned char md4_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD4 final digest
+ */
+void md4_finish( md4_context *ctx, unsigned char output[16] )
+{
+ unsigned long last, padn;
+ unsigned long high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_ULONG_LE( low, msglen, 0 );
+ PUT_ULONG_LE( high, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ md4_update( ctx, (unsigned char *) md4_padding, padn );
+ md4_update( ctx, msglen, 8 );
+
+ PUT_ULONG_LE( ctx->state[0], output, 0 );
+ PUT_ULONG_LE( ctx->state[1], output, 4 );
+ PUT_ULONG_LE( ctx->state[2], output, 8 );
+ PUT_ULONG_LE( ctx->state[3], output, 12 );
+}
+
+/*
+ * output = MD4( input buffer )
+ */
+void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+ md4_context ctx;
+
+ md4_starts( &ctx );
+ md4_update( &ctx, input, ilen );
+ md4_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md4_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD4( file contents )
+ */
+int md4_file( const char *path, unsigned char output[16] )
+{
+ FILE *f;
+ size_t n;
+ md4_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
+
+ md4_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ md4_update( &ctx, buf, n );
+
+ md4_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md4_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD4 HMAC context setup
+ */
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen )
+{
+ size_t i;
+ unsigned char sum[16];
+
+ if( keylen > 64 )
+ {
+ md4( key, keylen, sum );
+ keylen = 16;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ md4_starts( ctx );
+ md4_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD4 HMAC process buffer
+ */
+void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen )
+{
+ md4_update( ctx, input, ilen );
+}
+
+/*
+ * MD4 HMAC final digest
+ */
+void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
+{
+ unsigned char tmpbuf[16];
+
+ md4_finish( ctx, tmpbuf );
+ md4_starts( ctx );
+ md4_update( ctx, ctx->opad, 64 );
+ md4_update( ctx, tmpbuf, 16 );
+ md4_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD4 HMAC context reset
+ */
+void md4_hmac_reset( md4_context *ctx )
+{
+ md4_starts( ctx );
+ md4_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD4( hmac key, input buffer )
+ */
+void md4_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] )
+{
+ md4_context ctx;
+
+ md4_hmac_starts( &ctx, key, keylen );
+ md4_hmac_update( &ctx, input, ilen );
+ md4_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md4_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * RFC 1320 test vectors
+ */
+static const char md4_test_str[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012" \
+ "345678901234567890" }
+};
+
+static const unsigned char md4_test_sum[7][16] =
+{
+ { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
+ 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
+ { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
+ 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
+ { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
+ 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
+ { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
+ 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
+ { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
+ 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
+ { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
+ 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
+ { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
+ 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
+};
+
+/*
+ * Checkup routine
+ */
+int md4_self_test( int verbose )
+{
+ int i;
+ unsigned char md4sum[16];
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " MD4 test #%d: ", i + 1 );
+
+ md4( (unsigned char *) md4_test_str[i],
+ strlen( md4_test_str[i] ), md4sum );
+
+ if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/md5.c b/polarssl/src/library/md5.c
new file mode 100644
index 0000000..7a449b2
--- /dev/null
+++ b/polarssl/src/library/md5.c
@@ -0,0 +1,583 @@
+/*
+ * RFC 1321 compliant MD5 implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The MD5 algorithm was designed by Ron Rivest in 1991.
+ *
+ * http://www.ietf.org/rfc/rfc1321.txt
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD5_C)
+
+#include "polarssl/md5.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_ULONG_LE
+#define GET_ULONG_LE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] ) \
+ | ( (unsigned long) (b)[(i) + 1] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_ULONG_LE
+#define PUT_ULONG_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+}
+#endif
+
+/*
+ * MD5 context setup
+ */
+void md5_starts( md5_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+}
+
+static void md5_process( md5_context *ctx, const unsigned char data[64] )
+{
+ unsigned long X[16], A, B, C, D;
+
+ GET_ULONG_LE( X[ 0], data, 0 );
+ GET_ULONG_LE( X[ 1], data, 4 );
+ GET_ULONG_LE( X[ 2], data, 8 );
+ GET_ULONG_LE( X[ 3], data, 12 );
+ GET_ULONG_LE( X[ 4], data, 16 );
+ GET_ULONG_LE( X[ 5], data, 20 );
+ GET_ULONG_LE( X[ 6], data, 24 );
+ GET_ULONG_LE( X[ 7], data, 28 );
+ GET_ULONG_LE( X[ 8], data, 32 );
+ GET_ULONG_LE( X[ 9], data, 36 );
+ GET_ULONG_LE( X[10], data, 40 );
+ GET_ULONG_LE( X[11], data, 44 );
+ GET_ULONG_LE( X[12], data, 48 );
+ GET_ULONG_LE( X[13], data, 52 );
+ GET_ULONG_LE( X[14], data, 56 );
+ GET_ULONG_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a,b,c,d,k,s,t) \
+{ \
+ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+ P( A, B, C, D, 0, 7, 0xD76AA478 );
+ P( D, A, B, C, 1, 12, 0xE8C7B756 );
+ P( C, D, A, B, 2, 17, 0x242070DB );
+ P( B, C, D, A, 3, 22, 0xC1BDCEEE );
+ P( A, B, C, D, 4, 7, 0xF57C0FAF );
+ P( D, A, B, C, 5, 12, 0x4787C62A );
+ P( C, D, A, B, 6, 17, 0xA8304613 );
+ P( B, C, D, A, 7, 22, 0xFD469501 );
+ P( A, B, C, D, 8, 7, 0x698098D8 );
+ P( D, A, B, C, 9, 12, 0x8B44F7AF );
+ P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
+ P( B, C, D, A, 11, 22, 0x895CD7BE );
+ P( A, B, C, D, 12, 7, 0x6B901122 );
+ P( D, A, B, C, 13, 12, 0xFD987193 );
+ P( C, D, A, B, 14, 17, 0xA679438E );
+ P( B, C, D, A, 15, 22, 0x49B40821 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+ P( A, B, C, D, 1, 5, 0xF61E2562 );
+ P( D, A, B, C, 6, 9, 0xC040B340 );
+ P( C, D, A, B, 11, 14, 0x265E5A51 );
+ P( B, C, D, A, 0, 20, 0xE9B6C7AA );
+ P( A, B, C, D, 5, 5, 0xD62F105D );
+ P( D, A, B, C, 10, 9, 0x02441453 );
+ P( C, D, A, B, 15, 14, 0xD8A1E681 );
+ P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
+ P( A, B, C, D, 9, 5, 0x21E1CDE6 );
+ P( D, A, B, C, 14, 9, 0xC33707D6 );
+ P( C, D, A, B, 3, 14, 0xF4D50D87 );
+ P( B, C, D, A, 8, 20, 0x455A14ED );
+ P( A, B, C, D, 13, 5, 0xA9E3E905 );
+ P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
+ P( C, D, A, B, 7, 14, 0x676F02D9 );
+ P( B, C, D, A, 12, 20, 0x8D2A4C8A );
+
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+
+ P( A, B, C, D, 5, 4, 0xFFFA3942 );
+ P( D, A, B, C, 8, 11, 0x8771F681 );
+ P( C, D, A, B, 11, 16, 0x6D9D6122 );
+ P( B, C, D, A, 14, 23, 0xFDE5380C );
+ P( A, B, C, D, 1, 4, 0xA4BEEA44 );
+ P( D, A, B, C, 4, 11, 0x4BDECFA9 );
+ P( C, D, A, B, 7, 16, 0xF6BB4B60 );
+ P( B, C, D, A, 10, 23, 0xBEBFBC70 );
+ P( A, B, C, D, 13, 4, 0x289B7EC6 );
+ P( D, A, B, C, 0, 11, 0xEAA127FA );
+ P( C, D, A, B, 3, 16, 0xD4EF3085 );
+ P( B, C, D, A, 6, 23, 0x04881D05 );
+ P( A, B, C, D, 9, 4, 0xD9D4D039 );
+ P( D, A, B, C, 12, 11, 0xE6DB99E5 );
+ P( C, D, A, B, 15, 16, 0x1FA27CF8 );
+ P( B, C, D, A, 2, 23, 0xC4AC5665 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+ P( A, B, C, D, 0, 6, 0xF4292244 );
+ P( D, A, B, C, 7, 10, 0x432AFF97 );
+ P( C, D, A, B, 14, 15, 0xAB9423A7 );
+ P( B, C, D, A, 5, 21, 0xFC93A039 );
+ P( A, B, C, D, 12, 6, 0x655B59C3 );
+ P( D, A, B, C, 3, 10, 0x8F0CCC92 );
+ P( C, D, A, B, 10, 15, 0xFFEFF47D );
+ P( B, C, D, A, 1, 21, 0x85845DD1 );
+ P( A, B, C, D, 8, 6, 0x6FA87E4F );
+ P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
+ P( C, D, A, B, 6, 15, 0xA3014314 );
+ P( B, C, D, A, 13, 21, 0x4E0811A1 );
+ P( A, B, C, D, 4, 6, 0xF7537E82 );
+ P( D, A, B, C, 11, 10, 0xBD3AF235 );
+ P( C, D, A, B, 2, 15, 0x2AD7D2BB );
+ P( B, C, D, A, 9, 21, 0xEB86D391 );
+
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+}
+
+/*
+ * MD5 process buffer
+ */
+void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ unsigned long left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (unsigned long) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (unsigned long) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+ md5_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ md5_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, ilen );
+ }
+}
+
+static const unsigned char md5_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD5 final digest
+ */
+void md5_finish( md5_context *ctx, unsigned char output[16] )
+{
+ unsigned long last, padn;
+ unsigned long high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_ULONG_LE( low, msglen, 0 );
+ PUT_ULONG_LE( high, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ md5_update( ctx, (unsigned char *) md5_padding, padn );
+ md5_update( ctx, msglen, 8 );
+
+ PUT_ULONG_LE( ctx->state[0], output, 0 );
+ PUT_ULONG_LE( ctx->state[1], output, 4 );
+ PUT_ULONG_LE( ctx->state[2], output, 8 );
+ PUT_ULONG_LE( ctx->state[3], output, 12 );
+}
+
+/*
+ * output = MD5( input buffer )
+ */
+void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
+{
+ md5_context ctx;
+
+ md5_starts( &ctx );
+ md5_update( &ctx, input, ilen );
+ md5_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md5_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = MD5( file contents )
+ */
+int md5_file( const char *path, unsigned char output[16] )
+{
+ FILE *f;
+ size_t n;
+ md5_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
+
+ md5_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ md5_update( &ctx, buf, n );
+
+ md5_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md5_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * MD5 HMAC context setup
+ */
+void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen )
+{
+ size_t i;
+ unsigned char sum[16];
+
+ if( keylen > 64 )
+ {
+ md5( key, keylen, sum );
+ keylen = 16;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ md5_starts( ctx );
+ md5_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * MD5 HMAC process buffer
+ */
+void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen )
+{
+ md5_update( ctx, input, ilen );
+}
+
+/*
+ * MD5 HMAC final digest
+ */
+void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
+{
+ unsigned char tmpbuf[16];
+
+ md5_finish( ctx, tmpbuf );
+ md5_starts( ctx );
+ md5_update( ctx, ctx->opad, 64 );
+ md5_update( ctx, tmpbuf, 16 );
+ md5_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * MD5 HMAC context reset
+ */
+void md5_hmac_reset( md5_context *ctx )
+{
+ md5_starts( ctx );
+ md5_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-MD5( hmac key, input buffer )
+ */
+void md5_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[16] )
+{
+ md5_context ctx;
+
+ md5_hmac_starts( &ctx, key, keylen );
+ md5_hmac_update( &ctx, input, ilen );
+ md5_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( md5_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * RFC 1321 test vectors
+ */
+static unsigned char md5_test_buf[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012" \
+ "345678901234567890" }
+};
+
+static const int md5_test_buflen[7] =
+{
+ 0, 1, 3, 14, 26, 62, 80
+};
+
+static const unsigned char md5_test_sum[7][16] =
+{
+ { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
+ 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
+ { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
+ 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
+ { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
+ 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
+ { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
+ 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
+ { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
+ 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
+ { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
+ 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
+ { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
+ 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char md5_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 80 times */
+ { "" }
+};
+
+static const int md5_hmac_test_keylen[7] =
+{
+ 16, 4, 16, 25, 16, 80, 80
+};
+
+static unsigned char md5_hmac_test_buf[7][74] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "Test Using Larger Than Block-Size Key and Larger"
+ " Than One Block-Size Data" }
+};
+
+static const int md5_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char md5_hmac_test_sum[7][16] =
+{
+ { 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
+ 0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
+ { 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
+ 0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
+ { 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
+ 0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
+ { 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
+ 0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
+ { 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
+ 0xF9, 0xBA, 0xB9, 0x95 },
+ { 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
+ 0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
+ { 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
+ 0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
+};
+
+/*
+ * Checkup routine
+ */
+int md5_self_test( int verbose )
+{
+ int i, buflen;
+ unsigned char buf[1024];
+ unsigned char md5sum[16];
+ md5_context ctx;
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " MD5 test #%d: ", i + 1 );
+
+ md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
+
+ if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " HMAC-MD5 test #%d: ", i + 1 );
+
+ if( i == 5 || i == 6 )
+ {
+ memset( buf, '\xAA', buflen = 80 );
+ md5_hmac_starts( &ctx, buf, buflen );
+ }
+ else
+ md5_hmac_starts( &ctx, md5_hmac_test_key[i],
+ md5_hmac_test_keylen[i] );
+
+ md5_hmac_update( &ctx, md5_hmac_test_buf[i],
+ md5_hmac_test_buflen[i] );
+
+ md5_hmac_finish( &ctx, md5sum );
+
+ buflen = ( i == 4 ) ? 12 : 16;
+
+ if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/md_wrap.c b/polarssl/src/library/md_wrap.c
new file mode 100644
index 0000000..f276db5
--- /dev/null
+++ b/polarssl/src/library/md_wrap.c
@@ -0,0 +1,733 @@
+/**
+ * \file md_wrap.c
+
+ * \brief Generic message digest wrapper for PolarSSL
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_MD_C)
+
+#include "polarssl/md_wrap.h"
+
+#if defined(POLARSSL_MD2_C)
+#include "polarssl/md2.h"
+#endif
+
+#if defined(POLARSSL_MD4_C)
+#include "polarssl/md4.h"
+#endif
+
+#if defined(POLARSSL_MD5_C)
+#include "polarssl/md5.h"
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+#include "polarssl/sha1.h"
+#endif
+
+#if defined(POLARSSL_SHA2_C)
+#include "polarssl/sha2.h"
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+#include "polarssl/sha4.h"
+#endif
+
+#include <stdlib.h>
+
+#if defined(POLARSSL_MD2_C)
+
+static void md2_starts_wrap( void *ctx )
+{
+ md2_starts( (md2_context *) ctx );
+}
+
+static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md2_update( (md2_context *) ctx, input, ilen );
+}
+
+static void md2_finish_wrap( void *ctx, unsigned char *output )
+{
+ md2_finish( (md2_context *) ctx, output );
+}
+
+int md2_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return md2_file( path, output );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ md2_hmac_starts( (md2_context *) ctx, key, keylen );
+}
+
+static void md2_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md2_hmac_update( (md2_context *) ctx, input, ilen );
+}
+
+static void md2_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ md2_hmac_finish( (md2_context *) ctx, output );
+}
+
+static void md2_hmac_reset_wrap( void *ctx )
+{
+ md2_hmac_reset( (md2_context *) ctx );
+}
+
+static void * md2_ctx_alloc( void )
+{
+ return malloc( sizeof( md2_context ) );
+}
+
+static void md2_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t md2_info = {
+ POLARSSL_MD_MD2,
+ "MD2",
+ 16,
+ md2_starts_wrap,
+ md2_update_wrap,
+ md2_finish_wrap,
+ md2,
+ md2_file_wrap,
+ md2_hmac_starts_wrap,
+ md2_hmac_update_wrap,
+ md2_hmac_finish_wrap,
+ md2_hmac_reset_wrap,
+ md2_hmac,
+ md2_ctx_alloc,
+ md2_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_MD4_C)
+
+void md4_starts_wrap( void *ctx )
+{
+ md4_starts( (md4_context *) ctx );
+}
+
+void md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md4_update( (md4_context *) ctx, input, ilen );
+}
+
+void md4_finish_wrap( void *ctx, unsigned char *output )
+{
+ md4_finish( (md4_context *) ctx, output );
+}
+
+int md4_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return md4_file( path, output );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void md4_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ md4_hmac_starts( (md4_context *) ctx, key, keylen );
+}
+
+void md4_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md4_hmac_update( (md4_context *) ctx, input, ilen );
+}
+
+void md4_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ md4_hmac_finish( (md4_context *) ctx, output );
+}
+
+void md4_hmac_reset_wrap( void *ctx )
+{
+ md4_hmac_reset( (md4_context *) ctx );
+}
+
+void *md4_ctx_alloc( void )
+{
+ return malloc( sizeof( md4_context ) );
+}
+
+void md4_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t md4_info = {
+ POLARSSL_MD_MD4,
+ "MD4",
+ 16,
+ md4_starts_wrap,
+ md4_update_wrap,
+ md4_finish_wrap,
+ md4,
+ md4_file_wrap,
+ md4_hmac_starts_wrap,
+ md4_hmac_update_wrap,
+ md4_hmac_finish_wrap,
+ md4_hmac_reset_wrap,
+ md4_hmac,
+ md4_ctx_alloc,
+ md4_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_MD5_C)
+
+static void md5_starts_wrap( void *ctx )
+{
+ md5_starts( (md5_context *) ctx );
+}
+
+static void md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md5_update( (md5_context *) ctx, input, ilen );
+}
+
+static void md5_finish_wrap( void *ctx, unsigned char *output )
+{
+ md5_finish( (md5_context *) ctx, output );
+}
+
+int md5_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return md5_file( path, output );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ md5_hmac_starts( (md5_context *) ctx, key, keylen );
+}
+
+static void md5_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ md5_hmac_update( (md5_context *) ctx, input, ilen );
+}
+
+static void md5_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ md5_hmac_finish( (md5_context *) ctx, output );
+}
+
+static void md5_hmac_reset_wrap( void *ctx )
+{
+ md5_hmac_reset( (md5_context *) ctx );
+}
+
+static void * md5_ctx_alloc( void )
+{
+ return malloc( sizeof( md5_context ) );
+}
+
+static void md5_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t md5_info = {
+ POLARSSL_MD_MD5,
+ "MD5",
+ 16,
+ md5_starts_wrap,
+ md5_update_wrap,
+ md5_finish_wrap,
+ md5,
+ md5_file_wrap,
+ md5_hmac_starts_wrap,
+ md5_hmac_update_wrap,
+ md5_hmac_finish_wrap,
+ md5_hmac_reset_wrap,
+ md5_hmac,
+ md5_ctx_alloc,
+ md5_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_SHA1_C)
+
+void sha1_starts_wrap( void *ctx )
+{
+ sha1_starts( (sha1_context *) ctx );
+}
+
+void sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha1_update( (sha1_context *) ctx, input, ilen );
+}
+
+void sha1_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha1_finish( (sha1_context *) ctx, output );
+}
+
+int sha1_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha1_file( path, output );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha1_hmac_starts( (sha1_context *) ctx, key, keylen );
+}
+
+void sha1_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha1_hmac_update( (sha1_context *) ctx, input, ilen );
+}
+
+void sha1_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha1_hmac_finish( (sha1_context *) ctx, output );
+}
+
+void sha1_hmac_reset_wrap( void *ctx )
+{
+ sha1_hmac_reset( (sha1_context *) ctx );
+}
+
+void * sha1_ctx_alloc( void )
+{
+ return malloc( sizeof( sha1_context ) );
+}
+
+void sha1_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha1_info = {
+ POLARSSL_MD_SHA1,
+ "SHA1",
+ 20,
+ sha1_starts_wrap,
+ sha1_update_wrap,
+ sha1_finish_wrap,
+ sha1,
+ sha1_file_wrap,
+ sha1_hmac_starts_wrap,
+ sha1_hmac_update_wrap,
+ sha1_hmac_finish_wrap,
+ sha1_hmac_reset_wrap,
+ sha1_hmac,
+ sha1_ctx_alloc,
+ sha1_ctx_free,
+};
+
+#endif
+
+/*
+ * Wrappers for generic message digests
+ */
+#if defined(POLARSSL_SHA2_C)
+
+void sha224_starts_wrap( void *ctx )
+{
+ sha2_starts( (sha2_context *) ctx, 1 );
+}
+
+void sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha224_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha2_finish( (sha2_context *) ctx, output );
+}
+
+void sha224_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha2( input, ilen, output, 1 );
+}
+
+int sha224_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha2_file( path, output, 1 );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 1 );
+}
+
+void sha224_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_hmac_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha224_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha2_hmac_finish( (sha2_context *) ctx, output );
+}
+
+void sha224_hmac_reset_wrap( void *ctx )
+{
+ sha2_hmac_reset( (sha2_context *) ctx );
+}
+
+void sha224_hmac_wrap( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha2_hmac( key, keylen, input, ilen, output, 1 );
+}
+
+void * sha224_ctx_alloc( void )
+{
+ return malloc( sizeof( sha2_context ) );
+}
+
+void sha224_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha224_info = {
+ POLARSSL_MD_SHA224,
+ "SHA224",
+ 28,
+ sha224_starts_wrap,
+ sha224_update_wrap,
+ sha224_finish_wrap,
+ sha224_wrap,
+ sha224_file_wrap,
+ sha224_hmac_starts_wrap,
+ sha224_hmac_update_wrap,
+ sha224_hmac_finish_wrap,
+ sha224_hmac_reset_wrap,
+ sha224_hmac_wrap,
+ sha224_ctx_alloc,
+ sha224_ctx_free,
+};
+
+void sha256_starts_wrap( void *ctx )
+{
+ sha2_starts( (sha2_context *) ctx, 0 );
+}
+
+void sha256_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha256_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha2_finish( (sha2_context *) ctx, output );
+}
+
+void sha256_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha2( input, ilen, output, 0 );
+}
+
+int sha256_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha2_file( path, output, 0 );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha2_hmac_starts( (sha2_context *) ctx, key, keylen, 0 );
+}
+
+void sha256_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_hmac_update( (sha2_context *) ctx, input, ilen );
+}
+
+void sha256_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha2_hmac_finish( (sha2_context *) ctx, output );
+}
+
+void sha256_hmac_reset_wrap( void *ctx )
+{
+ sha2_hmac_reset( (sha2_context *) ctx );
+}
+
+void sha256_hmac_wrap( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha2_hmac( key, keylen, input, ilen, output, 0 );
+}
+
+void * sha256_ctx_alloc( void )
+{
+ return malloc( sizeof( sha2_context ) );
+}
+
+void sha256_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha256_info = {
+ POLARSSL_MD_SHA256,
+ "SHA256",
+ 32,
+ sha256_starts_wrap,
+ sha256_update_wrap,
+ sha256_finish_wrap,
+ sha256_wrap,
+ sha256_file_wrap,
+ sha256_hmac_starts_wrap,
+ sha256_hmac_update_wrap,
+ sha256_hmac_finish_wrap,
+ sha256_hmac_reset_wrap,
+ sha256_hmac_wrap,
+ sha256_ctx_alloc,
+ sha256_ctx_free,
+};
+
+#endif
+
+#if defined(POLARSSL_SHA4_C)
+
+void sha384_starts_wrap( void *ctx )
+{
+ sha4_starts( (sha4_context *) ctx, 1 );
+}
+
+void sha384_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha4_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha384_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha4_finish( (sha4_context *) ctx, output );
+}
+
+void sha384_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha4( input, ilen, output, 1 );
+}
+
+int sha384_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha4_file( path, output, 1 );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 1 );
+}
+
+void sha384_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha4_hmac_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha384_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha4_hmac_finish( (sha4_context *) ctx, output );
+}
+
+void sha384_hmac_reset_wrap( void *ctx )
+{
+ sha4_hmac_reset( (sha4_context *) ctx );
+}
+
+void sha384_hmac_wrap( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha4_hmac( key, keylen, input, ilen, output, 1 );
+}
+
+void * sha384_ctx_alloc( void )
+{
+ return malloc( sizeof( sha4_context ) );
+}
+
+void sha384_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha384_info = {
+ POLARSSL_MD_SHA384,
+ "SHA384",
+ 48,
+ sha384_starts_wrap,
+ sha384_update_wrap,
+ sha384_finish_wrap,
+ sha384_wrap,
+ sha384_file_wrap,
+ sha384_hmac_starts_wrap,
+ sha384_hmac_update_wrap,
+ sha384_hmac_finish_wrap,
+ sha384_hmac_reset_wrap,
+ sha384_hmac_wrap,
+ sha384_ctx_alloc,
+ sha384_ctx_free,
+};
+
+void sha512_starts_wrap( void *ctx )
+{
+ sha4_starts( (sha4_context *) ctx, 0 );
+}
+
+void sha512_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha4_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha512_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha4_finish( (sha4_context *) ctx, output );
+}
+
+void sha512_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha4( input, ilen, output, 0 );
+}
+
+int sha512_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+ return sha4_file( path, output, 0 );
+#else
+ ((void) path);
+ ((void) output);
+ return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+#endif
+}
+
+void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+{
+ sha4_hmac_starts( (sha4_context *) ctx, key, keylen, 0 );
+}
+
+void sha512_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+{
+ sha4_hmac_update( (sha4_context *) ctx, input, ilen );
+}
+
+void sha512_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+ sha4_hmac_finish( (sha4_context *) ctx, output );
+}
+
+void sha512_hmac_reset_wrap( void *ctx )
+{
+ sha4_hmac_reset( (sha4_context *) ctx );
+}
+
+void sha512_hmac_wrap( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ sha4_hmac( key, keylen, input, ilen, output, 0 );
+}
+
+void * sha512_ctx_alloc( void )
+{
+ return malloc( sizeof( sha4_context ) );
+}
+
+void sha512_ctx_free( void *ctx )
+{
+ free( ctx );
+}
+
+const md_info_t sha512_info = {
+ POLARSSL_MD_SHA512,
+ "SHA512",
+ 64,
+ sha512_starts_wrap,
+ sha512_update_wrap,
+ sha512_finish_wrap,
+ sha512_wrap,
+ sha512_file_wrap,
+ sha512_hmac_starts_wrap,
+ sha512_hmac_update_wrap,
+ sha512_hmac_finish_wrap,
+ sha512_hmac_reset_wrap,
+ sha512_hmac_wrap,
+ sha512_ctx_alloc,
+ sha512_ctx_free,
+};
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/net.c b/polarssl/src/library/net.c
new file mode 100644
index 0000000..e30aebb
--- /dev/null
+++ b/polarssl/src/library/net.c
@@ -0,0 +1,358 @@
+/*
+ * TCP networking functions
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_NET_C)
+
+#include "polarssl/net.h"
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+
+#include <winsock2.h>
+#include <windows.h>
+
+#if defined(_WIN32_WCE)
+#pragma comment( lib, "ws2.lib" )
+#else
+#pragma comment( lib, "ws2_32.lib" )
+#endif
+
+#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
+#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
+#define close(fd) closesocket(fd)
+
+static int wsa_init_done = 0;
+
+#else
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <errno.h>
+
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+#include <sys/endian.h>
+#elif defined(__APPLE__)
+#include <machine/endian.h>
+#elif defined(sun)
+#include <sys/isa_defs.h>
+#else
+#include <endian.h>
+#endif
+
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+/*
+ * htons() is not always available.
+ * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and __BIG_ENDIAN
+ * to help determine endianess.
+ */
+#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN
+#define POLARSSL_HTONS(n) (n)
+#else
+#define POLARSSL_HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
+#endif
+
+unsigned short net_htons(unsigned short n);
+#define net_htons(n) POLARSSL_HTONS(n)
+
+/*
+ * Initiate a TCP connection with host:port
+ */
+int net_connect( int *fd, const char *host, int port )
+{
+ struct sockaddr_in server_addr;
+ struct hostent *server_host;
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ WSADATA wsaData;
+
+ if( wsa_init_done == 0 )
+ {
+ if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
+ return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+ wsa_init_done = 1;
+ }
+#else
+ signal( SIGPIPE, SIG_IGN );
+#endif
+
+ if( ( server_host = gethostbyname( host ) ) == NULL )
+ return( POLARSSL_ERR_NET_UNKNOWN_HOST );
+
+ if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
+ return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+ memcpy( (void *) &server_addr.sin_addr,
+ (void *) server_host->h_addr,
+ server_host->h_length );
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = net_htons( port );
+
+ if( connect( *fd, (struct sockaddr *) &server_addr,
+ sizeof( server_addr ) ) < 0 )
+ {
+ close( *fd );
+ return( POLARSSL_ERR_NET_CONNECT_FAILED );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Create a listening socket on bind_ip:port
+ */
+int net_bind( int *fd, const char *bind_ip, int port )
+{
+ int n, c[4];
+ struct sockaddr_in server_addr;
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ WSADATA wsaData;
+
+ if( wsa_init_done == 0 )
+ {
+ if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
+ return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+ wsa_init_done = 1;
+ }
+#else
+ signal( SIGPIPE, SIG_IGN );
+#endif
+
+ if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
+ return( POLARSSL_ERR_NET_SOCKET_FAILED );
+
+ n = 1;
+ setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &n, sizeof( n ) );
+
+ server_addr.sin_addr.s_addr = INADDR_ANY;
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = net_htons( port );
+
+ if( bind_ip != NULL )
+ {
+ memset( c, 0, sizeof( c ) );
+ sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1], &c[2], &c[3] );
+
+ for( n = 0; n < 4; n++ )
+ if( c[n] < 0 || c[n] > 255 )
+ break;
+
+ if( n == 4 )
+ server_addr.sin_addr.s_addr =
+ ( (unsigned long) c[0] << 24 ) |
+ ( (unsigned long) c[1] << 16 ) |
+ ( (unsigned long) c[2] << 8 ) |
+ ( (unsigned long) c[3] );
+ }
+
+ if( bind( *fd, (struct sockaddr *) &server_addr,
+ sizeof( server_addr ) ) < 0 )
+ {
+ close( *fd );
+ return( POLARSSL_ERR_NET_BIND_FAILED );
+ }
+
+ if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
+ {
+ close( *fd );
+ return( POLARSSL_ERR_NET_LISTEN_FAILED );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Check if the current operation is blocking
+ */
+static int net_is_blocking( void )
+{
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ return( WSAGetLastError() == WSAEWOULDBLOCK );
+#else
+ switch( errno )
+ {
+#if defined EAGAIN
+ case EAGAIN:
+#endif
+#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ return( 1 );
+ }
+ return( 0 );
+#endif
+}
+
+/*
+ * Accept a connection from a remote client
+ */
+int net_accept( int bind_fd, int *client_fd, void *client_ip )
+{
+ struct sockaddr_in client_addr;
+
+#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
+ defined(_SOCKLEN_T_DECLARED)
+ socklen_t n = (socklen_t) sizeof( client_addr );
+#else
+ int n = (int) sizeof( client_addr );
+#endif
+
+ *client_fd = accept( bind_fd, (struct sockaddr *)
+ &client_addr, &n );
+
+ if( *client_fd < 0 )
+ {
+ if( net_is_blocking() != 0 )
+ return( POLARSSL_ERR_NET_WANT_READ );
+
+ return( POLARSSL_ERR_NET_ACCEPT_FAILED );
+ }
+
+ if( client_ip != NULL )
+ memcpy( client_ip, &client_addr.sin_addr.s_addr,
+ sizeof( client_addr.sin_addr.s_addr ) );
+
+ return( 0 );
+}
+
+/*
+ * Set the socket blocking or non-blocking
+ */
+int net_set_block( int fd )
+{
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ u_long n = 0;
+ return( ioctlsocket( fd, FIONBIO, &n ) );
+#else
+ return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
+#endif
+}
+
+int net_set_nonblock( int fd )
+{
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ u_long n = 1;
+ return( ioctlsocket( fd, FIONBIO, &n ) );
+#else
+ return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
+#endif
+}
+
+/*
+ * Portable usleep helper
+ */
+void net_usleep( unsigned long usec )
+{
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = usec;
+ select( 0, NULL, NULL, NULL, &tv );
+}
+
+/*
+ * Read at most 'len' characters
+ */
+int net_recv( void *ctx, unsigned char *buf, size_t len )
+{
+ int ret = read( *((int *) ctx), buf, len );
+
+ if( ret < 0 )
+ {
+ if( net_is_blocking() != 0 )
+ return( POLARSSL_ERR_NET_WANT_READ );
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ if( WSAGetLastError() == WSAECONNRESET )
+ return( POLARSSL_ERR_NET_CONN_RESET );
+#else
+ if( errno == EPIPE || errno == ECONNRESET )
+ return( POLARSSL_ERR_NET_CONN_RESET );
+
+ if( errno == EINTR )
+ return( POLARSSL_ERR_NET_WANT_READ );
+#endif
+
+ return( POLARSSL_ERR_NET_RECV_FAILED );
+ }
+
+ return( ret );
+}
+
+/*
+ * Write at most 'len' characters
+ */
+int net_send( void *ctx, const unsigned char *buf, size_t len )
+{
+ int ret = write( *((int *) ctx), buf, len );
+
+ if( ret < 0 )
+ {
+ if( net_is_blocking() != 0 )
+ return( POLARSSL_ERR_NET_WANT_WRITE );
+
+#if defined(_WIN32) || defined(_WIN32_WCE)
+ if( WSAGetLastError() == WSAECONNRESET )
+ return( POLARSSL_ERR_NET_CONN_RESET );
+#else
+ if( errno == EPIPE || errno == ECONNRESET )
+ return( POLARSSL_ERR_NET_CONN_RESET );
+
+ if( errno == EINTR )
+ return( POLARSSL_ERR_NET_WANT_WRITE );
+#endif
+
+ return( POLARSSL_ERR_NET_SEND_FAILED );
+ }
+
+ return( ret );
+}
+
+/*
+ * Gracefully close the connection
+ */
+void net_close( int fd )
+{
+ shutdown( fd, 2 );
+ close( fd );
+}
+
+#endif
diff --git a/polarssl/src/library/padlock.c b/polarssl/src/library/padlock.c
new file mode 100644
index 0000000..2e2e477
--- /dev/null
+++ b/polarssl/src/library/padlock.c
@@ -0,0 +1,162 @@
+/*
+ * VIA PadLock support functions
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * This implementation is based on the VIA PadLock Programming Guide:
+ *
+ * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
+ * programming_guide.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PADLOCK_C)
+
+#include "polarssl/padlock.h"
+
+#if defined(POLARSSL_HAVE_X86)
+
+/*
+ * PadLock detection routine
+ */
+int padlock_supports( int feature )
+{
+ static int flags = -1;
+ int ebx, edx;
+
+ if( flags == -1 )
+ {
+ asm( "movl %%ebx, %0 \n" \
+ "movl $0xC0000000, %%eax \n" \
+ "cpuid \n" \
+ "cmpl $0xC0000001, %%eax \n" \
+ "movl $0, %%edx \n" \
+ "jb unsupported \n" \
+ "movl $0xC0000001, %%eax \n" \
+ "cpuid \n" \
+ "unsupported: \n" \
+ "movl %%edx, %1 \n" \
+ "movl %2, %%ebx \n"
+ : "=m" (ebx), "=m" (edx)
+ : "m" (ebx)
+ : "eax", "ecx", "edx" );
+
+ flags = edx;
+ }
+
+ return( flags & feature );
+}
+
+/*
+ * PadLock AES-ECB block en(de)cryption
+ */
+int padlock_xcryptecb( aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int ebx;
+ unsigned long *rk;
+ unsigned long *blk;
+ unsigned long *ctrl;
+ unsigned char buf[256];
+
+ rk = ctx->rk;
+ blk = PADLOCK_ALIGN16( buf );
+ memcpy( blk, input, 16 );
+
+ ctrl = blk + 4;
+ *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
+
+ asm( "pushfl; popfl \n" \
+ "movl %%ebx, %0 \n" \
+ "movl $1, %%ecx \n" \
+ "movl %2, %%edx \n" \
+ "movl %3, %%ebx \n" \
+ "movl %4, %%esi \n" \
+ "movl %4, %%edi \n" \
+ ".byte 0xf3,0x0f,0xa7,0xc8\n" \
+ "movl %1, %%ebx \n"
+ : "=m" (ebx)
+ : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
+ : "ecx", "edx", "esi", "edi" );
+
+ memcpy( output, blk, 16 );
+
+ return( 0 );
+}
+
+/*
+ * PadLock AES-CBC buffer en(de)cryption
+ */
+int padlock_xcryptcbc( aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ebx;
+ size_t count;
+ unsigned long *rk;
+ unsigned long *iw;
+ unsigned long *ctrl;
+ unsigned char buf[256];
+
+ if( ( (long) input & 15 ) != 0 ||
+ ( (long) output & 15 ) != 0 )
+ return( POLARSSL_ERR_PADLOCK_DATA_MISALIGNED );
+
+ rk = ctx->rk;
+ iw = PADLOCK_ALIGN16( buf );
+ memcpy( iw, iv, 16 );
+
+ ctrl = iw + 4;
+ *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 );
+
+ count = (length + 15) >> 4;
+
+ asm( "pushfl; popfl \n" \
+ "movl %%ebx, %0 \n" \
+ "movl %2, %%ecx \n" \
+ "movl %3, %%edx \n" \
+ "movl %4, %%ebx \n" \
+ "movl %5, %%esi \n" \
+ "movl %6, %%edi \n" \
+ "movl %7, %%eax \n" \
+ ".byte 0xf3,0x0f,0xa7,0xd0\n" \
+ "movl %1, %%ebx \n"
+ : "=m" (ebx)
+ : "m" (ebx), "m" (count), "m" (ctrl),
+ "m" (rk), "m" (input), "m" (output), "m" (iw)
+ : "eax", "ecx", "edx", "esi", "edi" );
+
+ memcpy( iv, iw, 16 );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/pem.c b/polarssl/src/library/pem.c
new file mode 100644
index 0000000..33e74ab
--- /dev/null
+++ b/polarssl/src/library/pem.c
@@ -0,0 +1,352 @@
+/*
+ * Privacy Enhanced Mail (PEM) decoding
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_PEM_C)
+
+#include "polarssl/pem.h"
+#include "polarssl/base64.h"
+#include "polarssl/des.h"
+#include "polarssl/aes.h"
+#include "polarssl/md5.h"
+#include "polarssl/cipher.h"
+
+#include <stdlib.h>
+
+void pem_init( pem_context *ctx )
+{
+ memset( ctx, 0, sizeof( pem_context ) );
+}
+
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+/*
+ * Read a 16-byte hex string and convert it to binary
+ */
+static int pem_get_iv( const unsigned char *s, unsigned char *iv, size_t iv_len )
+{
+ size_t i, j, k;
+
+ memset( iv, 0, iv_len );
+
+ for( i = 0; i < iv_len * 2; i++, s++ )
+ {
+ if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
+ if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
+ if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
+ return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+ k = ( ( i & 1 ) != 0 ) ? j : j << 4;
+
+ iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
+ }
+
+ return( 0 );
+}
+
+static void pem_pbkdf1( unsigned char *key, size_t keylen,
+ unsigned char *iv,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ md5_context md5_ctx;
+ unsigned char md5sum[16];
+ size_t use_len;
+
+ /*
+ * key[ 0..15] = MD5(pwd || IV)
+ */
+ md5_starts( &md5_ctx );
+ md5_update( &md5_ctx, pwd, pwdlen );
+ md5_update( &md5_ctx, iv, 8 );
+ md5_finish( &md5_ctx, md5sum );
+
+ if( keylen <= 16 )
+ {
+ memcpy( key, md5sum, keylen );
+
+ memset( &md5_ctx, 0, sizeof( md5_ctx ) );
+ memset( md5sum, 0, 16 );
+ return;
+ }
+
+ memcpy( key, md5sum, 16 );
+
+ /*
+ * key[16..23] = MD5(key[ 0..15] || pwd || IV])
+ */
+ md5_starts( &md5_ctx );
+ md5_update( &md5_ctx, md5sum, 16 );
+ md5_update( &md5_ctx, pwd, pwdlen );
+ md5_update( &md5_ctx, iv, 8 );
+ md5_finish( &md5_ctx, md5sum );
+
+ use_len = 16;
+ if( keylen < 32 )
+ use_len = keylen - 16;
+
+ memcpy( key + 16, md5sum, use_len );
+
+ memset( &md5_ctx, 0, sizeof( md5_ctx ) );
+ memset( md5sum, 0, 16 );
+}
+
+#if defined(POLARSSL_DES_C)
+/*
+ * Decrypt with DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des_decrypt( unsigned char des_iv[8],
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ des_context des_ctx;
+ unsigned char des_key[8];
+
+ pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
+
+ des_setkey_dec( &des_ctx, des_key );
+ des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen,
+ des_iv, buf, buf );
+
+ memset( &des_ctx, 0, sizeof( des_ctx ) );
+ memset( des_key, 0, 8 );
+}
+
+/*
+ * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des3_decrypt( unsigned char des3_iv[8],
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ des3_context des3_ctx;
+ unsigned char des3_key[24];
+
+ pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
+
+ des3_set3key_dec( &des3_ctx, des3_key );
+ des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
+ des3_iv, buf, buf );
+
+ memset( &des3_ctx, 0, sizeof( des3_ctx ) );
+ memset( des3_key, 0, 24 );
+}
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+/*
+ * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
+ */
+static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ aes_context aes_ctx;
+ unsigned char aes_key[32];
+
+ pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
+
+ aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
+ aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen,
+ aes_iv, buf, buf );
+
+ memset( &aes_ctx, 0, sizeof( aes_ctx ) );
+ memset( aes_key, 0, keylen );
+}
+#endif /* POLARSSL_AES_C */
+
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+
+int pem_read_buffer( pem_context *ctx, char *header, char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len )
+{
+ int ret, enc;
+ size_t len;
+ unsigned char *buf;
+ unsigned char *s1, *s2;
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+ unsigned char pem_iv[16];
+ cipher_type_t enc_alg = POLARSSL_CIPHER_NONE;
+#else
+ ((void) pwd);
+ ((void) pwdlen);
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+
+ if( ctx == NULL )
+ return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+ s1 = (unsigned char *) strstr( (char *) data, header );
+
+ if( s1 == NULL )
+ return( POLARSSL_ERR_PEM_NO_HEADER_PRESENT );
+
+ s2 = (unsigned char *) strstr( (char *) data, footer );
+
+ if( s2 == NULL || s2 <= s1 )
+ return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+ s1 += strlen( header );
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+ enc = 0;
+
+ if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
+ {
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+ enc++;
+
+ s1 += 22;
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( POLARSSL_ERR_PEM_INVALID_DATA );
+
+
+#if defined(POLARSSL_DES_C)
+ if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
+ {
+ enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC;
+
+ s1 += 23;
+ if( pem_get_iv( s1, pem_iv, 8 ) != 0 )
+ return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 16;
+ }
+ else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
+ {
+ enc_alg = POLARSSL_CIPHER_DES_CBC;
+
+ s1 += 18;
+ if( pem_get_iv( s1, pem_iv, 8) != 0 )
+ return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 16;
+ }
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+ if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
+ {
+ if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
+ enc_alg = POLARSSL_CIPHER_AES_128_CBC;
+ else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
+ enc_alg = POLARSSL_CIPHER_AES_192_CBC;
+ else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
+ enc_alg = POLARSSL_CIPHER_AES_256_CBC;
+ else
+ return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
+
+ s1 += 22;
+ if( pem_get_iv( s1, pem_iv, 16 ) != 0 )
+ return( POLARSSL_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 32;
+ }
+#endif /* POLARSSL_AES_C */
+
+ if( enc_alg == POLARSSL_CIPHER_NONE )
+ return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG );
+
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( POLARSSL_ERR_PEM_INVALID_DATA );
+#else
+ return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */
+ }
+
+ len = 0;
+ ret = base64_decode( NULL, &len, s1, s2 - s1 );
+
+ if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
+ return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
+
+ if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
+ return( POLARSSL_ERR_PEM_MALLOC_FAILED );
+
+ if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
+ {
+ free( buf );
+ return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
+ }
+
+ if( enc != 0 )
+ {
+#if defined(POLARSSL_MD5_C) && (defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C))
+ if( pwd == NULL )
+ {
+ free( buf );
+ return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED );
+ }
+
+#if defined(POLARSSL_DES_C)
+ if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC )
+ pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
+ else if( enc_alg == POLARSSL_CIPHER_DES_CBC )
+ pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_AES_C)
+ if( enc_alg == POLARSSL_CIPHER_AES_128_CBC )
+ pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
+ else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC )
+ pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
+ else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC )
+ pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
+#endif /* POLARSSL_AES_C */
+
+ if( buf[0] != 0x30 || buf[1] != 0x82 ||
+ buf[4] != 0x02 || buf[5] != 0x01 )
+ {
+ free( buf );
+ return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH );
+ }
+#else
+ return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif
+ }
+
+ ctx->buf = buf;
+ ctx->buflen = len;
+ s2 += strlen( footer );
+ if( *s2 == '\r' ) s2++;
+ if( *s2 == '\n' ) s2++;
+ *use_len = s2 - data;
+
+ return( 0 );
+}
+
+void pem_free( pem_context *ctx )
+{
+ if( ctx->buf )
+ free( ctx->buf );
+
+ if( ctx->info )
+ free( ctx->info );
+
+ memset( ctx, 0, sizeof( pem_context ) );
+}
+
+#endif
diff --git a/polarssl/src/library/pkcs11.c b/polarssl/src/library/pkcs11.c
new file mode 100644
index 0000000..b71415a
--- /dev/null
+++ b/polarssl/src/library/pkcs11.c
@@ -0,0 +1,238 @@
+/**
+ * \file pkcs11.c
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/pkcs11.h"
+
+#if defined(POLARSSL_PKCS11_C)
+
+#include <stdlib.h>
+
+int pkcs11_x509_cert_init( x509_cert *cert, pkcs11h_certificate_t pkcs11_cert )
+{
+ int ret = 1;
+ unsigned char *cert_blob = NULL;
+ size_t cert_blob_size = 0;
+
+ if( cert == NULL )
+ {
+ ret = 2;
+ goto cleanup;
+ }
+
+ if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, &cert_blob_size ) != CKR_OK )
+ {
+ ret = 3;
+ goto cleanup;
+ }
+
+ cert_blob = malloc( cert_blob_size );
+ if( NULL == cert_blob )
+ {
+ ret = 4;
+ goto cleanup;
+ }
+
+ if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, &cert_blob_size ) != CKR_OK )
+ {
+ ret = 5;
+ goto cleanup;
+ }
+
+ if( 0 != x509parse_crt(cert, cert_blob, cert_blob_size ) )
+ {
+ ret = 6;
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ if( NULL != cert_blob )
+ free( cert_blob );
+
+ return ret;
+}
+
+
+int pkcs11_priv_key_init( pkcs11_context *priv_key,
+ pkcs11h_certificate_t pkcs11_cert )
+{
+ int ret = 1;
+ x509_cert cert;
+
+ memset( &cert, 0, sizeof( cert ) );
+
+ if( priv_key == NULL )
+ goto cleanup;
+
+ if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) )
+ goto cleanup;
+
+ priv_key->len = cert.rsa.len;
+ priv_key->pkcs11h_cert = pkcs11_cert;
+
+ ret = 0;
+
+cleanup:
+ x509_free( &cert );
+
+ return ret;
+}
+
+void pkcs11_priv_key_free( pkcs11_context *priv_key )
+{
+ if( NULL != priv_key )
+ pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert );
+}
+
+int pkcs11_decrypt( pkcs11_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ unsigned int output_max_len )
+{
+ size_t input_len, output_len;
+
+ if( NULL == ctx )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ if( RSA_PUBLIC == mode )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ output_len = input_len = ctx->len;
+
+ if( input_len < 16 || input_len > output_max_len )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ /* Determine size of output buffer */
+ if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
+ input_len, NULL, &output_len ) != CKR_OK )
+ {
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ if( output_len > output_max_len )
+ return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+ if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
+ input_len, output, &output_len ) != CKR_OK )
+ {
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+ *olen = output_len;
+ return( 0 );
+}
+
+int pkcs11_sign( pkcs11_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ size_t olen, asn_len;
+ unsigned char *p = sig;
+
+ if( NULL == ctx )
+ return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+
+ if( RSA_PUBLIC == mode )
+ return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+
+ olen = ctx->len;
+
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ asn_len = 0;
+ memcpy( p, hash, hashlen );
+ break;
+
+ case SIG_RSA_MD2:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 2; break;
+
+ case SIG_RSA_MD4:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 4; break;
+
+ case SIG_RSA_MD5:
+ asn_len = OID_SIZE(ASN1_HASH_MDX);
+ memcpy( p, ASN1_HASH_MDX, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[13] = 5; break;
+
+ case SIG_RSA_SHA1:
+ asn_len = OID_SIZE(ASN1_HASH_SHA1);
+ memcpy( p, ASN1_HASH_SHA1, asn_len );
+ memcpy( p + 15, hash, hashlen );
+ break;
+
+ case SIG_RSA_SHA224:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 4; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA256:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 1; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA384:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 2; p[18] += hashlen; break;
+
+ case SIG_RSA_SHA512:
+ asn_len = OID_SIZE(ASN1_HASH_SHA2X);
+ memcpy( p, ASN1_HASH_SHA2X, asn_len );
+ memcpy( p + asn_len, hash, hashlen );
+ p[1] += hashlen; p[14] = 3; p[18] += hashlen; break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
+ asn_len + hashlen, sig, &olen ) != CKR_OK )
+ {
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ return( 0 );
+}
+
+#endif /* defined(POLARSSL_PKCS11_C) */
diff --git a/polarssl/src/library/rsa.c b/polarssl/src/library/rsa.c
new file mode 100644
index 0000000..72806e1
--- /dev/null
+++ b/polarssl/src/library/rsa.c
@@ -0,0 +1,1219 @@
+/*
+ * The RSA public-key cryptosystem
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
+ *
+ * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
+ * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_RSA_C)
+
+#include "polarssl/rsa.h"
+#include "polarssl/md.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * Initialize an RSA context
+ */
+void rsa_init( rsa_context *ctx,
+ int padding,
+ int hash_id )
+{
+ memset( ctx, 0, sizeof( rsa_context ) );
+
+ ctx->padding = padding;
+ ctx->hash_id = hash_id;
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Generate an RSA keypair
+ */
+int rsa_gen_key( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ unsigned int nbits, int exponent )
+{
+ int ret;
+ mpi P1, Q1, H, G;
+
+ if( f_rng == NULL || nbits < 128 || exponent < 3 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G );
+
+ /*
+ * find primes P and Q with Q < P so that:
+ * GCD( E, (P-1)*(Q-1) ) == 1
+ */
+ MPI_CHK( mpi_lset( &ctx->E, exponent ) );
+
+ do
+ {
+ MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
+ f_rng, p_rng ) );
+
+ MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
+ f_rng, p_rng ) );
+
+ if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
+ mpi_swap( &ctx->P, &ctx->Q );
+
+ if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
+ continue;
+
+ MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
+ if( mpi_msb( &ctx->N ) != nbits )
+ continue;
+
+ MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+ MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+ MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+ MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
+ }
+ while( mpi_cmp_int( &G, 1 ) != 0 );
+
+ /*
+ * D = E^-1 mod ((P-1)*(Q-1))
+ * DP = D mod (P - 1)
+ * DQ = D mod (Q - 1)
+ * QP = Q^-1 mod P
+ */
+ MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
+ MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
+ MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
+ MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
+
+ ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
+
+cleanup:
+
+ mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G );
+
+ if( ret != 0 )
+ {
+ rsa_free( ctx );
+ return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret );
+ }
+
+ return( 0 );
+}
+
+#endif
+
+/*
+ * Check a public RSA key
+ */
+int rsa_check_pubkey( const rsa_context *ctx )
+{
+ if( !ctx->N.p || !ctx->E.p )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( ( ctx->N.p[0] & 1 ) == 0 ||
+ ( ctx->E.p[0] & 1 ) == 0 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( mpi_msb( &ctx->N ) < 128 ||
+ mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( mpi_msb( &ctx->E ) < 2 ||
+ mpi_msb( &ctx->E ) > 64 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ return( 0 );
+}
+
+/*
+ * Check a private RSA key
+ */
+int rsa_check_privkey( const rsa_context *ctx )
+{
+ int ret;
+ mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2;
+
+ if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
+ return( ret );
+
+ if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+ mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 );
+ mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 );
+ mpi_init( &L1 ); mpi_init( &L2 );
+
+ MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
+ MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
+ MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+ MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+ MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+ MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
+
+ MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
+ MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );
+ MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) );
+
+ /*
+ * Check for a valid PKCS1v2 private key
+ */
+ if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
+ mpi_cmp_int( &L2, 0 ) != 0 ||
+ mpi_cmp_int( &I, 1 ) != 0 ||
+ mpi_cmp_int( &G, 1 ) != 0 )
+ {
+ ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED;
+ }
+
+
+cleanup:
+
+ mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 );
+ mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 );
+ mpi_free( &L1 ); mpi_free( &L2 );
+
+ if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED )
+ return( ret );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA public key operation
+ */
+int rsa_public( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t olen;
+ mpi T;
+
+ mpi_init( &T );
+
+ MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+ if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ mpi_free( &T );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ olen = ctx->len;
+ MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
+ MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+ mpi_free( &T );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA private key operation
+ */
+int rsa_private( rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t olen;
+ mpi T, T1, T2;
+
+ mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
+
+ MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+ if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ mpi_free( &T );
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+#if defined(POLARSSL_RSA_NO_CRT)
+ MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
+#else
+ /*
+ * faster decryption using the CRT
+ *
+ * T1 = input ^ dP mod P
+ * T2 = input ^ dQ mod Q
+ */
+ MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
+ MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
+
+ /*
+ * T = (T1 - T2) * (Q^-1 mod P) mod P
+ */
+ MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
+ MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
+ MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
+
+ /*
+ * output = T2 + T * Q
+ */
+ MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
+ MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
+#endif
+
+ olen = ctx->len;
+ MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+ mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_PKCS1_V21)
+/**
+ * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
+ *
+ * \param dst buffer to mask
+ * \param dlen length of destination buffer
+ * \param src source of the mask generation
+ * \param slen length of the source buffer
+ * \param md_ctx message digest context to use
+ */
+static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen,
+ md_context_t *md_ctx )
+{
+ unsigned char mask[POLARSSL_MD_MAX_SIZE];
+ unsigned char counter[4];
+ unsigned char *p;
+ unsigned int hlen;
+ size_t i, use_len;
+
+ memset( mask, 0, POLARSSL_MD_MAX_SIZE );
+ memset( counter, 0, 4 );
+
+ hlen = md_ctx->md_info->size;
+
+ // Generate and apply dbMask
+ //
+ p = dst;
+
+ while( dlen > 0 )
+ {
+ use_len = hlen;
+ if( dlen < hlen )
+ use_len = dlen;
+
+ md_starts( md_ctx );
+ md_update( md_ctx, src, slen );
+ md_update( md_ctx, counter, 4 );
+ md_finish( md_ctx, mask );
+
+ for( i = 0; i < use_len; ++i )
+ *p++ ^= mask[i];
+
+ counter[3]++;
+
+ dlen -= use_len;
+ }
+}
+#endif
+
+/*
+ * Add the message padding, then do an RSA operation
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ size_t nb_pad, olen;
+ int ret;
+ unsigned char *p = output;
+#if defined(POLARSSL_PKCS1_V21)
+ unsigned int hlen;
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+#endif
+
+ olen = ctx->len;
+
+ if( f_rng == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+
+ if( olen < ilen + 11 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ nb_pad = olen - 3 - ilen;
+
+ *p++ = 0;
+ *p++ = RSA_CRYPT;
+
+ while( nb_pad-- > 0 )
+ {
+ int rng_dl = 100;
+
+ do {
+ ret = f_rng( p_rng, p, 1 );
+ } while( *p == 0 && --rng_dl && ret == 0 );
+
+ // Check if RNG failed to generate data
+ //
+ if( rng_dl == 0 || ret != 0)
+ return POLARSSL_ERR_RSA_RNG_FAILED + ret;
+
+ p++;
+ }
+ *p++ = 0;
+ memcpy( p, input, ilen );
+ break;
+
+#if defined(POLARSSL_PKCS1_V21)
+ case RSA_PKCS_V21:
+
+ md_info = md_info_from_type( ctx->hash_id );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = md_get_size( md_info );
+
+ if( olen < ilen + 2 * hlen + 2 || f_rng == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ memset( output, 0, olen );
+ memset( &md_ctx, 0, sizeof( md_context_t ) );
+
+ md_init_ctx( &md_ctx, md_info );
+
+ *p++ = 0;
+
+ // Generate a random octet string seed
+ //
+ if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
+ return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
+
+ p += hlen;
+
+ // Construct DB
+ //
+ md( md_info, p, 0, p );
+ p += hlen;
+ p += olen - 2 * hlen - 2 - ilen;
+ *p++ = 1;
+ memcpy( p, input, ilen );
+
+ // maskedDB: Apply dbMask to DB
+ //
+ mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
+ &md_ctx );
+
+ // maskedSeed: Apply seedMask to seed
+ //
+ mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
+ &md_ctx );
+ break;
+#endif
+
+ default:
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ return( ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, output, output )
+ : rsa_private( ctx, output, output ) );
+}
+
+/*
+ * Do an RSA operation, then remove the message padding
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len)
+{
+ int ret;
+ size_t ilen;
+ unsigned char *p;
+ unsigned char buf[1024];
+#if defined(POLARSSL_PKCS1_V21)
+ unsigned char lhash[POLARSSL_MD_MAX_SIZE];
+ unsigned int hlen;
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+#endif
+
+ ilen = ctx->len;
+
+ if( ilen < 16 || ilen > sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, input, buf )
+ : rsa_private( ctx, input, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+
+ if( *p++ != 0 || *p++ != RSA_CRYPT )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ while( *p != 0 )
+ {
+ if( p >= buf + ilen - 1 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ p++;
+ }
+ p++;
+ break;
+
+#if defined(POLARSSL_PKCS1_V21)
+ case RSA_PKCS_V21:
+
+ if( *p++ != 0 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ md_info = md_info_from_type( ctx->hash_id );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = md_get_size( md_info );
+ memset( &md_ctx, 0, sizeof( md_context_t ) );
+
+ md_init_ctx( &md_ctx, md_info );
+
+ // Generate lHash
+ //
+ md( md_info, lhash, 0, lhash );
+
+ // seed: Apply seedMask to maskedSeed
+ //
+ mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
+ &md_ctx );
+
+ // DB: Apply dbMask to maskedDB
+ //
+ mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
+ &md_ctx );
+
+ p += hlen;
+
+ // Check validity
+ //
+ if( memcmp( lhash, p, hlen ) != 0 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ p += hlen;
+
+ while( *p == 0 && p < buf + ilen )
+ p++;
+
+ if( p == buf + ilen )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ if( *p++ != 0x01 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ break;
+#endif
+
+ default:
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ if (ilen - (p - buf) > output_max_len)
+ return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+ *olen = ilen - (p - buf);
+ memcpy( output, p, *olen );
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ size_t nb_pad, olen;
+ unsigned char *p = sig;
+#if defined(POLARSSL_PKCS1_V21)
+ unsigned char salt[POLARSSL_MD_MAX_SIZE];
+ unsigned int slen, hlen, offset = 0;
+ int ret;
+ size_t msb;
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+#else
+ (void) f_rng;
+ (void) p_rng;
+#endif
+
+ olen = ctx->len;
+
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ nb_pad = olen - 3 - hashlen;
+ break;
+
+ case SIG_RSA_MD2:
+ case SIG_RSA_MD4:
+ case SIG_RSA_MD5:
+ nb_pad = olen - 3 - 34;
+ break;
+
+ case SIG_RSA_SHA1:
+ nb_pad = olen - 3 - 35;
+ break;
+
+ case SIG_RSA_SHA224:
+ nb_pad = olen - 3 - 47;
+ break;
+
+ case SIG_RSA_SHA256:
+ nb_pad = olen - 3 - 51;
+ break;
+
+ case SIG_RSA_SHA384:
+ nb_pad = olen - 3 - 67;
+ break;
+
+ case SIG_RSA_SHA512:
+ nb_pad = olen - 3 - 83;
+ break;
+
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ if( nb_pad < 8 )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ *p++ = 0;
+ *p++ = RSA_SIGN;
+ memset( p, 0xFF, nb_pad );
+ p += nb_pad;
+ *p++ = 0;
+
+ switch( hash_id )
+ {
+ case SIG_RSA_RAW:
+ memcpy( p, hash, hashlen );
+ break;
+
+ case SIG_RSA_MD2:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 2; break;
+
+ case SIG_RSA_MD4:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 4; break;
+
+ case SIG_RSA_MD5:
+ memcpy( p, ASN1_HASH_MDX, 18 );
+ memcpy( p + 18, hash, 16 );
+ p[13] = 5; break;
+
+ case SIG_RSA_SHA1:
+ memcpy( p, ASN1_HASH_SHA1, 15 );
+ memcpy( p + 15, hash, 20 );
+ break;
+
+ case SIG_RSA_SHA224:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 28 );
+ p[1] += 28; p[14] = 4; p[18] += 28; break;
+
+ case SIG_RSA_SHA256:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 32 );
+ p[1] += 32; p[14] = 1; p[18] += 32; break;
+
+ case SIG_RSA_SHA384:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 48 );
+ p[1] += 48; p[14] = 2; p[18] += 48; break;
+
+ case SIG_RSA_SHA512:
+ memcpy( p, ASN1_HASH_SHA2X, 19 );
+ memcpy( p + 19, hash, 64 );
+ p[1] += 64; p[14] = 3; p[18] += 64; break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ break;
+
+#if defined(POLARSSL_PKCS1_V21)
+ case RSA_PKCS_V21:
+
+ if( f_rng == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ switch( hash_id )
+ {
+ case SIG_RSA_MD2:
+ case SIG_RSA_MD4:
+ case SIG_RSA_MD5:
+ hashlen = 16;
+ break;
+
+ case SIG_RSA_SHA1:
+ hashlen = 20;
+ break;
+
+ case SIG_RSA_SHA224:
+ hashlen = 28;
+ break;
+
+ case SIG_RSA_SHA256:
+ hashlen = 32;
+ break;
+
+ case SIG_RSA_SHA384:
+ hashlen = 48;
+ break;
+
+ case SIG_RSA_SHA512:
+ hashlen = 64;
+ break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ md_info = md_info_from_type( ctx->hash_id );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = md_get_size( md_info );
+ slen = hlen;
+
+ memset( sig, 0, olen );
+ memset( &md_ctx, 0, sizeof( md_context_t ) );
+
+ md_init_ctx( &md_ctx, md_info );
+
+ msb = mpi_msb( &ctx->N ) - 1;
+
+ // Generate salt of length slen
+ //
+ if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
+ return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
+
+ // Note: EMSA-PSS encoding is over the length of N - 1 bits
+ //
+ msb = mpi_msb( &ctx->N ) - 1;
+ p += olen - hlen * 2 - 2;
+ *p++ = 0x01;
+ memcpy( p, salt, slen );
+ p += slen;
+
+ // Generate H = Hash( M' )
+ //
+ md_starts( &md_ctx );
+ md_update( &md_ctx, p, 8 );
+ md_update( &md_ctx, hash, hashlen );
+ md_update( &md_ctx, salt, slen );
+ md_finish( &md_ctx, p );
+
+ // Compensate for boundary condition when applying mask
+ //
+ if( msb % 8 == 0 )
+ offset = 1;
+
+ // maskedDB: Apply dbMask to DB
+ //
+ mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
+
+ msb = mpi_msb( &ctx->N ) - 1;
+ sig[0] &= 0xFF >> ( olen * 8 - msb );
+
+ p += hlen;
+ *p++ = 0xBC;
+ break;
+#endif
+
+ default:
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ return( ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, sig )
+ : rsa_private( ctx, sig, sig ) );
+}
+
+/*
+ * Do an RSA operation and check the message digest
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+ int mode,
+ int hash_id,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ int ret;
+ size_t len, siglen;
+ unsigned char *p, c;
+ unsigned char buf[1024];
+#if defined(POLARSSL_PKCS1_V21)
+ unsigned char result[POLARSSL_MD_MAX_SIZE];
+ unsigned char zeros[8];
+ unsigned int hlen;
+ size_t slen, msb;
+ const md_info_t *md_info;
+ md_context_t md_ctx;
+#endif
+ siglen = ctx->len;
+
+ if( siglen < 16 || siglen > sizeof( buf ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == RSA_PUBLIC )
+ ? rsa_public( ctx, sig, buf )
+ : rsa_private( ctx, sig, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ switch( ctx->padding )
+ {
+ case RSA_PKCS_V15:
+
+ if( *p++ != 0 || *p++ != RSA_SIGN )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ while( *p != 0 )
+ {
+ if( p >= buf + siglen - 1 || *p != 0xFF )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ p++;
+ }
+ p++;
+
+ len = siglen - ( p - buf );
+
+ if( len == 33 && hash_id == SIG_RSA_SHA1 )
+ {
+ if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 &&
+ memcmp( p + 13, hash, 20 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ if( len == 34 )
+ {
+ c = p[13];
+ p[13] = 0;
+
+ if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+ if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
+ ( c == 4 && hash_id == SIG_RSA_MD4 ) ||
+ ( c == 5 && hash_id == SIG_RSA_MD5 ) )
+ {
+ if( memcmp( p + 18, hash, 16 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ }
+
+ if( len == 35 && hash_id == SIG_RSA_SHA1 )
+ {
+ if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
+ memcmp( p + 15, hash, 20 ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+ if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
+ ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
+ ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
+ ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
+ {
+ c = p[1] - 17;
+ p[1] = 17;
+ p[14] = 0;
+
+ if( p[18] == c &&
+ memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
+ memcmp( p + 19, hash, c ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+
+ if( len == hashlen && hash_id == SIG_RSA_RAW )
+ {
+ if( memcmp( p, hash, hashlen ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+ }
+
+ break;
+
+#if defined(POLARSSL_PKCS1_V21)
+ case RSA_PKCS_V21:
+
+ if( buf[siglen - 1] != 0xBC )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ switch( hash_id )
+ {
+ case SIG_RSA_MD2:
+ case SIG_RSA_MD4:
+ case SIG_RSA_MD5:
+ hashlen = 16;
+ break;
+
+ case SIG_RSA_SHA1:
+ hashlen = 20;
+ break;
+
+ case SIG_RSA_SHA224:
+ hashlen = 28;
+ break;
+
+ case SIG_RSA_SHA256:
+ hashlen = 32;
+ break;
+
+ case SIG_RSA_SHA384:
+ hashlen = 48;
+ break;
+
+ case SIG_RSA_SHA512:
+ hashlen = 64;
+ break;
+
+ default:
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ md_info = md_info_from_type( ctx->hash_id );
+ if( md_info == NULL )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = md_get_size( md_info );
+ slen = siglen - hlen - 1;
+
+ memset( &md_ctx, 0, sizeof( md_context_t ) );
+ memset( zeros, 0, 8 );
+
+ md_init_ctx( &md_ctx, md_info );
+
+ // Note: EMSA-PSS verification is over the length of N - 1 bits
+ //
+ msb = mpi_msb( &ctx->N ) - 1;
+
+ // Compensate for boundary condition when applying mask
+ //
+ if( msb % 8 == 0 )
+ {
+ p++;
+ siglen -= 1;
+ }
+ if( buf[0] >> ( 8 - siglen * 8 + msb ) )
+ return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+ mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );
+
+ buf[0] &= 0xFF >> ( siglen * 8 - msb );
+
+ while( *p == 0 && p < buf + siglen )
+ p++;
+
+ if( p == buf + siglen )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ if( *p++ != 0x01 )
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+ slen -= p - buf;
+
+ // Generate H = Hash( M' )
+ //
+ md_starts( &md_ctx );
+ md_update( &md_ctx, zeros, 8 );
+ md_update( &md_ctx, hash, hashlen );
+ md_update( &md_ctx, p, slen );
+ md_finish( &md_ctx, result );
+
+ if( memcmp( p + slen, result, hlen ) == 0 )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+#endif
+
+ default:
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ }
+
+ return( POLARSSL_ERR_RSA_INVALID_PADDING );
+}
+
+/*
+ * Free the components of an RSA key
+ */
+void rsa_free( rsa_context *ctx )
+{
+ mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
+ mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
+ mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D );
+ mpi_free( &ctx->E ); mpi_free( &ctx->N );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/sha1.h"
+
+/*
+ * Example RSA-1024 keypair, for test purposes
+ */
+#define KEY_LEN 128
+
+#define RSA_N "9292758453063D803DD603D5E777D788" \
+ "8ED1D5BF35786190FA2F23EBC0848AEA" \
+ "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
+ "7130B9CED7ACDF54CFC7555AC14EEBAB" \
+ "93A89813FBF3C4F8066D2D800F7C38A8" \
+ "1AE31942917403FF4946B0A83D3D3E05" \
+ "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
+ "5E94BB77B07507233A0BC7BAC8F90F79"
+
+#define RSA_E "10001"
+
+#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
+ "66CA472BC44D253102F8B4A9D3BFA750" \
+ "91386C0077937FE33FA3252D28855837" \
+ "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
+ "DF79C5CE07EE72C7F123142198164234" \
+ "CABB724CF78B8173B9F880FC86322407" \
+ "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
+ "071513A1E85B5DFA031F21ECAE91A34D"
+
+#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
+ "2C01CAD19EA484A87EA4377637E75500" \
+ "FCB2005C5C7DD6EC4AC023CDA285D796" \
+ "C3D9E75E1EFC42488BB4F1D13AC30A57"
+
+#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
+ "E211C2B9E5DB1ED0BF61D0D9899620F4" \
+ "910E4168387E3C30AA1E00C339A79508" \
+ "8452DD96A9A5EA5D9DCA68DA636032AF"
+
+#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
+ "3C94D22288ACD763FD8E5600ED4A702D" \
+ "F84198A5F06C2E72236AE490C93F07F8" \
+ "3CC559CD27BC2D1CA488811730BB5725"
+
+#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
+ "D8AAEA56749EA28623272E4F7D0592AF" \
+ "7C1F1313CAC9471B5C523BFE592F517B" \
+ "407A1BD76C164B93DA2D32A383E58357"
+
+#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
+ "F38D18D2B2F0E2DD275AA977E2BF4411" \
+ "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
+ "A74206CEC169D74BF5A8C50D6F48EA08"
+
+#define PT_LEN 24
+#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
+ "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
+
+static int myrand( void *rng_state, unsigned char *output, size_t len )
+{
+ size_t i;
+
+ if( rng_state != NULL )
+ rng_state = NULL;
+
+ for( i = 0; i < len; ++i )
+ output[i] = rand();
+
+ return( 0 );
+}
+
+/*
+ * Checkup routine
+ */
+int rsa_self_test( int verbose )
+{
+ size_t len;
+ rsa_context rsa;
+ unsigned char rsa_plaintext[PT_LEN];
+ unsigned char rsa_decrypted[PT_LEN];
+ unsigned char rsa_ciphertext[KEY_LEN];
+#if defined(POLARSSL_SHA1_C)
+ unsigned char sha1sum[20];
+#endif
+
+ rsa_init( &rsa, RSA_PKCS_V15, 0 );
+
+ rsa.len = KEY_LEN;
+ mpi_read_string( &rsa.N , 16, RSA_N );
+ mpi_read_string( &rsa.E , 16, RSA_E );
+ mpi_read_string( &rsa.D , 16, RSA_D );
+ mpi_read_string( &rsa.P , 16, RSA_P );
+ mpi_read_string( &rsa.Q , 16, RSA_Q );
+ mpi_read_string( &rsa.DP, 16, RSA_DP );
+ mpi_read_string( &rsa.DQ, 16, RSA_DQ );
+ mpi_read_string( &rsa.QP, 16, RSA_QP );
+
+ if( verbose != 0 )
+ printf( " RSA key validation: " );
+
+ if( rsa_check_pubkey( &rsa ) != 0 ||
+ rsa_check_privkey( &rsa ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 encryption : " );
+
+ memcpy( rsa_plaintext, RSA_PT, PT_LEN );
+
+ if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN,
+ rsa_plaintext, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 decryption : " );
+
+ if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
+ rsa_ciphertext, rsa_decrypted,
+ sizeof(rsa_decrypted) ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+#if defined(POLARSSL_SHA1_C)
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 data sign : " );
+
+ sha1( rsa_plaintext, PT_LEN, sha1sum );
+
+ if( rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20,
+ sha1sum, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n PKCS#1 sig. verify: " );
+
+ if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20,
+ sha1sum, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n\n" );
+#endif /* POLARSSL_SHA1_C */
+
+ rsa_free( &rsa );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/sha1.c b/polarssl/src/library/sha1.c
new file mode 100644
index 0000000..72ca063
--- /dev/null
+++ b/polarssl/src/library/sha1.c
@@ -0,0 +1,624 @@
+/*
+ * FIPS-180-1 compliant SHA-1 implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The SHA-1 standard was published by NIST in 1993.
+ *
+ * http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SHA1_C)
+
+#include "polarssl/sha1.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * SHA-1 context setup
+ */
+void sha1_starts( sha1_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+}
+
+static void sha1_process( sha1_context *ctx, const unsigned char data[64] )
+{
+ unsigned long temp, W[16], A, B, C, D, E;
+
+ GET_ULONG_BE( W[ 0], data, 0 );
+ GET_ULONG_BE( W[ 1], data, 4 );
+ GET_ULONG_BE( W[ 2], data, 8 );
+ GET_ULONG_BE( W[ 3], data, 12 );
+ GET_ULONG_BE( W[ 4], data, 16 );
+ GET_ULONG_BE( W[ 5], data, 20 );
+ GET_ULONG_BE( W[ 6], data, 24 );
+ GET_ULONG_BE( W[ 7], data, 28 );
+ GET_ULONG_BE( W[ 8], data, 32 );
+ GET_ULONG_BE( W[ 9], data, 36 );
+ GET_ULONG_BE( W[10], data, 40 );
+ GET_ULONG_BE( W[11], data, 44 );
+ GET_ULONG_BE( W[12], data, 48 );
+ GET_ULONG_BE( W[13], data, 52 );
+ GET_ULONG_BE( W[14], data, 56 );
+ GET_ULONG_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) \
+( \
+ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
+ W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) \
+{ \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P( A, B, C, D, E, W[0] );
+ P( E, A, B, C, D, W[1] );
+ P( D, E, A, B, C, W[2] );
+ P( C, D, E, A, B, W[3] );
+ P( B, C, D, E, A, W[4] );
+ P( A, B, C, D, E, W[5] );
+ P( E, A, B, C, D, W[6] );
+ P( D, E, A, B, C, W[7] );
+ P( C, D, E, A, B, W[8] );
+ P( B, C, D, E, A, W[9] );
+ P( A, B, C, D, E, W[10] );
+ P( E, A, B, C, D, W[11] );
+ P( D, E, A, B, C, W[12] );
+ P( C, D, E, A, B, W[13] );
+ P( B, C, D, E, A, W[14] );
+ P( A, B, C, D, E, W[15] );
+ P( E, A, B, C, D, R(16) );
+ P( D, E, A, B, C, R(17) );
+ P( C, D, E, A, B, R(18) );
+ P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P( A, B, C, D, E, R(20) );
+ P( E, A, B, C, D, R(21) );
+ P( D, E, A, B, C, R(22) );
+ P( C, D, E, A, B, R(23) );
+ P( B, C, D, E, A, R(24) );
+ P( A, B, C, D, E, R(25) );
+ P( E, A, B, C, D, R(26) );
+ P( D, E, A, B, C, R(27) );
+ P( C, D, E, A, B, R(28) );
+ P( B, C, D, E, A, R(29) );
+ P( A, B, C, D, E, R(30) );
+ P( E, A, B, C, D, R(31) );
+ P( D, E, A, B, C, R(32) );
+ P( C, D, E, A, B, R(33) );
+ P( B, C, D, E, A, R(34) );
+ P( A, B, C, D, E, R(35) );
+ P( E, A, B, C, D, R(36) );
+ P( D, E, A, B, C, R(37) );
+ P( C, D, E, A, B, R(38) );
+ P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P( A, B, C, D, E, R(40) );
+ P( E, A, B, C, D, R(41) );
+ P( D, E, A, B, C, R(42) );
+ P( C, D, E, A, B, R(43) );
+ P( B, C, D, E, A, R(44) );
+ P( A, B, C, D, E, R(45) );
+ P( E, A, B, C, D, R(46) );
+ P( D, E, A, B, C, R(47) );
+ P( C, D, E, A, B, R(48) );
+ P( B, C, D, E, A, R(49) );
+ P( A, B, C, D, E, R(50) );
+ P( E, A, B, C, D, R(51) );
+ P( D, E, A, B, C, R(52) );
+ P( C, D, E, A, B, R(53) );
+ P( B, C, D, E, A, R(54) );
+ P( A, B, C, D, E, R(55) );
+ P( E, A, B, C, D, R(56) );
+ P( D, E, A, B, C, R(57) );
+ P( C, D, E, A, B, R(58) );
+ P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P( A, B, C, D, E, R(60) );
+ P( E, A, B, C, D, R(61) );
+ P( D, E, A, B, C, R(62) );
+ P( C, D, E, A, B, R(63) );
+ P( B, C, D, E, A, R(64) );
+ P( A, B, C, D, E, R(65) );
+ P( E, A, B, C, D, R(66) );
+ P( D, E, A, B, C, R(67) );
+ P( C, D, E, A, B, R(68) );
+ P( B, C, D, E, A, R(69) );
+ P( A, B, C, D, E, R(70) );
+ P( E, A, B, C, D, R(71) );
+ P( D, E, A, B, C, R(72) );
+ P( C, D, E, A, B, R(73) );
+ P( B, C, D, E, A, R(74) );
+ P( A, B, C, D, E, R(75) );
+ P( E, A, B, C, D, R(76) );
+ P( D, E, A, B, C, R(77) );
+ P( C, D, E, A, B, R(78) );
+ P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ unsigned long left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (unsigned long) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (unsigned long) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+ sha1_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ sha1_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, ilen );
+ }
+}
+
+static const unsigned char sha1_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+void sha1_finish( sha1_context *ctx, unsigned char output[20] )
+{
+ unsigned long last, padn;
+ unsigned long high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_ULONG_BE( high, msglen, 0 );
+ PUT_ULONG_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ sha1_update( ctx, (unsigned char *) sha1_padding, padn );
+ sha1_update( ctx, msglen, 8 );
+
+ PUT_ULONG_BE( ctx->state[0], output, 0 );
+ PUT_ULONG_BE( ctx->state[1], output, 4 );
+ PUT_ULONG_BE( ctx->state[2], output, 8 );
+ PUT_ULONG_BE( ctx->state[3], output, 12 );
+ PUT_ULONG_BE( ctx->state[4], output, 16 );
+}
+
+/*
+ * output = SHA-1( input buffer )
+ */
+void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
+{
+ sha1_context ctx;
+
+ sha1_starts( &ctx );
+ sha1_update( &ctx, input, ilen );
+ sha1_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-1( file contents )
+ */
+int sha1_file( const char *path, unsigned char output[20] )
+{
+ FILE *f;
+ size_t n;
+ sha1_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
+
+ sha1_starts( &ctx );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ sha1_update( &ctx, buf, n );
+
+ sha1_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-1 HMAC context setup
+ */
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
+{
+ size_t i;
+ unsigned char sum[20];
+
+ if( keylen > 64 )
+ {
+ sha1( key, keylen, sum );
+ keylen = 20;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ sha1_starts( ctx );
+ sha1_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-1 HMAC process buffer
+ */
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+{
+ sha1_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-1 HMAC final digest
+ */
+void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
+{
+ unsigned char tmpbuf[20];
+
+ sha1_finish( ctx, tmpbuf );
+ sha1_starts( ctx );
+ sha1_update( ctx, ctx->opad, 64 );
+ sha1_update( ctx, tmpbuf, 20 );
+ sha1_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA1 HMAC context reset
+ */
+void sha1_hmac_reset( sha1_context *ctx )
+{
+ sha1_starts( ctx );
+ sha1_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-1( hmac key, input buffer )
+ */
+void sha1_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[20] )
+{
+ sha1_context ctx;
+
+ sha1_hmac_starts( &ctx, key, keylen );
+ sha1_hmac_update( &ctx, input, ilen );
+ sha1_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha1_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-1 test vectors
+ */
+static unsigned char sha1_test_buf[3][57] =
+{
+ { "abc" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "" }
+};
+
+static const int sha1_test_buflen[3] =
+{
+ 3, 56, 1000
+};
+
+static const unsigned char sha1_test_sum[3][20] =
+{
+ { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+ 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+ 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
+ { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+ 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
+};
+
+/*
+ * RFC 2202 test vectors
+ */
+static unsigned char sha1_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+ "\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+ "\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 80 times */
+ { "" }
+};
+
+static const int sha1_hmac_test_keylen[7] =
+{
+ 20, 4, 20, 25, 20, 80, 80
+};
+
+static unsigned char sha1_hmac_test_buf[7][74] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "Test Using Larger Than Block-Size Key and Larger"
+ " Than One Block-Size Data" }
+};
+
+static const int sha1_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 73
+};
+
+static const unsigned char sha1_hmac_test_sum[7][20] =
+{
+ { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
+ 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
+ { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
+ 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
+ { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
+ 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
+ { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
+ 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
+ { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
+ 0x7B, 0xE1 },
+ { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
+ 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
+ { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
+ 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha1_self_test( int verbose )
+{
+ int i, j, buflen;
+ unsigned char buf[1024];
+ unsigned char sha1sum[20];
+ sha1_context ctx;
+
+ /*
+ * SHA-1
+ */
+ for( i = 0; i < 3; i++ )
+ {
+ if( verbose != 0 )
+ printf( " SHA-1 test #%d: ", i + 1 );
+
+ sha1_starts( &ctx );
+
+ if( i == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ sha1_update( &ctx, buf, buflen );
+ }
+ else
+ sha1_update( &ctx, sha1_test_buf[i],
+ sha1_test_buflen[i] );
+
+ sha1_finish( &ctx, sha1sum );
+
+ if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ printf( " HMAC-SHA-1 test #%d: ", i + 1 );
+
+ if( i == 5 || i == 6 )
+ {
+ memset( buf, '\xAA', buflen = 80 );
+ sha1_hmac_starts( &ctx, buf, buflen );
+ }
+ else
+ sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
+ sha1_hmac_test_keylen[i] );
+
+ sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
+ sha1_hmac_test_buflen[i] );
+
+ sha1_hmac_finish( &ctx, sha1sum );
+
+ buflen = ( i == 4 ) ? 12 : 20;
+
+ if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/sha2.c b/polarssl/src/library/sha2.c
new file mode 100644
index 0000000..4b5e696
--- /dev/null
+++ b/polarssl/src/library/sha2.c
@@ -0,0 +1,705 @@
+/*
+ * FIPS-180-2 compliant SHA-256 implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The SHA-256 Secure Hash Standard was published by NIST in 2002.
+ *
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SHA2_C)
+
+#include "polarssl/sha2.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * SHA-256 context setup
+ */
+void sha2_starts( sha2_context *ctx, int is224 )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if( is224 == 0 )
+ {
+ /* SHA-256 */
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+ }
+ else
+ {
+ /* SHA-224 */
+ ctx->state[0] = 0xC1059ED8;
+ ctx->state[1] = 0x367CD507;
+ ctx->state[2] = 0x3070DD17;
+ ctx->state[3] = 0xF70E5939;
+ ctx->state[4] = 0xFFC00B31;
+ ctx->state[5] = 0x68581511;
+ ctx->state[6] = 0x64F98FA7;
+ ctx->state[7] = 0xBEFA4FA4;
+ }
+
+ ctx->is224 = is224;
+}
+
+static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
+{
+ unsigned long temp1, temp2, W[64];
+ unsigned long A, B, C, D, E, F, G, H;
+
+ GET_ULONG_BE( W[ 0], data, 0 );
+ GET_ULONG_BE( W[ 1], data, 4 );
+ GET_ULONG_BE( W[ 2], data, 8 );
+ GET_ULONG_BE( W[ 3], data, 12 );
+ GET_ULONG_BE( W[ 4], data, 16 );
+ GET_ULONG_BE( W[ 5], data, 20 );
+ GET_ULONG_BE( W[ 6], data, 24 );
+ GET_ULONG_BE( W[ 7], data, 28 );
+ GET_ULONG_BE( W[ 8], data, 32 );
+ GET_ULONG_BE( W[ 9], data, 36 );
+ GET_ULONG_BE( W[10], data, 40 );
+ GET_ULONG_BE( W[11], data, 44 );
+ GET_ULONG_BE( W[12], data, 48 );
+ GET_ULONG_BE( W[13], data, 52 );
+ GET_ULONG_BE( W[14], data, 56 );
+ GET_ULONG_BE( W[15], data, 60 );
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+
+ P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
+ P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
+ P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
+ P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
+ P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
+ P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
+ P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
+ P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
+ P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
+ P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
+ P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
+ P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
+ P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
+ P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
+ P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
+ P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
+ P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
+ P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
+ P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
+ P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
+ P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
+ P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
+ P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
+ P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
+ P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
+ P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
+ P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
+ P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
+ P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
+ P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
+ P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
+ P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
+ P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
+ P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
+ P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
+ P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
+ P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
+ P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
+ P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
+ P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
+ P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
+ P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
+ P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
+ P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
+ P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
+ P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
+ P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
+ P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
+ P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
+ P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
+ P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
+ P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
+ P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
+ P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
+ P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
+ P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
+ P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
+ P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
+ P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
+ P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
+ P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
+ P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
+ P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
+ P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+/*
+ * SHA-256 process buffer
+ */
+void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ unsigned long left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (unsigned long) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (unsigned long) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+ sha2_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ sha2_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, ilen );
+ }
+}
+
+static const unsigned char sha2_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-256 final digest
+ */
+void sha2_finish( sha2_context *ctx, unsigned char output[32] )
+{
+ unsigned long last, padn;
+ unsigned long high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_ULONG_BE( high, msglen, 0 );
+ PUT_ULONG_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ sha2_update( ctx, (unsigned char *) sha2_padding, padn );
+ sha2_update( ctx, msglen, 8 );
+
+ PUT_ULONG_BE( ctx->state[0], output, 0 );
+ PUT_ULONG_BE( ctx->state[1], output, 4 );
+ PUT_ULONG_BE( ctx->state[2], output, 8 );
+ PUT_ULONG_BE( ctx->state[3], output, 12 );
+ PUT_ULONG_BE( ctx->state[4], output, 16 );
+ PUT_ULONG_BE( ctx->state[5], output, 20 );
+ PUT_ULONG_BE( ctx->state[6], output, 24 );
+
+ if( ctx->is224 == 0 )
+ PUT_ULONG_BE( ctx->state[7], output, 28 );
+}
+
+/*
+ * output = SHA-256( input buffer )
+ */
+void sha2( const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 )
+{
+ sha2_context ctx;
+
+ sha2_starts( &ctx, is224 );
+ sha2_update( &ctx, input, ilen );
+ sha2_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha2_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-256( file contents )
+ */
+int sha2_file( const char *path, unsigned char output[32], int is224 )
+{
+ FILE *f;
+ size_t n;
+ sha2_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_SHA2_FILE_IO_ERROR );
+
+ sha2_starts( &ctx, is224 );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ sha2_update( &ctx, buf, n );
+
+ sha2_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha2_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_SHA2_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-256 HMAC context setup
+ */
+void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, size_t keylen,
+ int is224 )
+{
+ size_t i;
+ unsigned char sum[32];
+
+ if( keylen > 64 )
+ {
+ sha2( key, keylen, sum, is224 );
+ keylen = ( is224 ) ? 28 : 32;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 64 );
+ memset( ctx->opad, 0x5C, 64 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ sha2_starts( ctx, is224 );
+ sha2_update( ctx, ctx->ipad, 64 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-256 HMAC process buffer
+ */
+void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, size_t ilen )
+{
+ sha2_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-256 HMAC final digest
+ */
+void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
+{
+ int is224, hlen;
+ unsigned char tmpbuf[32];
+
+ is224 = ctx->is224;
+ hlen = ( is224 == 0 ) ? 32 : 28;
+
+ sha2_finish( ctx, tmpbuf );
+ sha2_starts( ctx, is224 );
+ sha2_update( ctx, ctx->opad, 64 );
+ sha2_update( ctx, tmpbuf, hlen );
+ sha2_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA-256 HMAC context reset
+ */
+void sha2_hmac_reset( sha2_context *ctx )
+{
+ sha2_starts( ctx, ctx->is224 );
+ sha2_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-SHA-256( hmac key, input buffer )
+ */
+void sha2_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 )
+{
+ sha2_context ctx;
+
+ sha2_hmac_starts( &ctx, key, keylen, is224 );
+ sha2_hmac_update( &ctx, input, ilen );
+ sha2_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha2_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * FIPS-180-2 test vectors
+ */
+static unsigned char sha2_test_buf[3][57] =
+{
+ { "abc" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "" }
+};
+
+static const int sha2_test_buflen[3] =
+{
+ 3, 56, 1000
+};
+
+static const unsigned char sha2_test_sum[6][32] =
+{
+ /*
+ * SHA-224 test vectors
+ */
+ { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+ 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+ 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+ 0xE3, 0x6C, 0x9D, 0xA7 },
+ { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+ 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+ 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+ 0x52, 0x52, 0x25, 0x25 },
+ { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
+ 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
+ 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
+ 0x4E, 0xE7, 0xAD, 0x67 },
+
+ /*
+ * SHA-256 test vectors
+ */
+ { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+ 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+ 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+ 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
+ { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+ 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+ 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+ 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
+ { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
+ 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
+ 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
+ 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
+};
+
+/*
+ * RFC 4231 test vectors
+ */
+static unsigned char sha2_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+ "\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+ "\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 131 times */
+ { "" }
+};
+
+static const int sha2_hmac_test_keylen[7] =
+{
+ 20, 4, 20, 25, 20, 131, 131
+};
+
+static unsigned char sha2_hmac_test_buf[7][153] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "This is a test using a larger than block-size key "
+ "and a larger than block-size data. The key needs to "
+ "be hashed before being used by the HMAC algorithm." }
+};
+
+static const int sha2_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 152
+};
+
+static const unsigned char sha2_hmac_test_sum[14][32] =
+{
+ /*
+ * HMAC-SHA-224 test vectors
+ */
+ { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
+ 0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
+ 0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
+ 0x53, 0x68, 0x4B, 0x22 },
+ { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
+ 0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
+ 0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
+ 0x8F, 0xD0, 0x5E, 0x44 },
+ { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
+ 0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
+ 0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
+ 0xEC, 0x83, 0x33, 0xEA },
+ { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
+ 0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
+ 0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
+ 0xE7, 0xAF, 0xEC, 0x5A },
+ { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
+ 0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
+ { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
+ 0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
+ 0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
+ 0x3F, 0xA6, 0x87, 0x0E },
+ { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
+ 0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
+ 0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
+ 0xF6, 0xF5, 0x65, 0xD1 },
+
+ /*
+ * HMAC-SHA-256 test vectors
+ */
+ { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
+ 0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
+ 0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
+ 0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
+ { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
+ 0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
+ 0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
+ 0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
+ { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
+ 0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
+ 0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
+ 0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
+ { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
+ 0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
+ 0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
+ 0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
+ { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
+ 0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
+ { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
+ 0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
+ 0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
+ 0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
+ { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
+ 0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
+ 0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
+ 0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha2_self_test( int verbose )
+{
+ int i, j, k, buflen;
+ unsigned char buf[1024];
+ unsigned char sha2sum[32];
+ sha2_context ctx;
+
+ for( i = 0; i < 6; i++ )
+ {
+ j = i % 3;
+ k = i < 3;
+
+ if( verbose != 0 )
+ printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+ sha2_starts( &ctx, k );
+
+ if( j == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ sha2_update( &ctx, buf, buflen );
+ }
+ else
+ sha2_update( &ctx, sha2_test_buf[j],
+ sha2_test_buflen[j] );
+
+ sha2_finish( &ctx, sha2sum );
+
+ if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 14; i++ )
+ {
+ j = i % 7;
+ k = i < 7;
+
+ if( verbose != 0 )
+ printf( " HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+ if( j == 5 || j == 6 )
+ {
+ memset( buf, '\xAA', buflen = 131 );
+ sha2_hmac_starts( &ctx, buf, buflen, k );
+ }
+ else
+ sha2_hmac_starts( &ctx, sha2_hmac_test_key[j],
+ sha2_hmac_test_keylen[j], k );
+
+ sha2_hmac_update( &ctx, sha2_hmac_test_buf[j],
+ sha2_hmac_test_buflen[j] );
+
+ sha2_hmac_finish( &ctx, sha2sum );
+
+ buflen = ( j == 4 ) ? 16 : 32 - k * 4;
+
+ if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/sha4.c b/polarssl/src/library/sha4.c
new file mode 100644
index 0000000..cf54d11
--- /dev/null
+++ b/polarssl/src/library/sha4.c
@@ -0,0 +1,760 @@
+/*
+ * FIPS-180-2 compliant SHA-384/512 implementation
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The SHA-512 Secure Hash Standard was published by NIST in 2002.
+ *
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SHA4_C)
+
+#include "polarssl/sha4.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+/*
+ * 64-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT64_BE
+#define GET_UINT64_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long64) (b)[(i) ] << 56 ) \
+ | ( (unsigned long64) (b)[(i) + 1] << 48 ) \
+ | ( (unsigned long64) (b)[(i) + 2] << 40 ) \
+ | ( (unsigned long64) (b)[(i) + 3] << 32 ) \
+ | ( (unsigned long64) (b)[(i) + 4] << 24 ) \
+ | ( (unsigned long64) (b)[(i) + 5] << 16 ) \
+ | ( (unsigned long64) (b)[(i) + 6] << 8 ) \
+ | ( (unsigned long64) (b)[(i) + 7] ); \
+}
+#endif
+
+#ifndef PUT_UINT64_BE
+#define PUT_UINT64_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
+ (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 7] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * Round constants
+ */
+static const unsigned long64 K[80] =
+{
+ UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
+ UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
+ UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
+ UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
+ UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
+ UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
+ UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
+ UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
+ UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
+ UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
+ UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
+ UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
+ UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
+ UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
+ UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
+ UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
+ UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
+ UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
+ UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
+ UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
+ UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
+ UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
+ UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
+ UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
+ UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
+ UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
+ UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
+ UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
+ UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
+ UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
+ UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
+ UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
+ UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
+ UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
+ UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
+ UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
+ UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
+ UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
+ UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
+ UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
+};
+
+/*
+ * SHA-512 context setup
+ */
+void sha4_starts( sha4_context *ctx, int is384 )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if( is384 == 0 )
+ {
+ /* SHA-512 */
+ ctx->state[0] = UL64(0x6A09E667F3BCC908);
+ ctx->state[1] = UL64(0xBB67AE8584CAA73B);
+ ctx->state[2] = UL64(0x3C6EF372FE94F82B);
+ ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
+ ctx->state[4] = UL64(0x510E527FADE682D1);
+ ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
+ ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
+ ctx->state[7] = UL64(0x5BE0CD19137E2179);
+ }
+ else
+ {
+ /* SHA-384 */
+ ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
+ ctx->state[1] = UL64(0x629A292A367CD507);
+ ctx->state[2] = UL64(0x9159015A3070DD17);
+ ctx->state[3] = UL64(0x152FECD8F70E5939);
+ ctx->state[4] = UL64(0x67332667FFC00B31);
+ ctx->state[5] = UL64(0x8EB44A8768581511);
+ ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
+ ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
+ }
+
+ ctx->is384 = is384;
+}
+
+static void sha4_process( sha4_context *ctx, const unsigned char data[128] )
+{
+ int i;
+ unsigned long64 temp1, temp2, W[80];
+ unsigned long64 A, B, C, D, E, F, G, H;
+
+#define SHR(x,n) (x >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
+
+#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
+#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
+
+#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
+#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ for( i = 0; i < 16; i++ )
+ {
+ GET_UINT64_BE( W[i], data, i << 3 );
+ }
+
+ for( ; i < 80; i++ )
+ {
+ W[i] = S1(W[i - 2]) + W[i - 7] +
+ S0(W[i - 15]) + W[i - 16];
+ }
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+ i = 0;
+
+ do
+ {
+ P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
+ P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
+ P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
+ P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
+ P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
+ P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
+ P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
+ P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
+ }
+ while( i < 80 );
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+/*
+ * SHA-512 process buffer
+ */
+void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen )
+{
+ size_t fill;
+ unsigned int left;
+
+ if( ilen <= 0 )
+ return;
+
+ left = (unsigned int) (ctx->total[0] & 0x7F);
+ fill = 128 - left;
+
+ ctx->total[0] += (unsigned long64) ilen;
+
+ if( ctx->total[0] < (unsigned long64) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+ sha4_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 128 )
+ {
+ sha4_process( ctx, input );
+ input += 128;
+ ilen -= 128;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, ilen );
+ }
+}
+
+static const unsigned char sha4_padding[128] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-512 final digest
+ */
+void sha4_finish( sha4_context *ctx, unsigned char output[64] )
+{
+ size_t last, padn;
+ unsigned long64 high, low;
+ unsigned char msglen[16];
+
+ high = ( ctx->total[0] >> 61 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT64_BE( high, msglen, 0 );
+ PUT_UINT64_BE( low, msglen, 8 );
+
+ last = (size_t)( ctx->total[0] & 0x7F );
+ padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
+
+ sha4_update( ctx, (unsigned char *) sha4_padding, padn );
+ sha4_update( ctx, msglen, 16 );
+
+ PUT_UINT64_BE( ctx->state[0], output, 0 );
+ PUT_UINT64_BE( ctx->state[1], output, 8 );
+ PUT_UINT64_BE( ctx->state[2], output, 16 );
+ PUT_UINT64_BE( ctx->state[3], output, 24 );
+ PUT_UINT64_BE( ctx->state[4], output, 32 );
+ PUT_UINT64_BE( ctx->state[5], output, 40 );
+
+ if( ctx->is384 == 0 )
+ {
+ PUT_UINT64_BE( ctx->state[6], output, 48 );
+ PUT_UINT64_BE( ctx->state[7], output, 56 );
+ }
+}
+
+/*
+ * output = SHA-512( input buffer )
+ */
+void sha4( const unsigned char *input, size_t ilen,
+ unsigned char output[64], int is384 )
+{
+ sha4_context ctx;
+
+ sha4_starts( &ctx, is384 );
+ sha4_update( &ctx, input, ilen );
+ sha4_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha4_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = SHA-512( file contents )
+ */
+int sha4_file( const char *path, unsigned char output[64], int is384 )
+{
+ FILE *f;
+ size_t n;
+ sha4_context ctx;
+ unsigned char buf[1024];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_SHA4_FILE_IO_ERROR );
+
+ sha4_starts( &ctx, is384 );
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ sha4_update( &ctx, buf, n );
+
+ sha4_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha4_context ) );
+
+ if( ferror( f ) != 0 )
+ {
+ fclose( f );
+ return( POLARSSL_ERR_SHA4_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+ return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * SHA-512 HMAC context setup
+ */
+void sha4_hmac_starts( sha4_context *ctx, const unsigned char *key, size_t keylen,
+ int is384 )
+{
+ size_t i;
+ unsigned char sum[64];
+
+ if( keylen > 128 )
+ {
+ sha4( key, keylen, sum, is384 );
+ keylen = ( is384 ) ? 48 : 64;
+ key = sum;
+ }
+
+ memset( ctx->ipad, 0x36, 128 );
+ memset( ctx->opad, 0x5C, 128 );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+ ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+ }
+
+ sha4_starts( ctx, is384 );
+ sha4_update( ctx, ctx->ipad, 128 );
+
+ memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SHA-512 HMAC process buffer
+ */
+void sha4_hmac_update( sha4_context *ctx,
+ const unsigned char *input, size_t ilen )
+{
+ sha4_update( ctx, input, ilen );
+}
+
+/*
+ * SHA-512 HMAC final digest
+ */
+void sha4_hmac_finish( sha4_context *ctx, unsigned char output[64] )
+{
+ int is384, hlen;
+ unsigned char tmpbuf[64];
+
+ is384 = ctx->is384;
+ hlen = ( is384 == 0 ) ? 64 : 48;
+
+ sha4_finish( ctx, tmpbuf );
+ sha4_starts( ctx, is384 );
+ sha4_update( ctx, ctx->opad, 128 );
+ sha4_update( ctx, tmpbuf, hlen );
+ sha4_finish( ctx, output );
+
+ memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * SHA-512 HMAC context reset
+ */
+void sha4_hmac_reset( sha4_context *ctx )
+{
+ sha4_starts( ctx, ctx->is384 );
+ sha4_update( ctx, ctx->ipad, 128 );
+}
+
+/*
+ * output = HMAC-SHA-512( hmac key, input buffer )
+ */
+void sha4_hmac( const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char output[64], int is384 )
+{
+ sha4_context ctx;
+
+ sha4_hmac_starts( &ctx, key, keylen, is384 );
+ sha4_hmac_update( &ctx, input, ilen );
+ sha4_hmac_finish( &ctx, output );
+
+ memset( &ctx, 0, sizeof( sha4_context ) );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * FIPS-180-2 test vectors
+ */
+static unsigned char sha4_test_buf[3][113] =
+{
+ { "abc" },
+ { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
+ { "" }
+};
+
+static const int sha4_test_buflen[3] =
+{
+ 3, 112, 1000
+};
+
+static const unsigned char sha4_test_sum[6][64] =
+{
+ /*
+ * SHA-384 test vectors
+ */
+ { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
+ 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
+ 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
+ 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
+ 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
+ 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
+ { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
+ 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
+ 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
+ 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
+ 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
+ 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
+ { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
+ 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
+ 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
+ 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
+ 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
+ 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
+
+ /*
+ * SHA-512 test vectors
+ */
+ { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
+ 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
+ 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
+ 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
+ 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
+ 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
+ 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
+ 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
+ { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
+ 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
+ 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
+ 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
+ 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
+ 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
+ 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
+ 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
+ { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
+ 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
+ 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
+ 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
+ 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
+ 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
+ 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
+ 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
+};
+
+/*
+ * RFC 4231 test vectors
+ */
+static unsigned char sha4_hmac_test_key[7][26] =
+{
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+ "\x0B\x0B\x0B\x0B" },
+ { "Jefe" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+ "\x0C\x0C\x0C\x0C" },
+ { "" }, /* 0xAA 131 times */
+ { "" }
+};
+
+static const int sha4_hmac_test_keylen[7] =
+{
+ 20, 4, 20, 25, 20, 131, 131
+};
+
+static unsigned char sha4_hmac_test_buf[7][153] =
+{
+ { "Hi There" },
+ { "what do ya want for nothing?" },
+ { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
+ { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
+ { "Test With Truncation" },
+ { "Test Using Larger Than Block-Size Key - Hash Key First" },
+ { "This is a test using a larger than block-size key "
+ "and a larger than block-size data. The key needs to "
+ "be hashed before being used by the HMAC algorithm." }
+};
+
+static const int sha4_hmac_test_buflen[7] =
+{
+ 8, 28, 50, 50, 20, 54, 152
+};
+
+static const unsigned char sha4_hmac_test_sum[14][64] =
+{
+ /*
+ * HMAC-SHA-384 test vectors
+ */
+ { 0xAF, 0xD0, 0x39, 0x44, 0xD8, 0x48, 0x95, 0x62,
+ 0x6B, 0x08, 0x25, 0xF4, 0xAB, 0x46, 0x90, 0x7F,
+ 0x15, 0xF9, 0xDA, 0xDB, 0xE4, 0x10, 0x1E, 0xC6,
+ 0x82, 0xAA, 0x03, 0x4C, 0x7C, 0xEB, 0xC5, 0x9C,
+ 0xFA, 0xEA, 0x9E, 0xA9, 0x07, 0x6E, 0xDE, 0x7F,
+ 0x4A, 0xF1, 0x52, 0xE8, 0xB2, 0xFA, 0x9C, 0xB6 },
+ { 0xAF, 0x45, 0xD2, 0xE3, 0x76, 0x48, 0x40, 0x31,
+ 0x61, 0x7F, 0x78, 0xD2, 0xB5, 0x8A, 0x6B, 0x1B,
+ 0x9C, 0x7E, 0xF4, 0x64, 0xF5, 0xA0, 0x1B, 0x47,
+ 0xE4, 0x2E, 0xC3, 0x73, 0x63, 0x22, 0x44, 0x5E,
+ 0x8E, 0x22, 0x40, 0xCA, 0x5E, 0x69, 0xE2, 0xC7,
+ 0x8B, 0x32, 0x39, 0xEC, 0xFA, 0xB2, 0x16, 0x49 },
+ { 0x88, 0x06, 0x26, 0x08, 0xD3, 0xE6, 0xAD, 0x8A,
+ 0x0A, 0xA2, 0xAC, 0xE0, 0x14, 0xC8, 0xA8, 0x6F,
+ 0x0A, 0xA6, 0x35, 0xD9, 0x47, 0xAC, 0x9F, 0xEB,
+ 0xE8, 0x3E, 0xF4, 0xE5, 0x59, 0x66, 0x14, 0x4B,
+ 0x2A, 0x5A, 0xB3, 0x9D, 0xC1, 0x38, 0x14, 0xB9,
+ 0x4E, 0x3A, 0xB6, 0xE1, 0x01, 0xA3, 0x4F, 0x27 },
+ { 0x3E, 0x8A, 0x69, 0xB7, 0x78, 0x3C, 0x25, 0x85,
+ 0x19, 0x33, 0xAB, 0x62, 0x90, 0xAF, 0x6C, 0xA7,
+ 0x7A, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9C,
+ 0xC5, 0x57, 0x7C, 0x6E, 0x1F, 0x57, 0x3B, 0x4E,
+ 0x68, 0x01, 0xDD, 0x23, 0xC4, 0xA7, 0xD6, 0x79,
+ 0xCC, 0xF8, 0xA3, 0x86, 0xC6, 0x74, 0xCF, 0xFB },
+ { 0x3A, 0xBF, 0x34, 0xC3, 0x50, 0x3B, 0x2A, 0x23,
+ 0xA4, 0x6E, 0xFC, 0x61, 0x9B, 0xAE, 0xF8, 0x97 },
+ { 0x4E, 0xCE, 0x08, 0x44, 0x85, 0x81, 0x3E, 0x90,
+ 0x88, 0xD2, 0xC6, 0x3A, 0x04, 0x1B, 0xC5, 0xB4,
+ 0x4F, 0x9E, 0xF1, 0x01, 0x2A, 0x2B, 0x58, 0x8F,
+ 0x3C, 0xD1, 0x1F, 0x05, 0x03, 0x3A, 0xC4, 0xC6,
+ 0x0C, 0x2E, 0xF6, 0xAB, 0x40, 0x30, 0xFE, 0x82,
+ 0x96, 0x24, 0x8D, 0xF1, 0x63, 0xF4, 0x49, 0x52 },
+ { 0x66, 0x17, 0x17, 0x8E, 0x94, 0x1F, 0x02, 0x0D,
+ 0x35, 0x1E, 0x2F, 0x25, 0x4E, 0x8F, 0xD3, 0x2C,
+ 0x60, 0x24, 0x20, 0xFE, 0xB0, 0xB8, 0xFB, 0x9A,
+ 0xDC, 0xCE, 0xBB, 0x82, 0x46, 0x1E, 0x99, 0xC5,
+ 0xA6, 0x78, 0xCC, 0x31, 0xE7, 0x99, 0x17, 0x6D,
+ 0x38, 0x60, 0xE6, 0x11, 0x0C, 0x46, 0x52, 0x3E },
+
+ /*
+ * HMAC-SHA-512 test vectors
+ */
+ { 0x87, 0xAA, 0x7C, 0xDE, 0xA5, 0xEF, 0x61, 0x9D,
+ 0x4F, 0xF0, 0xB4, 0x24, 0x1A, 0x1D, 0x6C, 0xB0,
+ 0x23, 0x79, 0xF4, 0xE2, 0xCE, 0x4E, 0xC2, 0x78,
+ 0x7A, 0xD0, 0xB3, 0x05, 0x45, 0xE1, 0x7C, 0xDE,
+ 0xDA, 0xA8, 0x33, 0xB7, 0xD6, 0xB8, 0xA7, 0x02,
+ 0x03, 0x8B, 0x27, 0x4E, 0xAE, 0xA3, 0xF4, 0xE4,
+ 0xBE, 0x9D, 0x91, 0x4E, 0xEB, 0x61, 0xF1, 0x70,
+ 0x2E, 0x69, 0x6C, 0x20, 0x3A, 0x12, 0x68, 0x54 },
+ { 0x16, 0x4B, 0x7A, 0x7B, 0xFC, 0xF8, 0x19, 0xE2,
+ 0xE3, 0x95, 0xFB, 0xE7, 0x3B, 0x56, 0xE0, 0xA3,
+ 0x87, 0xBD, 0x64, 0x22, 0x2E, 0x83, 0x1F, 0xD6,
+ 0x10, 0x27, 0x0C, 0xD7, 0xEA, 0x25, 0x05, 0x54,
+ 0x97, 0x58, 0xBF, 0x75, 0xC0, 0x5A, 0x99, 0x4A,
+ 0x6D, 0x03, 0x4F, 0x65, 0xF8, 0xF0, 0xE6, 0xFD,
+ 0xCA, 0xEA, 0xB1, 0xA3, 0x4D, 0x4A, 0x6B, 0x4B,
+ 0x63, 0x6E, 0x07, 0x0A, 0x38, 0xBC, 0xE7, 0x37 },
+ { 0xFA, 0x73, 0xB0, 0x08, 0x9D, 0x56, 0xA2, 0x84,
+ 0xEF, 0xB0, 0xF0, 0x75, 0x6C, 0x89, 0x0B, 0xE9,
+ 0xB1, 0xB5, 0xDB, 0xDD, 0x8E, 0xE8, 0x1A, 0x36,
+ 0x55, 0xF8, 0x3E, 0x33, 0xB2, 0x27, 0x9D, 0x39,
+ 0xBF, 0x3E, 0x84, 0x82, 0x79, 0xA7, 0x22, 0xC8,
+ 0x06, 0xB4, 0x85, 0xA4, 0x7E, 0x67, 0xC8, 0x07,
+ 0xB9, 0x46, 0xA3, 0x37, 0xBE, 0xE8, 0x94, 0x26,
+ 0x74, 0x27, 0x88, 0x59, 0xE1, 0x32, 0x92, 0xFB },
+ { 0xB0, 0xBA, 0x46, 0x56, 0x37, 0x45, 0x8C, 0x69,
+ 0x90, 0xE5, 0xA8, 0xC5, 0xF6, 0x1D, 0x4A, 0xF7,
+ 0xE5, 0x76, 0xD9, 0x7F, 0xF9, 0x4B, 0x87, 0x2D,
+ 0xE7, 0x6F, 0x80, 0x50, 0x36, 0x1E, 0xE3, 0xDB,
+ 0xA9, 0x1C, 0xA5, 0xC1, 0x1A, 0xA2, 0x5E, 0xB4,
+ 0xD6, 0x79, 0x27, 0x5C, 0xC5, 0x78, 0x80, 0x63,
+ 0xA5, 0xF1, 0x97, 0x41, 0x12, 0x0C, 0x4F, 0x2D,
+ 0xE2, 0xAD, 0xEB, 0xEB, 0x10, 0xA2, 0x98, 0xDD },
+ { 0x41, 0x5F, 0xAD, 0x62, 0x71, 0x58, 0x0A, 0x53,
+ 0x1D, 0x41, 0x79, 0xBC, 0x89, 0x1D, 0x87, 0xA6 },
+ { 0x80, 0xB2, 0x42, 0x63, 0xC7, 0xC1, 0xA3, 0xEB,
+ 0xB7, 0x14, 0x93, 0xC1, 0xDD, 0x7B, 0xE8, 0xB4,
+ 0x9B, 0x46, 0xD1, 0xF4, 0x1B, 0x4A, 0xEE, 0xC1,
+ 0x12, 0x1B, 0x01, 0x37, 0x83, 0xF8, 0xF3, 0x52,
+ 0x6B, 0x56, 0xD0, 0x37, 0xE0, 0x5F, 0x25, 0x98,
+ 0xBD, 0x0F, 0xD2, 0x21, 0x5D, 0x6A, 0x1E, 0x52,
+ 0x95, 0xE6, 0x4F, 0x73, 0xF6, 0x3F, 0x0A, 0xEC,
+ 0x8B, 0x91, 0x5A, 0x98, 0x5D, 0x78, 0x65, 0x98 },
+ { 0xE3, 0x7B, 0x6A, 0x77, 0x5D, 0xC8, 0x7D, 0xBA,
+ 0xA4, 0xDF, 0xA9, 0xF9, 0x6E, 0x5E, 0x3F, 0xFD,
+ 0xDE, 0xBD, 0x71, 0xF8, 0x86, 0x72, 0x89, 0x86,
+ 0x5D, 0xF5, 0xA3, 0x2D, 0x20, 0xCD, 0xC9, 0x44,
+ 0xB6, 0x02, 0x2C, 0xAC, 0x3C, 0x49, 0x82, 0xB1,
+ 0x0D, 0x5E, 0xEB, 0x55, 0xC3, 0xE4, 0xDE, 0x15,
+ 0x13, 0x46, 0x76, 0xFB, 0x6D, 0xE0, 0x44, 0x60,
+ 0x65, 0xC9, 0x74, 0x40, 0xFA, 0x8C, 0x6A, 0x58 }
+};
+
+/*
+ * Checkup routine
+ */
+int sha4_self_test( int verbose )
+{
+ int i, j, k, buflen;
+ unsigned char buf[1024];
+ unsigned char sha4sum[64];
+ sha4_context ctx;
+
+ for( i = 0; i < 6; i++ )
+ {
+ j = i % 3;
+ k = i < 3;
+
+ if( verbose != 0 )
+ printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+ sha4_starts( &ctx, k );
+
+ if( j == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ sha4_update( &ctx, buf, buflen );
+ }
+ else
+ sha4_update( &ctx, sha4_test_buf[j],
+ sha4_test_buflen[j] );
+
+ sha4_finish( &ctx, sha4sum );
+
+ if( memcmp( sha4sum, sha4_test_sum[i], 64 - k * 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ for( i = 0; i < 14; i++ )
+ {
+ j = i % 7;
+ k = i < 7;
+
+ if( verbose != 0 )
+ printf( " HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+ if( j == 5 || j == 6 )
+ {
+ memset( buf, '\xAA', buflen = 131 );
+ sha4_hmac_starts( &ctx, buf, buflen, k );
+ }
+ else
+ sha4_hmac_starts( &ctx, sha4_hmac_test_key[j],
+ sha4_hmac_test_keylen[j], k );
+
+ sha4_hmac_update( &ctx, sha4_hmac_test_buf[j],
+ sha4_hmac_test_buflen[j] );
+
+ sha4_hmac_finish( &ctx, sha4sum );
+
+ buflen = ( j == 4 ) ? 16 : 64 - k * 16;
+
+ if( memcmp( sha4sum, sha4_hmac_test_sum[i], buflen ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/ssl_cli.c b/polarssl/src/library/ssl_cli.c
new file mode 100644
index 0000000..99120d5
--- /dev/null
+++ b/polarssl/src/library/ssl_cli.c
@@ -0,0 +1,1130 @@
+/*
+ * SSLv3/TLSv1 client-side functions
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SSL_CLI_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#if defined(POLARSSL_PKCS11_C)
+#include "polarssl/pkcs11.h"
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#if defined(POLARSSL_SHA4_C)
+#include "polarssl/sha4.h"
+#endif
+
+static int ssl_write_client_hello( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n, ext_len = 0;
+ unsigned char *buf;
+ unsigned char *p;
+ time_t t;
+ unsigned char sig_alg_list[20];
+ size_t sig_alg_len = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
+
+ ssl->major_ver = SSL_MAJOR_VERSION_3;
+ ssl->minor_ver = SSL_MINOR_VERSION_0;
+
+ if( ssl->max_major_ver == 0 && ssl->max_minor_ver == 0 )
+ {
+ ssl->max_major_ver = SSL_MAJOR_VERSION_3;
+ ssl->max_minor_ver = SSL_MINOR_VERSION_3;
+ }
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 highest version supported
+ * 6 . 9 current UNIX time
+ * 10 . 37 random bytes
+ */
+ buf = ssl->out_msg;
+ p = buf + 4;
+
+ *p++ = (unsigned char) ssl->max_major_ver;
+ *p++ = (unsigned char) ssl->max_minor_ver;
+
+ SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
+ buf[4], buf[5] ) );
+
+ t = time( NULL );
+ *p++ = (unsigned char)( t >> 24 );
+ *p++ = (unsigned char)( t >> 16 );
+ *p++ = (unsigned char)( t >> 8 );
+ *p++ = (unsigned char)( t );
+
+ SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
+
+ if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
+ return( ret );
+
+ p += 28;
+
+ memcpy( ssl->randbytes, buf + 6, 32 );
+
+ SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 6, 32 );
+
+ /*
+ * 38 . 38 session id length
+ * 39 . 39+n session id
+ * 40+n . 41+n ciphersuitelist length
+ * 42+n . .. ciphersuitelist
+ * .. . .. compression methods length
+ * .. . .. compression methods
+ * .. . .. extensions length
+ * .. . .. extensions
+ */
+ n = ssl->session->length;
+
+ if( n < 16 || n > 32 || ssl->resume == 0 ||
+ ( ssl->timeout != 0 && t - ssl->session->start > ssl->timeout ) )
+ n = 0;
+
+ *p++ = (unsigned char) n;
+
+ for( i = 0; i < n; i++ )
+ *p++ = ssl->session->id[i];
+
+ SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
+ SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n );
+
+ for( n = 0; ssl->ciphersuites[n] != 0; n++ );
+ *p++ = (unsigned char)( n >> 7 );
+ *p++ = (unsigned char)( n << 1 );
+
+ SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) );
+
+ for( i = 0; i < n; i++ )
+ {
+ SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d",
+ ssl->ciphersuites[i] ) );
+
+ *p++ = (unsigned char)( ssl->ciphersuites[i] >> 8 );
+ *p++ = (unsigned char)( ssl->ciphersuites[i] );
+ }
+
+ SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
+ SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", 0 ) );
+
+ *p++ = 1;
+ *p++ = SSL_COMPRESS_NULL;
+
+ if ( ssl->hostname != NULL )
+ {
+ SSL_DEBUG_MSG( 3, ( "client hello, prepping for server name extension: %s",
+ ssl->hostname ) );
+
+ ext_len += ssl->hostname_len + 9;
+ }
+
+ /*
+ * Prepare signature_algorithms extension (TLS 1.2)
+ */
+ if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 )
+ {
+#if defined(POLARSSL_SHA4_C)
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA512;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA384;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA256;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA224;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ sig_alg_list[sig_alg_len++] = SSL_HASH_SHA1;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+#if defined(POLARSSL_MD5_C)
+ sig_alg_list[sig_alg_len++] = SSL_HASH_MD5;
+ sig_alg_list[sig_alg_len++] = SSL_SIG_RSA;
+#endif
+ ext_len = 6 + sig_alg_len;
+ }
+
+ SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
+ ext_len ) );
+
+ *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ext_len ) & 0xFF );
+
+ if ( ssl->hostname != NULL )
+ {
+ /*
+ * struct {
+ * NameType name_type;
+ * select (name_type) {
+ * case host_name: HostName;
+ * } name;
+ * } ServerName;
+ *
+ * enum {
+ * host_name(0), (255)
+ * } NameType;
+ *
+ * opaque HostName<1..2^16-1>;
+ *
+ * struct {
+ * ServerName server_name_list<1..2^16-1>
+ * } ServerNameList;
+ */
+ SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s",
+ ssl->hostname ) );
+
+ *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME ) & 0xFF );
+
+ *p++ = (unsigned char)( ( (ssl->hostname_len + 5) >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( (ssl->hostname_len + 5) ) & 0xFF );
+
+ *p++ = (unsigned char)( ( (ssl->hostname_len + 3) >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( (ssl->hostname_len + 3) ) & 0xFF );
+
+ *p++ = (unsigned char)( ( TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->hostname_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->hostname_len ) & 0xFF );
+
+ memcpy( p, ssl->hostname, ssl->hostname_len );
+
+ p += ssl->hostname_len;
+ }
+
+ if( ssl->max_minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ /*
+ * enum {
+ * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+ * sha512(6), (255)
+ * } HashAlgorithm;
+ *
+ * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+ * SignatureAlgorithm;
+ *
+ * struct {
+ * HashAlgorithm hash;
+ * SignatureAlgorithm signature;
+ * } SignatureAndHashAlgorithm;
+ *
+ * SignatureAndHashAlgorithm
+ * supported_signature_algorithms<2..2^16-2>;
+ */
+ SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) );
+
+ *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( TLS_EXT_SIG_ALG ) & 0xFF );
+
+ *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF );
+
+ *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF );
+
+ memcpy( p, sig_alg_list, sig_alg_len );
+
+ p += sig_alg_len;
+ }
+
+ ssl->out_msglen = p - buf;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CLIENT_HELLO;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_server_hello( ssl_context *ssl )
+{
+#if defined(POLARSSL_DEBUG_C)
+ time_t t;
+#endif
+ int ret, i;
+ size_t n;
+ int ext_len;
+ unsigned char *buf;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 protocol version
+ * 6 . 9 UNIX time()
+ * 10 . 37 random bytes
+ */
+ buf = ssl->in_msg;
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
+ buf[4], buf[5] ) );
+
+ if( ssl->in_hslen < 42 ||
+ buf[0] != SSL_HS_SERVER_HELLO ||
+ buf[4] != SSL_MAJOR_VERSION_3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ if( buf[5] > ssl->max_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ ssl->minor_ver = buf[5];
+
+#if defined(POLARSSL_DEBUG_C)
+ t = ( (time_t) buf[6] << 24 )
+ | ( (time_t) buf[7] << 16 )
+ | ( (time_t) buf[8] << 8 )
+ | ( (time_t) buf[9] );
+#endif
+
+ memcpy( ssl->randbytes + 32, buf + 6, 32 );
+
+ n = buf[38];
+
+ SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+ SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
+
+ /*
+ * 38 . 38 session id length
+ * 39 . 38+n session id
+ * 39+n . 40+n chosen ciphersuite
+ * 41+n . 41+n chosen compression alg.
+ * 42+n . 43+n extensions length
+ * 44+n . 44+n+m extensions
+ */
+ if( n > 32 || ssl->in_hslen > 42 + n )
+ {
+ ext_len = ( ( buf[42 + n] << 8 )
+ | ( buf[43 + n] ) ) + 2;
+ }
+ else
+ {
+ ext_len = 0;
+ }
+
+ if( n > 32 || ssl->in_hslen != 42 + n + ext_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ i = ( buf[39 + n] << 8 ) | buf[40 + n];
+
+ /*
+ * Initialize update checksum functions
+ */
+ ssl_kickstart_checksum( ssl, i, buf, ssl->in_hslen );
+
+ SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+ SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
+
+ /*
+ * Check if the session can be resumed
+ */
+ if( ssl->resume == 0 || n == 0 ||
+ ssl->session->ciphersuite != i ||
+ ssl->session->length != n ||
+ memcmp( ssl->session->id, buf + 39, n ) != 0 )
+ {
+ ssl->state++;
+ ssl->resume = 0;
+ ssl->session->start = time( NULL );
+ ssl->session->ciphersuite = i;
+ ssl->session->length = n;
+ memcpy( ssl->session->id, buf + 39, n );
+ }
+ else
+ {
+ ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+ if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+ return( ret );
+ }
+ }
+
+ SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
+ ssl->resume ? "a" : "no" ) );
+
+ SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d", i ) );
+ SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[41 + n] ) );
+
+ i = 0;
+ while( 1 )
+ {
+ if( ssl->ciphersuites[i] == 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ if( ssl->ciphersuites[i++] == ssl->session->ciphersuite )
+ break;
+ }
+
+ if( buf[41 + n] != SSL_COMPRESS_NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ /* TODO: Process extensions */
+
+ SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_server_key_exchange( ssl_context *ssl )
+{
+#if defined(POLARSSL_DHM_C)
+ int ret;
+ size_t n;
+ unsigned char *p, *end;
+ unsigned char hash[64];
+ md5_context md5;
+ sha1_context sha1;
+ int hash_id = SIG_RSA_RAW;
+ unsigned int hashlen = 0;
+#endif
+
+ SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
+
+ if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+#if !defined(POLARSSL_DHM_C)
+ SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ if( ssl->in_msg[0] != SSL_HS_SERVER_KEY_EXCHANGE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ SSL_DEBUG_BUF( 3, "server key exchange", ssl->in_msg + 4, ssl->in_hslen - 4 );
+
+ /*
+ * Ephemeral DH parameters:
+ *
+ * struct {
+ * opaque dh_p<1..2^16-1>;
+ * opaque dh_g<1..2^16-1>;
+ * opaque dh_Ys<1..2^16-1>;
+ * } ServerDHParams;
+ */
+ p = ssl->in_msg + 4;
+ end = ssl->in_msg + ssl->in_hslen;
+
+ if( ( ret = dhm_read_params( &ssl->dhm_ctx, &p, end ) ) != 0 )
+ {
+ SSL_DEBUG_MSG( 2, ( "DHM Read Params returned -0x%x", -ret ) );
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ if( p[1] != SSL_SIG_RSA )
+ {
+ SSL_DEBUG_MSG( 2, ( "Server used unsupported SignatureAlgorithm %d", p[1] ) );
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ switch( p[0] )
+ {
+#if defined(POLARSSL_MD5_C)
+ case SSL_HASH_MD5:
+ hash_id = SIG_RSA_MD5;
+ break;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ case SSL_HASH_SHA1:
+ hash_id = SIG_RSA_SHA1;
+ break;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ case SSL_HASH_SHA224:
+ hash_id = SIG_RSA_SHA224;
+ break;
+ case SSL_HASH_SHA256:
+ hash_id = SIG_RSA_SHA256;
+ break;
+#endif
+#if defined(POLARSSL_SHA4_C)
+ case SSL_HASH_SHA384:
+ hash_id = SIG_RSA_SHA384;
+ break;
+ case SSL_HASH_SHA512:
+ hash_id = SIG_RSA_SHA512;
+ break;
+#endif
+ default:
+ SSL_DEBUG_MSG( 2, ( "Server used unsupported HashAlgorithm %d", p[0] ) );
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", p[1] ) );
+ SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", p[0] ) );
+ p += 2;
+ }
+
+ n = ( p[0] << 8 ) | p[1];
+ p += 2;
+
+ if( end != p + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ if( (unsigned int)( end - p ) != ssl->peer_cert->rsa.len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ if( ssl->dhm_ctx.len < 64 || ssl->dhm_ctx.len > 512 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P );
+ SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G );
+ SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+ {
+ /*
+ * digitally-signed struct {
+ * opaque md5_hash[16];
+ * opaque sha_hash[20];
+ * };
+ *
+ * md5_hash
+ * MD5(ClientHello.random + ServerHello.random
+ * + ServerParams);
+ * sha_hash
+ * SHA(ClientHello.random + ServerHello.random
+ * + ServerParams);
+ */
+ n = ssl->in_hslen - ( end - p ) - 6;
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->randbytes, 64 );
+ md5_update( &md5, ssl->in_msg + 4, n );
+ md5_finish( &md5, hash );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->randbytes, 64 );
+ sha1_update( &sha1, ssl->in_msg + 4, n );
+ sha1_finish( &sha1, hash + 16 );
+
+ hash_id = SIG_RSA_RAW;
+ hashlen = 36;
+ }
+ else
+ {
+ sha2_context sha2;
+ sha4_context sha4;
+
+ n = ssl->in_hslen - ( end - p ) - 8;
+
+ /*
+ * digitally-signed struct {
+ * opaque client_random[32];
+ * opaque server_random[32];
+ * ServerDHParams params;
+ * };
+ */
+ switch( hash_id )
+ {
+#if defined(POLARSSL_MD5_C)
+ case SIG_RSA_MD5:
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->randbytes, 64 );
+ md5_update( &md5, ssl->in_msg + 4, n );
+ md5_finish( &md5, hash );
+ hashlen = 16;
+ break;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ case SIG_RSA_SHA1:
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->randbytes, 64 );
+ sha1_update( &sha1, ssl->in_msg + 4, n );
+ sha1_finish( &sha1, hash );
+ hashlen = 20;
+ break;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ case SIG_RSA_SHA224:
+ sha2_starts( &sha2, 1 );
+ sha2_update( &sha2, ssl->randbytes, 64 );
+ sha2_update( &sha2, ssl->in_msg + 4, n );
+ sha2_finish( &sha2, hash );
+ hashlen = 28;
+ break;
+ case SIG_RSA_SHA256:
+ sha2_starts( &sha2, 0 );
+ sha2_update( &sha2, ssl->randbytes, 64 );
+ sha2_update( &sha2, ssl->in_msg + 4, n );
+ sha2_finish( &sha2, hash );
+ hashlen = 32;
+ break;
+#endif
+#if defined(POLARSSL_SHA4_C)
+ case SIG_RSA_SHA384:
+ sha4_starts( &sha4, 1 );
+ sha4_update( &sha4, ssl->randbytes, 64 );
+ sha4_update( &sha4, ssl->in_msg + 4, n );
+ sha4_finish( &sha4, hash );
+ hashlen = 48;
+ break;
+ case SIG_RSA_SHA512:
+ sha4_starts( &sha4, 0 );
+ sha4_update( &sha4, ssl->randbytes, 64 );
+ sha4_update( &sha4, ssl->in_msg + 4, n );
+ sha4_finish( &sha4, hash );
+ hashlen = 64;
+ break;
+#endif
+ }
+ }
+
+ SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
+
+ if( ( ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
+ hash_id, hashlen, hash, p ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
+ return( ret );
+ }
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) );
+
+ return( 0 );
+#endif
+}
+
+static int ssl_parse_certificate_request( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 SSL version
+ * 6 . 6 cert type count
+ * 7 .. n-1 cert types
+ * n .. n+1 length of all DNs
+ * n+2 .. n+3 length of DN 1
+ * n+4 .. ... Distinguished Name #1
+ * ... .. ... length of DN 2, etc.
+ */
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ ssl->client_auth = 0;
+ ssl->state++;
+
+ if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST )
+ ssl->client_auth++;
+
+ SSL_DEBUG_MSG( 3, ( "got %s certificate request",
+ ssl->client_auth ? "a" : "no" ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_server_hello_done( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
+
+ if( ssl->client_auth != 0 )
+ {
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+ }
+
+ if( ssl->in_hslen != 4 ||
+ ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
+ }
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) );
+
+ return( 0 );
+}
+
+static int ssl_write_client_key_exchange( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n;
+
+ SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
+
+ if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+#if !defined(POLARSSL_DHM_C)
+ SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+ /*
+ * DHM key exchange -- send G^X mod P
+ */
+ n = ssl->dhm_ctx.len;
+
+ ssl->out_msg[4] = (unsigned char)( n >> 8 );
+ ssl->out_msg[5] = (unsigned char)( n );
+ i = 6;
+
+ ret = dhm_make_public( &ssl->dhm_ctx, 256,
+ &ssl->out_msg[i], n,
+ ssl->f_rng, ssl->p_rng );
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_make_public", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X );
+ SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
+
+ ssl->pmslen = ssl->dhm_ctx.len;
+
+ if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
+ ssl->premaster,
+ &ssl->pmslen ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K );
+#endif
+ }
+ else
+ {
+ /*
+ * RSA key exchange -- send rsa_public(pkcs1 v1.5(premaster))
+ */
+ ssl->premaster[0] = (unsigned char) ssl->max_major_ver;
+ ssl->premaster[1] = (unsigned char) ssl->max_minor_ver;
+ ssl->pmslen = 48;
+
+ ret = ssl->f_rng( ssl->p_rng, ssl->premaster + 2, ssl->pmslen - 2 );
+ if( ret != 0 )
+ return( ret );
+
+ i = 4;
+ n = ssl->peer_cert->rsa.len;
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
+ {
+ i += 2;
+ ssl->out_msg[4] = (unsigned char)( n >> 8 );
+ ssl->out_msg[5] = (unsigned char)( n );
+ }
+
+ ret = rsa_pkcs1_encrypt( &ssl->peer_cert->rsa,
+ ssl->f_rng, ssl->p_rng,
+ RSA_PUBLIC,
+ ssl->pmslen, ssl->premaster,
+ ssl->out_msg + i );
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, "rsa_pkcs1_encrypt", ret );
+ return( ret );
+ }
+ }
+
+ if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+ return( ret );
+ }
+
+ ssl->out_msglen = i + n;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CLIENT_KEY_EXCHANGE;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) );
+
+ return( 0 );
+}
+
+static int ssl_write_certificate_verify( ssl_context *ssl )
+{
+ int ret = 0;
+ size_t n = 0, offset = 0;
+ unsigned char hash[48];
+ int hash_id = SIG_RSA_RAW;
+ unsigned int hashlen = 36;
+
+ SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
+
+ if( ssl->client_auth == 0 || ssl->own_cert == NULL )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ // TODO TLS1.2 Should be based on allowed signature algorithm received in
+ // Certificate Request according to RFC 5246. But OpenSSL only allows
+ // SHA256 and SHA384. Find out why OpenSSL does this.
+ //
+ if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+ hash_id = SIG_RSA_SHA384;
+ hashlen = 48;
+ }
+ else
+ {
+ hash_id = SIG_RSA_SHA256;
+ hashlen = 32;
+ }
+ }
+
+ if( ssl->rsa_key == NULL )
+ {
+#if defined(POLARSSL_PKCS11_C)
+ if( ssl->pkcs11_key == NULL )
+ {
+#endif /* defined(POLARSSL_PKCS11_C) */
+ SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+ return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+#if defined(POLARSSL_PKCS11_C)
+ }
+#endif /* defined(POLARSSL_PKCS11_C) */
+ }
+
+ /*
+ * Make an RSA signature of the handshake digests
+ */
+ ssl->calc_verify( ssl, hash );
+
+ if ( ssl->rsa_key )
+ n = ssl->rsa_key->len;
+#if defined(POLARSSL_PKCS11_C)
+ else
+ n = ssl->pkcs11_key->len;
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ // TODO TLS1.2 Should be based on allowed signature algorithm received in
+ // Certificate Request according to RFC 5246. But OpenSSL only allows
+ // SHA256 and SHA384. Find out why OpenSSL does this.
+ //
+ if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+ ssl->out_msg[4] = SSL_HASH_SHA384;
+ ssl->out_msg[5] = SSL_SIG_RSA;
+ }
+ else
+ {
+ ssl->out_msg[4] = SSL_HASH_SHA256;
+ ssl->out_msg[5] = SSL_SIG_RSA;
+ }
+
+ offset = 2;
+ }
+
+ ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
+ ssl->out_msg[5 + offset] = (unsigned char)( n );
+
+ if( ssl->rsa_key )
+ {
+ ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
+ RSA_PRIVATE, hash_id,
+ hashlen, hash, ssl->out_msg + 6 + offset );
+ } else {
+#if defined(POLARSSL_PKCS11_C)
+ ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE, hash_id,
+ hashlen, hash, ssl->out_msg + 6 + offset );
+#endif /* defined(POLARSSL_PKCS11_C) */
+ }
+
+ if (ret != 0)
+ {
+ SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
+ return( ret );
+ }
+
+ ssl->out_msglen = 6 + n + offset;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CERTIFICATE_VERIFY;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) );
+
+ return( 0 );
+}
+
+/*
+ * SSL handshake -- client side
+ */
+int ssl_handshake_client( ssl_context *ssl )
+{
+ int ret = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> handshake client" ) );
+
+ while( ssl->state != SSL_HANDSHAKE_OVER )
+ {
+ SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
+
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ break;
+
+ switch( ssl->state )
+ {
+ case SSL_HELLO_REQUEST:
+ ssl->state = SSL_CLIENT_HELLO;
+ break;
+
+ /*
+ * ==> ClientHello
+ */
+ case SSL_CLIENT_HELLO:
+ ret = ssl_write_client_hello( ssl );
+ break;
+
+ /*
+ * <== ServerHello
+ * Certificate
+ * ( ServerKeyExchange )
+ * ( CertificateRequest )
+ * ServerHelloDone
+ */
+ case SSL_SERVER_HELLO:
+ ret = ssl_parse_server_hello( ssl );
+ break;
+
+ case SSL_SERVER_CERTIFICATE:
+ ret = ssl_parse_certificate( ssl );
+ break;
+
+ case SSL_SERVER_KEY_EXCHANGE:
+ ret = ssl_parse_server_key_exchange( ssl );
+ break;
+
+ case SSL_CERTIFICATE_REQUEST:
+ ret = ssl_parse_certificate_request( ssl );
+ break;
+
+ case SSL_SERVER_HELLO_DONE:
+ ret = ssl_parse_server_hello_done( ssl );
+ break;
+
+ /*
+ * ==> ( Certificate/Alert )
+ * ClientKeyExchange
+ * ( CertificateVerify )
+ * ChangeCipherSpec
+ * Finished
+ */
+ case SSL_CLIENT_CERTIFICATE:
+ ret = ssl_write_certificate( ssl );
+ break;
+
+ case SSL_CLIENT_KEY_EXCHANGE:
+ ret = ssl_write_client_key_exchange( ssl );
+ break;
+
+ case SSL_CERTIFICATE_VERIFY:
+ ret = ssl_write_certificate_verify( ssl );
+ break;
+
+ case SSL_CLIENT_CHANGE_CIPHER_SPEC:
+ ret = ssl_write_change_cipher_spec( ssl );
+ break;
+
+ case SSL_CLIENT_FINISHED:
+ ret = ssl_write_finished( ssl );
+ break;
+
+ /*
+ * <== ChangeCipherSpec
+ * Finished
+ */
+ case SSL_SERVER_CHANGE_CIPHER_SPEC:
+ ret = ssl_parse_change_cipher_spec( ssl );
+ break;
+
+ case SSL_SERVER_FINISHED:
+ ret = ssl_parse_finished( ssl );
+ break;
+
+ case SSL_FLUSH_BUFFERS:
+ SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+ ssl->state = SSL_HANDSHAKE_OVER;
+ break;
+
+ default:
+ SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ if( ret != 0 )
+ break;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= handshake client" ) );
+
+ return( ret );
+}
+
+#endif
diff --git a/polarssl/src/library/ssl_srv.c b/polarssl/src/library/ssl_srv.c
new file mode 100644
index 0000000..ecf1536
--- /dev/null
+++ b/polarssl/src/library/ssl_srv.c
@@ -0,0 +1,1080 @@
+/*
+ * SSLv3/TLSv1 server-side functions
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SSL_SRV_C)
+
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+
+#if defined(POLARSSL_PKCS11_C)
+#include "polarssl/pkcs11.h"
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+static int ssl_parse_client_hello( ssl_context *ssl )
+{
+ int ret;
+ unsigned int i, j;
+ size_t n;
+ unsigned int ciph_len, sess_len;
+ unsigned int chal_len, comp_len;
+ unsigned char *buf, *p;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
+
+ if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ buf = ssl->in_hdr;
+
+ if( ( buf[0] & 0x80 ) != 0 )
+ {
+ SSL_DEBUG_BUF( 4, "record header", buf, 5 );
+
+ SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
+ buf[2] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
+ ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
+ buf[3], buf[4] ) );
+
+ /*
+ * SSLv2 Client Hello
+ *
+ * Record layer:
+ * 0 . 1 message length
+ *
+ * SSL layer:
+ * 2 . 2 message type
+ * 3 . 4 protocol version
+ */
+ if( buf[2] != SSL_HS_CLIENT_HELLO ||
+ buf[3] != SSL_MAJOR_VERSION_3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
+
+ if( n < 17 || n > 512 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->max_major_ver = buf[3];
+ ssl->max_minor_ver = buf[4];
+
+ ssl->major_ver = SSL_MAJOR_VERSION_3;
+ ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_3 )
+ ? buf[4] : SSL_MINOR_VERSION_3;
+
+ if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ ssl->update_checksum( ssl, buf + 2, n );
+
+ buf = ssl->in_msg;
+ n = ssl->in_left - 5;
+
+ /*
+ * 0 . 1 ciphersuitelist length
+ * 2 . 3 session id length
+ * 4 . 5 challenge length
+ * 6 . .. ciphersuitelist
+ * .. . .. session id
+ * .. . .. challenge
+ */
+ SSL_DEBUG_BUF( 4, "record contents", buf, n );
+
+ ciph_len = ( buf[0] << 8 ) | buf[1];
+ sess_len = ( buf[2] << 8 ) | buf[3];
+ chal_len = ( buf[4] << 8 ) | buf[5];
+
+ SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
+ ciph_len, sess_len, chal_len ) );
+
+ /*
+ * Make sure each parameter length is valid
+ */
+ if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( sess_len > 32 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( chal_len < 8 || chal_len > 32 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( n != 6 + ciph_len + sess_len + chal_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
+ buf + 6, ciph_len );
+ SSL_DEBUG_BUF( 3, "client hello, session id",
+ buf + 6 + ciph_len, sess_len );
+ SSL_DEBUG_BUF( 3, "client hello, challenge",
+ buf + 6 + ciph_len + sess_len, chal_len );
+
+ p = buf + 6 + ciph_len;
+ ssl->session->length = sess_len;
+ memset( ssl->session->id, 0, sizeof( ssl->session->id ) );
+ memcpy( ssl->session->id, p, ssl->session->length );
+
+ p += sess_len;
+ memset( ssl->randbytes, 0, 64 );
+ memcpy( ssl->randbytes + 32 - chal_len, p, chal_len );
+
+ for( i = 0; ssl->ciphersuites[i] != 0; i++ )
+ {
+ for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
+ {
+ if( p[0] == 0 &&
+ p[1] == 0 &&
+ p[2] == ssl->ciphersuites[i] )
+ goto have_ciphersuite;
+ }
+ }
+ }
+ else
+ {
+ SSL_DEBUG_BUF( 4, "record header", buf, 5 );
+
+ SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",
+ buf[0] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d",
+ ( buf[3] << 8 ) | buf[4] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v3, protocol ver: [%d:%d]",
+ buf[1], buf[2] ) );
+
+ /*
+ * SSLv3 Client Hello
+ *
+ * Record layer:
+ * 0 . 0 message type
+ * 1 . 2 protocol version
+ * 3 . 4 message length
+ */
+ if( buf[0] != SSL_MSG_HANDSHAKE ||
+ buf[1] != SSL_MAJOR_VERSION_3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ n = ( buf[3] << 8 ) | buf[4];
+
+ if( n < 45 || n > 512 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ if( ( ret = ssl_fetch_input( ssl, 5 + n ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ buf = ssl->in_msg;
+ n = ssl->in_left - 5;
+
+ ssl->update_checksum( ssl, buf, n );
+
+ /*
+ * SSL layer:
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 protocol version
+ * 6 . 9 UNIX time()
+ * 10 . 37 random bytes
+ * 38 . 38 session id length
+ * 39 . 38+x session id
+ * 39+x . 40+x ciphersuitelist length
+ * 41+x . .. ciphersuitelist
+ * .. . .. compression alg.
+ * .. . .. extensions
+ */
+ SSL_DEBUG_BUF( 4, "record contents", buf, n );
+
+ SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d",
+ buf[0] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
+ ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
+ SSL_DEBUG_MSG( 3, ( "client hello v3, max. version: [%d:%d]",
+ buf[4], buf[5] ) );
+
+ /*
+ * Check the handshake type and protocol version
+ */
+ if( buf[0] != SSL_HS_CLIENT_HELLO ||
+ buf[4] != SSL_MAJOR_VERSION_3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->major_ver = SSL_MAJOR_VERSION_3;
+ ssl->minor_ver = ( buf[5] <= SSL_MINOR_VERSION_3 )
+ ? buf[5] : SSL_MINOR_VERSION_3;
+
+ ssl->max_major_ver = buf[4];
+ ssl->max_minor_ver = buf[5];
+
+ memcpy( ssl->randbytes, buf + 6, 32 );
+
+ /*
+ * Check the handshake message length
+ */
+ if( buf[1] != 0 || n != (unsigned int) 4 + ( ( buf[2] << 8 ) | buf[3] ) )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ /*
+ * Check the session length
+ */
+ sess_len = buf[38];
+
+ if( sess_len > 32 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->session->length = sess_len;
+ memset( ssl->session->id, 0, sizeof( ssl->session->id ) );
+ memcpy( ssl->session->id, buf + 39 , ssl->session->length );
+
+ /*
+ * Check the ciphersuitelist length
+ */
+ ciph_len = ( buf[39 + sess_len] << 8 )
+ | ( buf[40 + sess_len] );
+
+ if( ciph_len < 2 || ciph_len > 256 || ( ciph_len % 2 ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ /*
+ * Check the compression algorithms length
+ */
+ comp_len = buf[41 + sess_len + ciph_len];
+
+ if( comp_len < 1 || comp_len > 16 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ SSL_DEBUG_BUF( 3, "client hello, random bytes",
+ buf + 6, 32 );
+ SSL_DEBUG_BUF( 3, "client hello, session id",
+ buf + 38, sess_len );
+ SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
+ buf + 41 + sess_len, ciph_len );
+ SSL_DEBUG_BUF( 3, "client hello, compression",
+ buf + 42 + sess_len + ciph_len, comp_len );
+
+ /*
+ * Search for a matching ciphersuite
+ */
+ for( i = 0; ssl->ciphersuites[i] != 0; i++ )
+ {
+ for( j = 0, p = buf + 41 + sess_len; j < ciph_len;
+ j += 2, p += 2 )
+ {
+ if( p[0] == 0 && p[1] == ssl->ciphersuites[i] )
+ goto have_ciphersuite;
+ }
+ }
+ }
+
+ SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
+
+ return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+
+have_ciphersuite:
+
+ ssl->session->ciphersuite = ssl->ciphersuites[i];
+ ssl_kickstart_checksum( ssl, ssl->session->ciphersuite, buf, n );
+
+ ssl->in_left = 0;
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
+
+ return( 0 );
+}
+
+static int ssl_write_server_hello( ssl_context *ssl )
+{
+ time_t t;
+ int ret, n;
+ unsigned char *buf, *p;
+
+ SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 5 protocol version
+ * 6 . 9 UNIX time()
+ * 10 . 37 random bytes
+ */
+ buf = ssl->out_msg;
+ p = buf + 4;
+
+ *p++ = (unsigned char) ssl->major_ver;
+ *p++ = (unsigned char) ssl->minor_ver;
+
+ SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
+ buf[4], buf[5] ) );
+
+ t = time( NULL );
+ *p++ = (unsigned char)( t >> 24 );
+ *p++ = (unsigned char)( t >> 16 );
+ *p++ = (unsigned char)( t >> 8 );
+ *p++ = (unsigned char)( t );
+
+ SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+
+ if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
+ return( ret );
+
+ p += 28;
+
+ memcpy( ssl->randbytes + 32, buf + 6, 32 );
+
+ SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
+
+ /*
+ * 38 . 38 session id length
+ * 39 . 38+n session id
+ * 39+n . 40+n chosen ciphersuite
+ * 41+n . 41+n chosen compression alg.
+ */
+ ssl->session->length = n = 32;
+ *p++ = (unsigned char) ssl->session->length;
+
+ if( ssl->s_get == NULL ||
+ ssl->s_get( ssl ) != 0 )
+ {
+ /*
+ * Not found, create a new session id
+ */
+ ssl->resume = 0;
+ ssl->state++;
+
+ if( ssl->session == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "No session struct set" ) );
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ if( ( ret = ssl->f_rng( ssl->p_rng, ssl->session->id, n ) ) != 0 )
+ return( ret );
+ }
+ else
+ {
+ /*
+ * Found a matching session, resume it
+ */
+ ssl->resume = 1;
+ ssl->state = SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+ if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+ return( ret );
+ }
+ }
+
+ memcpy( p, ssl->session->id, ssl->session->length );
+ p += ssl->session->length;
+
+ SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+ SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n );
+ SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
+ ssl->resume ? "a" : "no" ) );
+
+ *p++ = (unsigned char)( ssl->session->ciphersuite >> 8 );
+ *p++ = (unsigned char)( ssl->session->ciphersuite );
+ *p++ = SSL_COMPRESS_NULL;
+
+ SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %d",
+ ssl->session->ciphersuite ) );
+ SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", 0 ) );
+
+ ssl->out_msglen = p - buf;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_SERVER_HELLO;
+
+ ret = ssl_write_record( ssl );
+
+ SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
+
+ return( ret );
+}
+
+static int ssl_write_certificate_request( ssl_context *ssl )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf, *p;
+ const x509_cert *crt;
+
+ SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
+
+ ssl->state++;
+
+ if( ssl->authmode == SSL_VERIFY_NONE )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
+ return( 0 );
+ }
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 4 cert type count
+ * 5 .. n-1 cert types
+ * n .. n+1 length of all DNs
+ * n+2 .. n+3 length of DN 1
+ * n+4 .. ... Distinguished Name #1
+ * ... .. ... length of DN 2, etc.
+ */
+ buf = ssl->out_msg;
+ p = buf + 4;
+
+ /*
+ * At the moment, only RSA certificates are supported
+ */
+ *p++ = 1;
+ *p++ = 1;
+
+ p += 2;
+ crt = ssl->ca_chain;
+
+ while( crt != NULL )
+ {
+ if( p - buf > 4096 )
+ break;
+
+ n = crt->subject_raw.len;
+ *p++ = (unsigned char)( n >> 8 );
+ *p++ = (unsigned char)( n );
+ memcpy( p, crt->subject_raw.p, n );
+
+ SSL_DEBUG_BUF( 3, "requested DN", p, n );
+ p += n; crt = crt->next;
+ }
+
+ ssl->out_msglen = n = p - buf;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CERTIFICATE_REQUEST;
+ ssl->out_msg[6] = (unsigned char)( ( n - 8 ) >> 8 );
+ ssl->out_msg[7] = (unsigned char)( ( n - 8 ) );
+
+ ret = ssl_write_record( ssl );
+
+ SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
+
+ return( ret );
+}
+
+static int ssl_write_server_key_exchange( ssl_context *ssl )
+{
+#if defined(POLARSSL_DHM_C)
+ int ret;
+ size_t n, rsa_key_len = 0;
+ unsigned char hash[48];
+ md5_context md5;
+ sha1_context sha1;
+ int hash_id;
+ unsigned int hashlen;
+#endif
+
+ SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
+
+ if( ssl->session->ciphersuite != SSL_EDH_RSA_DES_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_DES_168_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 &&
+ ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+#if !defined(POLARSSL_DHM_C)
+ SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+
+ if( ssl->rsa_key == NULL )
+ {
+#if defined(POLARSSL_PKCS11_C)
+ if( ssl->pkcs11_key == NULL )
+ {
+#endif /* defined(POLARSSL_PKCS11_C) */
+ SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+ return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+#if defined(POLARSSL_PKCS11_C)
+ }
+#endif /* defined(POLARSSL_PKCS11_C) */
+ }
+
+ /*
+ * Ephemeral DH parameters:
+ *
+ * struct {
+ * opaque dh_p<1..2^16-1>;
+ * opaque dh_g<1..2^16-1>;
+ * opaque dh_Ys<1..2^16-1>;
+ * } ServerDHParams;
+ */
+ if( ( ret = dhm_make_params( &ssl->dhm_ctx, 256, ssl->out_msg + 4,
+ &n, ssl->f_rng, ssl->p_rng ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_make_params", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->dhm_ctx.X );
+ SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->dhm_ctx.P );
+ SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->dhm_ctx.G );
+ SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->dhm_ctx.GX );
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
+ {
+ /*
+ * digitally-signed struct {
+ * opaque md5_hash[16];
+ * opaque sha_hash[20];
+ * };
+ *
+ * md5_hash
+ * MD5(ClientHello.random + ServerHello.random
+ * + ServerParams);
+ * sha_hash
+ * SHA(ClientHello.random + ServerHello.random
+ * + ServerParams);
+ */
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->randbytes, 64 );
+ md5_update( &md5, ssl->out_msg + 4, n );
+ md5_finish( &md5, hash );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->randbytes, 64 );
+ sha1_update( &sha1, ssl->out_msg + 4, n );
+ sha1_finish( &sha1, hash + 16 );
+
+ hashlen = 36;
+ hash_id = SIG_RSA_RAW;
+ }
+ else
+ {
+ /*
+ * digitally-signed struct {
+ * opaque client_random[32];
+ * opaque server_random[32];
+ * ServerDHParams params;
+ * };
+ */
+ /* TODO TLS1.2 Get a supported hash algorithm from the
+ * signature_algorithms extension, Otherwise SHA1 + RSA!
+ */
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->randbytes, 64 );
+ sha1_update( &sha1, ssl->out_msg + 4, n );
+ sha1_finish( &sha1, hash );
+
+ hashlen = 20;
+ hash_id = SIG_RSA_SHA1;
+ }
+
+ SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
+
+ if ( ssl->rsa_key )
+ rsa_key_len = ssl->rsa_key->len;
+#if defined(POLARSSL_PKCS11_C)
+ else
+ rsa_key_len = ssl->pkcs11_key->len;
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
+ {
+ // TODO TLS1.2 Base on selection above (SHA1 + RSA is default choice)
+ ssl->out_msg[4 + n] = SSL_HASH_SHA1;
+ ssl->out_msg[5 + n] = SSL_SIG_RSA;
+
+ n += 2;
+ }
+
+ ssl->out_msg[4 + n] = (unsigned char)( rsa_key_len >> 8 );
+ ssl->out_msg[5 + n] = (unsigned char)( rsa_key_len );
+
+ if ( ssl->rsa_key )
+ {
+ ret = rsa_pkcs1_sign( ssl->rsa_key, ssl->f_rng, ssl->p_rng,
+ RSA_PRIVATE,
+ hash_id, hashlen, hash, ssl->out_msg + 6 + n );
+ }
+#if defined(POLARSSL_PKCS11_C)
+ else {
+ ret = pkcs11_sign( ssl->pkcs11_key, RSA_PRIVATE,
+ hash_id, hashlen, hash, ssl->out_msg + 6 + n );
+ }
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, "pkcs1_sign", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_BUF( 3, "my RSA sig", ssl->out_msg + 6 + n, rsa_key_len );
+
+ ssl->out_msglen = 6 + n + rsa_key_len;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_SERVER_KEY_EXCHANGE;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
+
+ return( 0 );
+#endif
+}
+
+static int ssl_write_server_hello_done( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
+
+ ssl->out_msglen = 4;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_SERVER_HELLO_DONE;
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_client_key_exchange( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+
+ if( ssl->in_msg[0] != SSL_HS_CLIENT_KEY_EXCHANGE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+
+ if( ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_DES_168_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+#if !defined(POLARSSL_DHM_C)
+ SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+#else
+ /*
+ * Receive G^Y mod P, premaster = (G^Y)^X mod P
+ */
+ n = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+
+ if( n < 1 || n > ssl->dhm_ctx.len ||
+ n + 6 != ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+
+ if( ( ret = dhm_read_public( &ssl->dhm_ctx,
+ ssl->in_msg + 6, n ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_read_public", ret );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_RP );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->dhm_ctx.GY );
+
+ ssl->pmslen = ssl->dhm_ctx.len;
+
+ if( ( ret = dhm_calc_secret( &ssl->dhm_ctx,
+ ssl->premaster, &ssl->pmslen ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_DHM_CS );
+ }
+
+ SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->dhm_ctx.K );
+#endif
+ }
+ else
+ {
+ if( ssl->rsa_key == NULL )
+ {
+#if defined(POLARSSL_PKCS11_C)
+ if( ssl->pkcs11_key == NULL )
+ {
+#endif
+ SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+ return( POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED );
+#if defined(POLARSSL_PKCS11_C)
+ }
+#endif
+ }
+
+ /*
+ * Decrypt the premaster using own private RSA key
+ */
+ i = 4;
+ if( ssl->rsa_key )
+ n = ssl->rsa_key->len;
+#if defined(POLARSSL_PKCS11_C)
+ else
+ n = ssl->pkcs11_key->len;
+#endif
+ ssl->pmslen = 48;
+
+ if( ssl->minor_ver != SSL_MINOR_VERSION_0 )
+ {
+ i += 2;
+ if( ssl->in_msg[4] != ( ( n >> 8 ) & 0xFF ) ||
+ ssl->in_msg[5] != ( ( n ) & 0xFF ) )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+ }
+
+ if( ssl->in_hslen != i + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
+
+ if( ssl->rsa_key ) {
+ ret = rsa_pkcs1_decrypt( ssl->rsa_key, RSA_PRIVATE, &ssl->pmslen,
+ ssl->in_msg + i, ssl->premaster,
+ sizeof(ssl->premaster) );
+ }
+#if defined(POLARSSL_PKCS11_C)
+ else {
+ ret = pkcs11_decrypt( ssl->pkcs11_key, RSA_PRIVATE, &ssl->pmslen,
+ ssl->in_msg + i, ssl->premaster,
+ sizeof(ssl->premaster) );
+ }
+#endif /* defined(POLARSSL_PKCS11_C) */
+
+ if( ret != 0 || ssl->pmslen != 48 ||
+ ssl->premaster[0] != ssl->max_major_ver ||
+ ssl->premaster[1] != ssl->max_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+
+ /*
+ * Protection against Bleichenbacher's attack:
+ * invalid PKCS#1 v1.5 padding must not cause
+ * the connection to end immediately; instead,
+ * send a bad_record_mac later in the handshake.
+ */
+ ssl->pmslen = 48;
+
+ ret = ssl->f_rng( ssl->p_rng, ssl->premaster, ssl->pmslen );
+ if( ret != 0 )
+ return( ret );
+ }
+ }
+
+ if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_derive_keys", ret );
+ return( ret );
+ }
+
+ if( ssl->s_set != NULL )
+ ssl->s_set( ssl );
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) );
+
+ return( 0 );
+}
+
+static int ssl_parse_certificate_verify( ssl_context *ssl )
+{
+ int ret;
+ size_t n1, n2;
+ unsigned char hash[48];
+
+ SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
+
+ if( ssl->peer_cert == NULL )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ ssl->calc_verify( ssl, hash );
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ ssl->state++;
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+ }
+
+ if( ssl->in_msg[0] != SSL_HS_CERTIFICATE_VERIFY )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+ }
+
+ n1 = ssl->peer_cert->rsa.len;
+ n2 = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+
+ if( n1 + 6 != ssl->in_hslen || n1 != n2 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
+ }
+
+ ret = rsa_pkcs1_verify( &ssl->peer_cert->rsa, RSA_PUBLIC,
+ SIG_RSA_RAW, 36, hash, ssl->in_msg + 6 );
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, "rsa_pkcs1_verify", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
+
+ return( 0 );
+}
+
+/*
+ * SSL handshake -- server side
+ */
+int ssl_handshake_server( ssl_context *ssl )
+{
+ int ret = 0;
+
+ SSL_DEBUG_MSG( 2, ( "=> handshake server" ) );
+
+ while( ssl->state != SSL_HANDSHAKE_OVER )
+ {
+ SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
+
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ break;
+
+ switch( ssl->state )
+ {
+ case SSL_HELLO_REQUEST:
+ ssl->state = SSL_CLIENT_HELLO;
+ break;
+
+ /*
+ * <== ClientHello
+ */
+ case SSL_CLIENT_HELLO:
+ ret = ssl_parse_client_hello( ssl );
+ break;
+
+ /*
+ * ==> ServerHello
+ * Certificate
+ * ( ServerKeyExchange )
+ * ( CertificateRequest )
+ * ServerHelloDone
+ */
+ case SSL_SERVER_HELLO:
+ ret = ssl_write_server_hello( ssl );
+ break;
+
+ case SSL_SERVER_CERTIFICATE:
+ ret = ssl_write_certificate( ssl );
+ break;
+
+ case SSL_SERVER_KEY_EXCHANGE:
+ ret = ssl_write_server_key_exchange( ssl );
+ break;
+
+ case SSL_CERTIFICATE_REQUEST:
+ ret = ssl_write_certificate_request( ssl );
+ break;
+
+ case SSL_SERVER_HELLO_DONE:
+ ret = ssl_write_server_hello_done( ssl );
+ break;
+
+ /*
+ * <== ( Certificate/Alert )
+ * ClientKeyExchange
+ * ( CertificateVerify )
+ * ChangeCipherSpec
+ * Finished
+ */
+ case SSL_CLIENT_CERTIFICATE:
+ ret = ssl_parse_certificate( ssl );
+ break;
+
+ case SSL_CLIENT_KEY_EXCHANGE:
+ ret = ssl_parse_client_key_exchange( ssl );
+ break;
+
+ case SSL_CERTIFICATE_VERIFY:
+ ret = ssl_parse_certificate_verify( ssl );
+ break;
+
+ case SSL_CLIENT_CHANGE_CIPHER_SPEC:
+ ret = ssl_parse_change_cipher_spec( ssl );
+ break;
+
+ case SSL_CLIENT_FINISHED:
+ ret = ssl_parse_finished( ssl );
+ break;
+
+ /*
+ * ==> ChangeCipherSpec
+ * Finished
+ */
+ case SSL_SERVER_CHANGE_CIPHER_SPEC:
+ ret = ssl_write_change_cipher_spec( ssl );
+ break;
+
+ case SSL_SERVER_FINISHED:
+ ret = ssl_write_finished( ssl );
+ break;
+
+ case SSL_FLUSH_BUFFERS:
+ SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
+ ssl->state = SSL_HANDSHAKE_OVER;
+ break;
+
+ default:
+ SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ if( ret != 0 )
+ break;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= handshake server" ) );
+
+ return( ret );
+}
+
+#endif
diff --git a/polarssl/src/library/ssl_tls.c b/polarssl/src/library/ssl_tls.c
new file mode 100644
index 0000000..88c6e55
--- /dev/null
+++ b/polarssl/src/library/ssl_tls.c
@@ -0,0 +1,3166 @@
+/*
+ * SSLv3/TLSv1 shared functions
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The SSL 3.0 specification was drafted by Netscape in 1996,
+ * and became an IETF standard in 1999.
+ *
+ * http://wp.netscape.com/eng/ssl3/
+ * http://www.ietf.org/rfc/rfc2246.txt
+ * http://www.ietf.org/rfc/rfc4346.txt
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_SSL_TLS_C)
+
+#include "polarssl/aes.h"
+#include "polarssl/arc4.h"
+#include "polarssl/camellia.h"
+#include "polarssl/des.h"
+#include "polarssl/debug.h"
+#include "polarssl/ssl.h"
+#include "polarssl/sha2.h"
+
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
+#include <stdlib.h>
+#include <time.h>
+
+#if defined _MSC_VER && !defined strcasecmp
+#define strcasecmp _stricmp
+#endif
+
+/*
+ * Key material generation
+ */
+static int tls1_prf( unsigned char *secret, size_t slen, char *label,
+ unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ size_t nb, hs;
+ size_t i, j, k;
+ unsigned char *S1, *S2;
+ unsigned char tmp[128];
+ unsigned char h_i[20];
+
+ if( sizeof( tmp ) < 20 + strlen( label ) + rlen )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ hs = ( slen + 1 ) / 2;
+ S1 = secret;
+ S2 = secret + slen - hs;
+
+ nb = strlen( label );
+ memcpy( tmp + 20, label, nb );
+ memcpy( tmp + 20 + nb, random, rlen );
+ nb += rlen;
+
+ /*
+ * First compute P_md5(secret,label+random)[0..dlen]
+ */
+ md5_hmac( S1, hs, tmp + 20, nb, 4 + tmp );
+
+ for( i = 0; i < dlen; i += 16 )
+ {
+ md5_hmac( S1, hs, 4 + tmp, 16 + nb, h_i );
+ md5_hmac( S1, hs, 4 + tmp, 16, 4 + tmp );
+
+ k = ( i + 16 > dlen ) ? dlen % 16 : 16;
+
+ for( j = 0; j < k; j++ )
+ dstbuf[i + j] = h_i[j];
+ }
+
+ /*
+ * XOR out with P_sha1(secret,label+random)[0..dlen]
+ */
+ sha1_hmac( S2, hs, tmp + 20, nb, tmp );
+
+ for( i = 0; i < dlen; i += 20 )
+ {
+ sha1_hmac( S2, hs, tmp, 20 + nb, h_i );
+ sha1_hmac( S2, hs, tmp, 20, tmp );
+
+ k = ( i + 20 > dlen ) ? dlen % 20 : 20;
+
+ for( j = 0; j < k; j++ )
+ dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
+ }
+
+ memset( tmp, 0, sizeof( tmp ) );
+ memset( h_i, 0, sizeof( h_i ) );
+
+ return( 0 );
+}
+
+static int tls_prf_sha256( unsigned char *secret, size_t slen, char *label,
+ unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ size_t nb;
+ size_t i, j, k;
+ unsigned char tmp[128];
+ unsigned char h_i[32];
+
+ if( sizeof( tmp ) < 32 + strlen( label ) + rlen )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ nb = strlen( label );
+ memcpy( tmp + 32, label, nb );
+ memcpy( tmp + 32 + nb, random, rlen );
+ nb += rlen;
+
+ /*
+ * Compute P_<hash>(secret, label + random)[0..dlen]
+ */
+ sha2_hmac( secret, slen, tmp + 32, nb, tmp, 0 );
+
+ for( i = 0; i < dlen; i += 32 )
+ {
+ sha2_hmac( secret, slen, tmp, 32 + nb, h_i, 0 );
+ sha2_hmac( secret, slen, tmp, 32, tmp, 0 );
+
+ k = ( i + 32 > dlen ) ? dlen % 32 : 32;
+
+ for( j = 0; j < k; j++ )
+ dstbuf[i + j] = h_i[j];
+ }
+
+ memset( tmp, 0, sizeof( tmp ) );
+ memset( h_i, 0, sizeof( h_i ) );
+
+ return( 0 );
+}
+
+static int tls_prf_sha384( unsigned char *secret, size_t slen, char *label,
+ unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ size_t nb;
+ size_t i, j, k;
+ unsigned char tmp[128];
+ unsigned char h_i[48];
+
+ if( sizeof( tmp ) < 48 + strlen( label ) + rlen )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ nb = strlen( label );
+ memcpy( tmp + 48, label, nb );
+ memcpy( tmp + 48 + nb, random, rlen );
+ nb += rlen;
+
+ /*
+ * Compute P_<hash>(secret, label + random)[0..dlen]
+ */
+ sha4_hmac( secret, slen, tmp + 48, nb, tmp, 1 );
+
+ for( i = 0; i < dlen; i += 48 )
+ {
+ sha4_hmac( secret, slen, tmp, 48 + nb, h_i, 1 );
+ sha4_hmac( secret, slen, tmp, 48, tmp, 1 );
+
+ k = ( i + 48 > dlen ) ? dlen % 48 : 48;
+
+ for( j = 0; j < k; j++ )
+ dstbuf[i + j] = h_i[j];
+ }
+
+ memset( tmp, 0, sizeof( tmp ) );
+ memset( h_i, 0, sizeof( h_i ) );
+
+ return( 0 );
+}
+
+static void ssl_update_checksum_start(ssl_context *, unsigned char *, size_t);
+static void ssl_update_checksum_md5sha1(ssl_context *, unsigned char *, size_t);
+static void ssl_update_checksum_sha256(ssl_context *, unsigned char *, size_t);
+static void ssl_update_checksum_sha384(ssl_context *, unsigned char *, size_t);
+
+static void ssl_calc_verify_ssl(ssl_context *,unsigned char *);
+static void ssl_calc_verify_tls(ssl_context *,unsigned char *);
+static void ssl_calc_verify_tls_sha256(ssl_context *,unsigned char *);
+static void ssl_calc_verify_tls_sha384(ssl_context *,unsigned char *);
+
+static void ssl_calc_finished_ssl(ssl_context *,unsigned char *,int);
+static void ssl_calc_finished_tls(ssl_context *,unsigned char *,int);
+static void ssl_calc_finished_tls_sha256(ssl_context *,unsigned char *,int);
+static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int);
+
+int ssl_derive_keys( ssl_context *ssl )
+{
+ int i;
+ md5_context md5;
+ sha1_context sha1;
+ unsigned char tmp[64];
+ unsigned char padding[16];
+ unsigned char sha1sum[20];
+ unsigned char keyblk[256];
+ unsigned char *key1;
+ unsigned char *key2;
+ unsigned int iv_copy_len;
+
+ SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
+
+ /*
+ * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions
+ */
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ ssl->tls_prf = tls1_prf;
+ ssl->calc_verify = ssl_calc_verify_ssl;
+ ssl->calc_finished = ssl_calc_finished_ssl;
+ }
+ else if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+ {
+ ssl->tls_prf = tls1_prf;
+ ssl->calc_verify = ssl_calc_verify_tls;
+ ssl->calc_finished = ssl_calc_finished_tls;
+ }
+ else if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+ ssl->tls_prf = tls_prf_sha384;
+ ssl->calc_verify = ssl_calc_verify_tls_sha384;
+ ssl->calc_finished = ssl_calc_finished_tls_sha384;
+ }
+ else
+ {
+ ssl->tls_prf = tls_prf_sha256;
+ ssl->calc_verify = ssl_calc_verify_tls_sha256;
+ ssl->calc_finished = ssl_calc_finished_tls_sha256;
+ }
+
+ /*
+ * SSLv3:
+ * master =
+ * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) +
+ * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) +
+ * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
+ *
+ * TLSv1:
+ * master = PRF( premaster, "master secret", randbytes )[0..47]
+ */
+ if( ssl->resume == 0 )
+ {
+ size_t len = ssl->pmslen;
+
+ SSL_DEBUG_BUF( 3, "premaster secret", ssl->premaster, len );
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ for( i = 0; i < 3; i++ )
+ {
+ memset( padding, 'A' + i, 1 + i );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, padding, 1 + i );
+ sha1_update( &sha1, ssl->premaster, len );
+ sha1_update( &sha1, ssl->randbytes, 64 );
+ sha1_finish( &sha1, sha1sum );
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->premaster, len );
+ md5_update( &md5, sha1sum, 20 );
+ md5_finish( &md5, ssl->session->master + i * 16 );
+ }
+ }
+ else
+ ssl->tls_prf( ssl->premaster, len, "master secret",
+ ssl->randbytes, 64, ssl->session->master, 48 );
+
+ memset( ssl->premaster, 0, sizeof( ssl->premaster ) );
+ }
+ else
+ SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
+
+ /*
+ * Swap the client and server random values.
+ */
+ memcpy( tmp, ssl->randbytes, 64 );
+ memcpy( ssl->randbytes, tmp + 32, 32 );
+ memcpy( ssl->randbytes + 32, tmp, 32 );
+ memset( tmp, 0, sizeof( tmp ) );
+
+ /*
+ * SSLv3:
+ * key block =
+ * MD5( master + SHA1( 'A' + master + randbytes ) ) +
+ * MD5( master + SHA1( 'BB' + master + randbytes ) ) +
+ * MD5( master + SHA1( 'CCC' + master + randbytes ) ) +
+ * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) +
+ * ...
+ *
+ * TLSv1:
+ * key block = PRF( master, "key expansion", randbytes )
+ */
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ for( i = 0; i < 16; i++ )
+ {
+ memset( padding, 'A' + i, 1 + i );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, padding, 1 + i );
+ sha1_update( &sha1, ssl->session->master, 48 );
+ sha1_update( &sha1, ssl->randbytes, 64 );
+ sha1_finish( &sha1, sha1sum );
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->session->master, 48 );
+ md5_update( &md5, sha1sum, 20 );
+ md5_finish( &md5, keyblk + i * 16 );
+ }
+
+ memset( &md5, 0, sizeof( md5 ) );
+ memset( &sha1, 0, sizeof( sha1 ) );
+
+ memset( padding, 0, sizeof( padding ) );
+ memset( sha1sum, 0, sizeof( sha1sum ) );
+ }
+ else
+ ssl->tls_prf( ssl->session->master, 48, "key expansion",
+ ssl->randbytes, 64, keyblk, 256 );
+
+ SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", ssl_get_ciphersuite( ssl ) ) );
+ SSL_DEBUG_BUF( 3, "master secret", ssl->session->master, 48 );
+ SSL_DEBUG_BUF( 4, "random bytes", ssl->randbytes, 64 );
+ SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
+
+ memset( ssl->randbytes, 0, sizeof( ssl->randbytes ) );
+
+ /*
+ * Determine the appropriate key, IV and MAC length.
+ */
+ switch( ssl->session->ciphersuite )
+ {
+#if defined(POLARSSL_ARC4_C)
+ case SSL_RSA_RC4_128_MD5:
+ ssl->keylen = 16; ssl->minlen = 16;
+ ssl->ivlen = 0; ssl->maclen = 16;
+ break;
+
+ case SSL_RSA_RC4_128_SHA:
+ ssl->keylen = 16; ssl->minlen = 20;
+ ssl->ivlen = 0; ssl->maclen = 20;
+ break;
+#endif
+
+#if defined(POLARSSL_DES_C)
+ case SSL_RSA_DES_168_SHA:
+ case SSL_EDH_RSA_DES_168_SHA:
+ ssl->keylen = 24; ssl->minlen = 24;
+ ssl->ivlen = 8; ssl->maclen = 20;
+ break;
+#endif
+
+#if defined(POLARSSL_AES_C)
+ case SSL_RSA_AES_128_SHA:
+ case SSL_EDH_RSA_AES_128_SHA:
+ ssl->keylen = 16; ssl->minlen = 32;
+ ssl->ivlen = 16; ssl->maclen = 20;
+ break;
+
+ case SSL_RSA_AES_256_SHA:
+ case SSL_EDH_RSA_AES_256_SHA:
+ ssl->keylen = 32; ssl->minlen = 32;
+ ssl->ivlen = 16; ssl->maclen = 20;
+ break;
+
+#if defined(POLARSSL_SHA2_C)
+ case SSL_RSA_AES_128_SHA256:
+ case SSL_EDH_RSA_AES_128_SHA256:
+ ssl->keylen = 16; ssl->minlen = 32;
+ ssl->ivlen = 16; ssl->maclen = 32;
+ break;
+
+ case SSL_RSA_AES_256_SHA256:
+ case SSL_EDH_RSA_AES_256_SHA256:
+ ssl->keylen = 32; ssl->minlen = 32;
+ ssl->ivlen = 16; ssl->maclen = 32;
+ break;
+#endif
+#if defined(POLARSSL_GCM_C)
+ case SSL_RSA_AES_128_GCM_SHA256:
+ case SSL_EDH_RSA_AES_128_GCM_SHA256:
+ ssl->keylen = 16; ssl->minlen = 1;
+ ssl->ivlen = 12; ssl->maclen = 0;
+ ssl->fixed_ivlen = 4;
+ break;
+
+ case SSL_RSA_AES_256_GCM_SHA384:
+ case SSL_EDH_RSA_AES_256_GCM_SHA384:
+ ssl->keylen = 32; ssl->minlen = 1;
+ ssl->ivlen = 12; ssl->maclen = 0;
+ ssl->fixed_ivlen = 4;
+ break;
+#endif
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ case SSL_RSA_CAMELLIA_128_SHA:
+ case SSL_EDH_RSA_CAMELLIA_128_SHA:
+ ssl->keylen = 16; ssl->minlen = 32;
+ ssl->ivlen = 16; ssl->maclen = 20;
+ break;
+
+ case SSL_RSA_CAMELLIA_256_SHA:
+ case SSL_EDH_RSA_CAMELLIA_256_SHA:
+ ssl->keylen = 32; ssl->minlen = 32;
+ ssl->ivlen = 16; ssl->maclen = 20;
+ break;
+
+#if defined(POLARSSL_SHA2_C)
+ case SSL_RSA_CAMELLIA_128_SHA256:
+ case SSL_EDH_RSA_CAMELLIA_128_SHA256:
+ ssl->keylen = 16; ssl->minlen = 32;
+ ssl->ivlen = 16; ssl->maclen = 32;
+ break;
+
+ case SSL_RSA_CAMELLIA_256_SHA256:
+ case SSL_EDH_RSA_CAMELLIA_256_SHA256:
+ ssl->keylen = 32; ssl->minlen = 32;
+ ssl->ivlen = 16; ssl->maclen = 32;
+ break;
+#endif
+#endif
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ case SSL_RSA_NULL_MD5:
+ ssl->keylen = 0; ssl->minlen = 0;
+ ssl->ivlen = 0; ssl->maclen = 16;
+ break;
+
+ case SSL_RSA_NULL_SHA:
+ ssl->keylen = 0; ssl->minlen = 0;
+ ssl->ivlen = 0; ssl->maclen = 20;
+ break;
+
+ case SSL_RSA_NULL_SHA256:
+ ssl->keylen = 0; ssl->minlen = 0;
+ ssl->ivlen = 0; ssl->maclen = 32;
+ break;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#if defined(POLARSSL_DES_C)
+ case SSL_RSA_DES_SHA:
+ case SSL_EDH_RSA_DES_SHA:
+ ssl->keylen = 8; ssl->minlen = 8;
+ ssl->ivlen = 8; ssl->maclen = 20;
+ break;
+#endif
+#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+ default:
+ SSL_DEBUG_MSG( 1, ( "ciphersuite %s is not available",
+ ssl_get_ciphersuite( ssl ) ) );
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d",
+ ssl->keylen, ssl->minlen, ssl->ivlen, ssl->maclen ) );
+
+ /*
+ * Finally setup the cipher contexts, IVs and MAC secrets.
+ */
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ {
+ key1 = keyblk + ssl->maclen * 2;
+ key2 = keyblk + ssl->maclen * 2 + ssl->keylen;
+
+ memcpy( ssl->mac_enc, keyblk, ssl->maclen );
+ memcpy( ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen );
+
+ /*
+ * This is not used in TLS v1.1.
+ */
+ iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen;
+ memcpy( ssl->iv_enc, key2 + ssl->keylen, iv_copy_len );
+ memcpy( ssl->iv_dec, key2 + ssl->keylen + iv_copy_len,
+ iv_copy_len );
+ }
+ else
+ {
+ key1 = keyblk + ssl->maclen * 2 + ssl->keylen;
+ key2 = keyblk + ssl->maclen * 2;
+
+ memcpy( ssl->mac_dec, keyblk, ssl->maclen );
+ memcpy( ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen );
+
+ /*
+ * This is not used in TLS v1.1.
+ */
+ iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen;
+ memcpy( ssl->iv_dec, key1 + ssl->keylen, iv_copy_len );
+ memcpy( ssl->iv_enc, key1 + ssl->keylen + iv_copy_len,
+ iv_copy_len );
+ }
+
+ switch( ssl->session->ciphersuite )
+ {
+#if defined(POLARSSL_ARC4_C)
+ case SSL_RSA_RC4_128_MD5:
+ case SSL_RSA_RC4_128_SHA:
+ arc4_setup( (arc4_context *) ssl->ctx_enc, key1, ssl->keylen );
+ arc4_setup( (arc4_context *) ssl->ctx_dec, key2, ssl->keylen );
+ break;
+#endif
+
+#if defined(POLARSSL_DES_C)
+ case SSL_RSA_DES_168_SHA:
+ case SSL_EDH_RSA_DES_168_SHA:
+ des3_set3key_enc( (des3_context *) ssl->ctx_enc, key1 );
+ des3_set3key_dec( (des3_context *) ssl->ctx_dec, key2 );
+ break;
+#endif
+
+#if defined(POLARSSL_AES_C)
+ case SSL_RSA_AES_128_SHA:
+ case SSL_EDH_RSA_AES_128_SHA:
+ case SSL_RSA_AES_128_SHA256:
+ case SSL_EDH_RSA_AES_128_SHA256:
+ aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 128 );
+ aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 128 );
+ break;
+
+ case SSL_RSA_AES_256_SHA:
+ case SSL_EDH_RSA_AES_256_SHA:
+ case SSL_RSA_AES_256_SHA256:
+ case SSL_EDH_RSA_AES_256_SHA256:
+ aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 256 );
+ aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 256 );
+ break;
+
+#if defined(POLARSSL_GCM_C)
+ case SSL_RSA_AES_128_GCM_SHA256:
+ case SSL_EDH_RSA_AES_128_GCM_SHA256:
+ gcm_init( (gcm_context *) ssl->ctx_enc, key1, 128 );
+ gcm_init( (gcm_context *) ssl->ctx_dec, key2, 128 );
+ break;
+
+ case SSL_RSA_AES_256_GCM_SHA384:
+ case SSL_EDH_RSA_AES_256_GCM_SHA384:
+ gcm_init( (gcm_context *) ssl->ctx_enc, key1, 256 );
+ gcm_init( (gcm_context *) ssl->ctx_dec, key2, 256 );
+ break;
+#endif
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ case SSL_RSA_CAMELLIA_128_SHA:
+ case SSL_EDH_RSA_CAMELLIA_128_SHA:
+ case SSL_RSA_CAMELLIA_128_SHA256:
+ case SSL_EDH_RSA_CAMELLIA_128_SHA256:
+ camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 128 );
+ camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 128 );
+ break;
+
+ case SSL_RSA_CAMELLIA_256_SHA:
+ case SSL_EDH_RSA_CAMELLIA_256_SHA:
+ case SSL_RSA_CAMELLIA_256_SHA256:
+ case SSL_EDH_RSA_CAMELLIA_256_SHA256:
+ camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 256 );
+ camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 256 );
+ break;
+#endif
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ case SSL_RSA_NULL_MD5:
+ case SSL_RSA_NULL_SHA:
+ case SSL_RSA_NULL_SHA256:
+ break;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#if defined(POLARSSL_DES_C)
+ case SSL_RSA_DES_SHA:
+ case SSL_EDH_RSA_DES_SHA:
+ des_setkey_enc( (des_context *) ssl->ctx_enc, key1 );
+ des_setkey_dec( (des_context *) ssl->ctx_dec, key2 );
+ break;
+#endif
+#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+ default:
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ memset( keyblk, 0, sizeof( keyblk ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= derive keys" ) );
+
+ return( 0 );
+}
+
+void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] )
+{
+ md5_context md5;
+ sha1_context sha1;
+ unsigned char pad_1[48];
+ unsigned char pad_2[48];
+
+ SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) );
+
+ memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) );
+ memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
+ sizeof( sha1_context ) );
+
+ memset( pad_1, 0x36, 48 );
+ memset( pad_2, 0x5C, 48 );
+
+ md5_update( &md5, ssl->session->master, 48 );
+ md5_update( &md5, pad_1, 48 );
+ md5_finish( &md5, hash );
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->session->master, 48 );
+ md5_update( &md5, pad_2, 48 );
+ md5_update( &md5, hash, 16 );
+ md5_finish( &md5, hash );
+
+ sha1_update( &sha1, ssl->session->master, 48 );
+ sha1_update( &sha1, pad_1, 40 );
+ sha1_finish( &sha1, hash + 16 );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->session->master, 48 );
+ sha1_update( &sha1, pad_2, 40 );
+ sha1_update( &sha1, hash + 16, 20 );
+ sha1_finish( &sha1, hash + 16 );
+
+ SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+ SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+ return;
+}
+
+void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] )
+{
+ md5_context md5;
+ sha1_context sha1;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) );
+
+ memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) );
+ memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
+ sizeof( sha1_context ) );
+
+ md5_finish( &md5, hash );
+ sha1_finish( &sha1, hash + 16 );
+
+ SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+ SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+ return;
+}
+
+void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] )
+{
+ sha2_context sha2;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) );
+
+ memcpy( &sha2 , (sha2_context *) ssl->ctx_checksum, sizeof(sha2_context) );
+ sha2_finish( &sha2, hash );
+
+ SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 );
+ SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+ return;
+}
+
+void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] )
+{
+ sha4_context sha4;
+
+ SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) );
+
+ memcpy( &sha4 , (sha4_context *) ssl->ctx_checksum, sizeof(sha4_context) );
+ sha4_finish( &sha4, hash );
+
+ SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 );
+ SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
+
+ return;
+}
+
+/*
+ * SSLv3.0 MAC functions
+ */
+static void ssl_mac_md5( unsigned char *secret,
+ unsigned char *buf, size_t len,
+ unsigned char *ctr, int type )
+{
+ unsigned char header[11];
+ unsigned char padding[48];
+ md5_context md5;
+
+ memcpy( header, ctr, 8 );
+ header[ 8] = (unsigned char) type;
+ header[ 9] = (unsigned char)( len >> 8 );
+ header[10] = (unsigned char)( len );
+
+ memset( padding, 0x36, 48 );
+ md5_starts( &md5 );
+ md5_update( &md5, secret, 16 );
+ md5_update( &md5, padding, 48 );
+ md5_update( &md5, header, 11 );
+ md5_update( &md5, buf, len );
+ md5_finish( &md5, buf + len );
+
+ memset( padding, 0x5C, 48 );
+ md5_starts( &md5 );
+ md5_update( &md5, secret, 16 );
+ md5_update( &md5, padding, 48 );
+ md5_update( &md5, buf + len, 16 );
+ md5_finish( &md5, buf + len );
+}
+
+static void ssl_mac_sha1( unsigned char *secret,
+ unsigned char *buf, size_t len,
+ unsigned char *ctr, int type )
+{
+ unsigned char header[11];
+ unsigned char padding[40];
+ sha1_context sha1;
+
+ memcpy( header, ctr, 8 );
+ header[ 8] = (unsigned char) type;
+ header[ 9] = (unsigned char)( len >> 8 );
+ header[10] = (unsigned char)( len );
+
+ memset( padding, 0x36, 40 );
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, secret, 20 );
+ sha1_update( &sha1, padding, 40 );
+ sha1_update( &sha1, header, 11 );
+ sha1_update( &sha1, buf, len );
+ sha1_finish( &sha1, buf + len );
+
+ memset( padding, 0x5C, 40 );
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, secret, 20 );
+ sha1_update( &sha1, padding, 40 );
+ sha1_update( &sha1, buf + len, 20 );
+ sha1_finish( &sha1, buf + len );
+}
+
+/*
+ * Encryption/decryption functions
+ */
+static int ssl_encrypt_buf( ssl_context *ssl )
+{
+ size_t i, padlen;
+
+ SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
+
+ /*
+ * Add MAC then encrypt
+ */
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ if( ssl->maclen == 16 )
+ ssl_mac_md5( ssl->mac_enc,
+ ssl->out_msg, ssl->out_msglen,
+ ssl->out_ctr, ssl->out_msgtype );
+
+ if( ssl->maclen == 20 )
+ ssl_mac_sha1( ssl->mac_enc,
+ ssl->out_msg, ssl->out_msglen,
+ ssl->out_ctr, ssl->out_msgtype );
+ }
+ else
+ {
+ if( ssl->maclen == 16 )
+ md5_hmac( ssl->mac_enc, 16,
+ ssl->out_ctr, ssl->out_msglen + 13,
+ ssl->out_msg + ssl->out_msglen );
+
+ if( ssl->maclen == 20 )
+ sha1_hmac( ssl->mac_enc, 20,
+ ssl->out_ctr, ssl->out_msglen + 13,
+ ssl->out_msg + ssl->out_msglen );
+
+ if( ssl->maclen == 32 )
+ sha2_hmac( ssl->mac_enc, 32,
+ ssl->out_ctr, ssl->out_msglen + 13,
+ ssl->out_msg + ssl->out_msglen, 0);
+ }
+
+ SSL_DEBUG_BUF( 4, "computed mac",
+ ssl->out_msg + ssl->out_msglen, ssl->maclen );
+
+ ssl->out_msglen += ssl->maclen;
+
+ if( ssl->ivlen == 0 )
+ {
+ padlen = 0;
+
+ SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including %d bytes of padding",
+ ssl->out_msglen, 0 ) );
+
+ SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+#if defined(POLARSSL_ARC4_C)
+ if( ssl->session->ciphersuite == SSL_RSA_RC4_128_MD5 ||
+ ssl->session->ciphersuite == SSL_RSA_RC4_128_SHA )
+ {
+ arc4_crypt( (arc4_context *) ssl->ctx_enc,
+ ssl->out_msglen, ssl->out_msg,
+ ssl->out_msg );
+ } else
+#endif
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( ssl->session->ciphersuite == SSL_RSA_NULL_MD5 ||
+ ssl->session->ciphersuite == SSL_RSA_NULL_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_NULL_SHA256 )
+ {
+ } else
+#endif
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ else if( ssl->ivlen == 12 )
+ {
+ size_t enc_msglen;
+ unsigned char *enc_msg;
+ unsigned char add_data[13];
+ int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+ padlen = 0;
+ enc_msglen = ssl->out_msglen;
+
+ memcpy( add_data, ssl->out_ctr, 8 );
+ add_data[8] = ssl->out_msgtype;
+ add_data[9] = ssl->major_ver;
+ add_data[10] = ssl->minor_ver;
+ add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF;
+ add_data[12] = ssl->out_msglen & 0xFF;
+
+ SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+ add_data, 13 );
+
+#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
+
+ if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 ||
+ ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+ /*
+ * Generate IV
+ */
+ ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc + ssl->fixed_ivlen,
+ ssl->ivlen - ssl->fixed_ivlen );
+ if( ret != 0 )
+ return( ret );
+
+ /*
+ * Shift message for ivlen bytes and prepend IV
+ */
+ memmove( ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen,
+ ssl->out_msg, ssl->out_msglen );
+ memcpy( ssl->out_msg, ssl->iv_enc + ssl->fixed_ivlen,
+ ssl->ivlen - ssl->fixed_ivlen );
+
+ /*
+ * Fix pointer positions and message length with added IV
+ */
+ enc_msg = ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen;
+ enc_msglen = ssl->out_msglen;
+ ssl->out_msglen += ssl->ivlen - ssl->fixed_ivlen;
+
+ SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including %d bytes of padding",
+ ssl->out_msglen, 0 ) );
+
+ SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+ /*
+ * Adjust for tag
+ */
+ ssl->out_msglen += 16;
+
+ gcm_crypt_and_tag( (gcm_context *) ssl->ctx_enc,
+ GCM_ENCRYPT, enc_msglen,
+ ssl->iv_enc, ssl->ivlen,
+ add_data, 13,
+ enc_msg, enc_msg,
+ 16, enc_msg + enc_msglen );
+
+ SSL_DEBUG_BUF( 4, "after encrypt: tag",
+ enc_msg + enc_msglen, 16 );
+
+ } else
+#endif
+ return( ret );
+ }
+ else
+ {
+ unsigned char *enc_msg;
+ size_t enc_msglen;
+
+ padlen = ssl->ivlen - ( ssl->out_msglen + 1 ) % ssl->ivlen;
+ if( padlen == ssl->ivlen )
+ padlen = 0;
+
+ for( i = 0; i <= padlen; i++ )
+ ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen;
+
+ ssl->out_msglen += padlen + 1;
+
+ enc_msglen = ssl->out_msglen;
+ enc_msg = ssl->out_msg;
+
+ /*
+ * Prepend per-record IV for block cipher in TLS v1.1 and up as per
+ * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
+ */
+ if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+ {
+ /*
+ * Generate IV
+ */
+ int ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc, ssl->ivlen );
+ if( ret != 0 )
+ return( ret );
+
+ /*
+ * Shift message for ivlen bytes and prepend IV
+ */
+ memmove( ssl->out_msg + ssl->ivlen, ssl->out_msg, ssl->out_msglen );
+ memcpy( ssl->out_msg, ssl->iv_enc, ssl->ivlen );
+
+ /*
+ * Fix pointer positions and message length with added IV
+ */
+ enc_msg = ssl->out_msg + ssl->ivlen;
+ enc_msglen = ssl->out_msglen;
+ ssl->out_msglen += ssl->ivlen;
+ }
+
+ SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including %d bytes of IV and %d bytes of padding",
+ ssl->out_msglen, ssl->ivlen, padlen + 1 ) );
+
+ SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+ switch( ssl->ivlen )
+ {
+#if defined(POLARSSL_DES_C)
+ case 8:
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+ if( ssl->session->ciphersuite == SSL_RSA_DES_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA )
+ {
+ des_crypt_cbc( (des_context *) ssl->ctx_enc,
+ DES_ENCRYPT, enc_msglen,
+ ssl->iv_enc, enc_msg, enc_msg );
+ }
+ else
+#endif
+ des3_crypt_cbc( (des3_context *) ssl->ctx_enc,
+ DES_ENCRYPT, enc_msglen,
+ ssl->iv_enc, enc_msg, enc_msg );
+ break;
+#endif
+
+ case 16:
+#if defined(POLARSSL_AES_C)
+ if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_AES_256_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_AES_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_RSA_AES_256_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 )
+ {
+ aes_crypt_cbc( (aes_context *) ssl->ctx_enc,
+ AES_ENCRYPT, enc_msglen,
+ ssl->iv_enc, enc_msg, enc_msg);
+ break;
+ }
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 )
+ {
+ camellia_crypt_cbc( (camellia_context *) ssl->ctx_enc,
+ CAMELLIA_ENCRYPT, enc_msglen,
+ ssl->iv_enc, enc_msg, enc_msg );
+ break;
+ }
+#endif
+
+ default:
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ }
+
+ for( i = 8; i > 0; i-- )
+ if( ++ssl->out_ctr[i - 1] != 0 )
+ break;
+
+ SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
+
+ return( 0 );
+}
+
+/*
+ * TODO: Use digest version when integrated!
+ */
+#define POLARSSL_SSL_MAX_MAC_SIZE 32
+
+static int ssl_decrypt_buf( ssl_context *ssl )
+{
+ size_t i, padlen;
+ unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
+
+ SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
+
+ if( ssl->in_msglen < ssl->minlen )
+ {
+ SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)",
+ ssl->in_msglen, ssl->minlen ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+
+ if( ssl->ivlen == 0 )
+ {
+#if defined(POLARSSL_ARC4_C)
+ padlen = 0;
+ if( ssl->session->ciphersuite == SSL_RSA_RC4_128_MD5 ||
+ ssl->session->ciphersuite == SSL_RSA_RC4_128_SHA )
+ {
+ arc4_crypt( (arc4_context *) ssl->ctx_dec,
+ ssl->in_msglen, ssl->in_msg,
+ ssl->in_msg );
+ } else
+#endif
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if( ssl->session->ciphersuite == SSL_RSA_NULL_MD5 ||
+ ssl->session->ciphersuite == SSL_RSA_NULL_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_NULL_SHA256 )
+ {
+ } else
+#endif
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+ else if( ssl->ivlen == 12 )
+ {
+ unsigned char *dec_msg;
+ unsigned char *dec_msg_result;
+ size_t dec_msglen;
+ unsigned char add_data[13];
+ int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+ padlen = 0;
+
+#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
+ if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 ||
+ ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+ dec_msglen = ssl->in_msglen - ( ssl->ivlen - ssl->fixed_ivlen );
+ dec_msglen -= 16;
+ dec_msg = ssl->in_msg + ( ssl->ivlen - ssl->fixed_ivlen );
+ dec_msg_result = ssl->in_msg;
+ ssl->in_msglen = dec_msglen;
+
+ memcpy( add_data, ssl->in_ctr, 8 );
+ add_data[8] = ssl->in_msgtype;
+ add_data[9] = ssl->major_ver;
+ add_data[10] = ssl->minor_ver;
+ add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
+ add_data[12] = ssl->in_msglen & 0xFF;
+
+ SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+ add_data, 13 );
+
+ memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg,
+ ssl->ivlen - ssl->fixed_ivlen );
+
+ SSL_DEBUG_BUF( 4, "IV used", ssl->iv_dec, ssl->ivlen );
+ SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 );
+
+ memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg,
+ ssl->ivlen - ssl->fixed_ivlen );
+
+ ret = gcm_auth_decrypt( (gcm_context *) ssl->ctx_dec,
+ dec_msglen,
+ ssl->iv_dec, ssl->ivlen,
+ add_data, 13,
+ dec_msg + dec_msglen, 16,
+ dec_msg, dec_msg_result );
+
+ if( ret != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)",
+ -ret ) );
+
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+ } else
+#endif
+ return( ret );
+ }
+ else
+ {
+ unsigned char *dec_msg;
+ unsigned char *dec_msg_result;
+ size_t dec_msglen;
+
+ /*
+ * Decrypt and check the padding
+ */
+ if( ssl->in_msglen % ssl->ivlen != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
+ ssl->in_msglen, ssl->ivlen ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+
+ dec_msglen = ssl->in_msglen;
+ dec_msg = ssl->in_msg;
+ dec_msg_result = ssl->in_msg;
+
+ /*
+ * Initialize for prepended IV for block cipher in TLS v1.1 and up
+ */
+ if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
+ {
+ dec_msg += ssl->ivlen;
+ dec_msglen -= ssl->ivlen;
+ ssl->in_msglen -= ssl->ivlen;
+
+ for( i = 0; i < ssl->ivlen; i++ )
+ ssl->iv_dec[i] = ssl->in_msg[i];
+ }
+
+ switch( ssl->ivlen )
+ {
+#if defined(POLARSSL_DES_C)
+ case 8:
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+ if( ssl->session->ciphersuite == SSL_RSA_DES_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_DES_SHA )
+ {
+ des_crypt_cbc( (des_context *) ssl->ctx_dec,
+ DES_DECRYPT, dec_msglen,
+ ssl->iv_dec, dec_msg, dec_msg_result );
+ }
+ else
+#endif
+ des3_crypt_cbc( (des3_context *) ssl->ctx_dec,
+ DES_DECRYPT, dec_msglen,
+ ssl->iv_dec, dec_msg, dec_msg_result );
+ break;
+#endif
+
+ case 16:
+#if defined(POLARSSL_AES_C)
+ if ( ssl->session->ciphersuite == SSL_RSA_AES_128_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_AES_256_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_AES_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_RSA_AES_256_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_SHA256 )
+ {
+ aes_crypt_cbc( (aes_context *) ssl->ctx_dec,
+ AES_DECRYPT, dec_msglen,
+ ssl->iv_dec, dec_msg, dec_msg_result );
+ break;
+ }
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ if ( ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA ||
+ ssl->session->ciphersuite == SSL_RSA_CAMELLIA_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 ||
+ ssl->session->ciphersuite == SSL_RSA_CAMELLIA_256_SHA256 ||
+ ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 )
+ {
+ camellia_crypt_cbc( (camellia_context *) ssl->ctx_dec,
+ CAMELLIA_DECRYPT, dec_msglen,
+ ssl->iv_dec, dec_msg, dec_msg_result );
+ break;
+ }
+#endif
+
+ default:
+ return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ if( padlen > ssl->ivlen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
+ "should be no more than %d",
+ padlen, ssl->ivlen ) );
+ padlen = 0;
+ }
+ }
+ else
+ {
+ /*
+ * TLSv1: always check the padding
+ */
+ for( i = 1; i <= padlen; i++ )
+ {
+ if( ssl->in_msg[ssl->in_msglen - i] != padlen - 1 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad padding byte: should be "
+ "%02x, but is %02x", padlen - 1,
+ ssl->in_msg[ssl->in_msglen - i] ) );
+ padlen = 0;
+ }
+ }
+ }
+ }
+
+ SSL_DEBUG_BUF( 4, "raw buffer after decryption",
+ ssl->in_msg, ssl->in_msglen );
+
+ /*
+ * Always compute the MAC (RFC4346, CBCTIME).
+ */
+ if( ssl->in_msglen < ssl->maclen + padlen )
+ {
+ SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
+ ssl->in_msglen, ssl->maclen, padlen ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+
+ ssl->in_msglen -= ( ssl->maclen + padlen );
+
+ ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
+ ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen );
+
+ memcpy( tmp, ssl->in_msg + ssl->in_msglen, POLARSSL_SSL_MAX_MAC_SIZE );
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ if( ssl->maclen == 16 )
+ ssl_mac_md5( ssl->mac_dec,
+ ssl->in_msg, ssl->in_msglen,
+ ssl->in_ctr, ssl->in_msgtype );
+ else if( ssl->maclen == 20 )
+ ssl_mac_sha1( ssl->mac_dec,
+ ssl->in_msg, ssl->in_msglen,
+ ssl->in_ctr, ssl->in_msgtype );
+ }
+ else
+ {
+ if( ssl->maclen == 16 )
+ md5_hmac( ssl->mac_dec, 16,
+ ssl->in_ctr, ssl->in_msglen + 13,
+ ssl->in_msg + ssl->in_msglen );
+ else if( ssl->maclen == 20 )
+ sha1_hmac( ssl->mac_dec, 20,
+ ssl->in_ctr, ssl->in_msglen + 13,
+ ssl->in_msg + ssl->in_msglen );
+ else if( ssl->maclen == 32 )
+ sha2_hmac( ssl->mac_dec, 32,
+ ssl->in_ctr, ssl->in_msglen + 13,
+ ssl->in_msg + ssl->in_msglen, 0 );
+ }
+
+ SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->maclen );
+ SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen,
+ ssl->maclen );
+
+ if( memcmp( tmp, ssl->in_msg + ssl->in_msglen,
+ ssl->maclen ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+
+ /*
+ * Finally check the padding length; bad padding
+ * will produce the same error as an invalid MAC.
+ */
+ if( ssl->ivlen != 0 && ssl->ivlen != 12 && padlen == 0 )
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+
+ if( ssl->in_msglen == 0 )
+ {
+ ssl->nb_zero++;
+
+ /*
+ * Three or more empty messages may be a DoS attack
+ * (excessive CPU consumption).
+ */
+ if( ssl->nb_zero > 3 )
+ {
+ SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
+ "messages, possible DoS attack" ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+ }
+ else
+ ssl->nb_zero = 0;
+
+ for( i = 8; i > 0; i-- )
+ if( ++ssl->in_ctr[i - 1] != 0 )
+ break;
+
+ SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
+
+ return( 0 );
+}
+
+/*
+ * Fill the input message buffer
+ */
+int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
+{
+ int ret;
+ size_t len;
+
+ SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
+
+ while( ssl->in_left < nb_want )
+ {
+ len = nb_want - ssl->in_left;
+ ret = ssl->f_recv( ssl->p_recv, ssl->in_hdr + ssl->in_left, len );
+
+ SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+ ssl->in_left, nb_want ) );
+ SSL_DEBUG_RET( 2, "ssl->f_recv", ret );
+
+ if( ret == 0 )
+ return( POLARSSL_ERR_SSL_CONN_EOF );
+
+ if( ret < 0 )
+ return( ret );
+
+ ssl->in_left += ret;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
+
+ return( 0 );
+}
+
+/*
+ * Flush any data not yet written
+ */
+int ssl_flush_output( ssl_context *ssl )
+{
+ int ret;
+ unsigned char *buf;
+
+ SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
+
+ while( ssl->out_left > 0 )
+ {
+ SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
+ 5 + ssl->out_msglen, ssl->out_left ) );
+
+ buf = ssl->out_hdr + 5 + ssl->out_msglen - ssl->out_left;
+ ret = ssl->f_send( ssl->p_send, buf, ssl->out_left );
+ SSL_DEBUG_RET( 2, "ssl->f_send", ret );
+
+ if( ret <= 0 )
+ return( ret );
+
+ ssl->out_left -= ret;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
+
+ return( 0 );
+}
+
+/*
+ * Record layer functions
+ */
+int ssl_write_record( ssl_context *ssl )
+{
+ int ret;
+ size_t len = ssl->out_msglen;
+
+ SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+
+ ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
+ ssl->out_hdr[1] = (unsigned char) ssl->major_ver;
+ ssl->out_hdr[2] = (unsigned char) ssl->minor_ver;
+ ssl->out_hdr[3] = (unsigned char)( len >> 8 );
+ ssl->out_hdr[4] = (unsigned char)( len );
+
+ if( ssl->out_msgtype == SSL_MSG_HANDSHAKE )
+ {
+ ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 );
+ ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 );
+ ssl->out_msg[3] = (unsigned char)( ( len - 4 ) );
+
+ ssl->update_checksum( ssl, ssl->out_msg, len );
+ }
+
+ if( ssl->do_crypt != 0 )
+ {
+ if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
+ return( ret );
+ }
+
+ len = ssl->out_msglen;
+ ssl->out_hdr[3] = (unsigned char)( len >> 8 );
+ ssl->out_hdr[4] = (unsigned char)( len );
+ }
+
+ ssl->out_left = 5 + ssl->out_msglen;
+
+ SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
+ "version = [%d:%d], msglen = %d",
+ ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2],
+ ( ssl->out_hdr[3] << 8 ) | ssl->out_hdr[4] ) );
+
+ SSL_DEBUG_BUF( 4, "output record sent to network",
+ ssl->out_hdr, 5 + ssl->out_msglen );
+
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write record" ) );
+
+ return( 0 );
+}
+
+int ssl_read_record( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> read record" ) );
+
+ if( ssl->in_hslen != 0 &&
+ ssl->in_hslen < ssl->in_msglen )
+ {
+ /*
+ * Get next Handshake message in the current record
+ */
+ ssl->in_msglen -= ssl->in_hslen;
+
+ memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
+ ssl->in_msglen );
+
+ ssl->in_hslen = 4;
+ ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
+
+ SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+ " %d, type = %d, hslen = %d",
+ ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+ if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msglen < ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ ssl->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+
+ return( 0 );
+ }
+
+ ssl->in_hslen = 0;
+
+ /*
+ * Read the record header and validate it
+ */
+ if( ( ret = ssl_fetch_input( ssl, 5 ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ ssl->in_msgtype = ssl->in_hdr[0];
+ ssl->in_msglen = ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4];
+
+ SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
+ "version = [%d:%d], msglen = %d",
+ ssl->in_hdr[0], ssl->in_hdr[1], ssl->in_hdr[2],
+ ( ssl->in_hdr[3] << 8 ) | ssl->in_hdr[4] ) );
+
+ if( ssl->in_hdr[1] != ssl->major_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_hdr[2] > ssl->max_minor_ver )
+ {
+ SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ /*
+ * Make sure the message length is acceptable
+ */
+ if( ssl->do_crypt == 0 )
+ {
+ if( ssl->in_msglen < 1 ||
+ ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+ }
+ else
+ {
+ if( ssl->in_msglen < ssl->minlen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->minor_ver == SSL_MINOR_VERSION_0 &&
+ ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ /*
+ * TLS encrypted messages can have up to 256 bytes of padding
+ */
+ if( ssl->minor_ver >= SSL_MINOR_VERSION_1 &&
+ ssl->in_msglen > ssl->minlen + SSL_MAX_CONTENT_LEN + 256 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+ }
+
+ /*
+ * Read and optionally decrypt the message contents
+ */
+ if( ( ret = ssl_fetch_input( ssl, 5 + ssl->in_msglen ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_BUF( 4, "input record from network",
+ ssl->in_hdr, 5 + ssl->in_msglen );
+
+ if( ssl->do_crypt != 0 )
+ {
+ if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_BUF( 4, "input payload after decrypt",
+ ssl->in_msg, ssl->in_msglen );
+
+ if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE &&
+ ssl->in_msgtype != SSL_MSG_ALERT &&
+ ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC &&
+ ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
+ {
+ SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
+
+ if( ( ret = ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+ SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msgtype == SSL_MSG_HANDSHAKE )
+ {
+ ssl->in_hslen = 4;
+ ssl->in_hslen += ( ssl->in_msg[2] << 8 ) | ssl->in_msg[3];
+
+ SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+ " %d, type = %d, hslen = %d",
+ ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+ /*
+ * Additional checks to validate the handshake header
+ */
+ if( ssl->in_msglen < 4 || ssl->in_msg[1] != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msglen < ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad handshake length" ) );
+ return( POLARSSL_ERR_SSL_INVALID_RECORD );
+ }
+
+ ssl->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+ }
+
+ if( ssl->in_msgtype == SSL_MSG_ALERT )
+ {
+ SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
+ ssl->in_msg[0], ssl->in_msg[1] ) );
+
+ /*
+ * Ignore non-fatal alerts, except close_notify
+ */
+ if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL )
+ {
+ SSL_DEBUG_MSG( 1, ( "is a fatal alert message" ) );
+ /**
+ * Subtract from error code as ssl->in_msg[1] is 7-bit positive
+ * error identifier.
+ */
+ return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE - ssl->in_msg[1] );
+ }
+
+ if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY )
+ {
+ SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
+ return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY );
+ }
+ }
+
+ ssl->in_left = 0;
+
+ SSL_DEBUG_MSG( 2, ( "<= read record" ) );
+
+ return( 0 );
+}
+
+int ssl_send_alert_message( ssl_context *ssl,
+ unsigned char level,
+ unsigned char message )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
+
+ ssl->out_msgtype = SSL_MSG_ALERT;
+ ssl->out_msglen = 2;
+ ssl->out_msg[0] = level;
+ ssl->out_msg[1] = message;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
+
+ return( 0 );
+}
+
+/*
+ * Handshake functions
+ */
+int ssl_write_certificate( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n;
+ const x509_cert *crt;
+
+ SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
+
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ {
+ if( ssl->client_auth == 0 )
+ {
+ SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ /*
+ * If using SSLv3 and got no cert, send an Alert message
+ * (otherwise an empty Certificate message will be sent).
+ */
+ if( ssl->own_cert == NULL &&
+ ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ ssl->out_msglen = 2;
+ ssl->out_msgtype = SSL_MSG_ALERT;
+ ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING;
+ ssl->out_msg[1] = SSL_ALERT_MSG_NO_CERT;
+
+ SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
+ goto write_msg;
+ }
+ }
+ else /* SSL_IS_SERVER */
+ {
+ if( ssl->own_cert == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) );
+ return( POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED );
+ }
+ }
+
+ SSL_DEBUG_CRT( 3, "own certificate", ssl->own_cert );
+
+ /*
+ * 0 . 0 handshake type
+ * 1 . 3 handshake length
+ * 4 . 6 length of all certs
+ * 7 . 9 length of cert. 1
+ * 10 . n-1 peer certificate
+ * n . n+2 length of cert. 2
+ * n+3 . ... upper level cert, etc.
+ */
+ i = 7;
+ crt = ssl->own_cert;
+
+ while( crt != NULL )
+ {
+ n = crt->raw.len;
+ if( i + 3 + n > SSL_MAX_CONTENT_LEN )
+ {
+ SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
+ i + 3 + n, SSL_MAX_CONTENT_LEN ) );
+ return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE );
+ }
+
+ ssl->out_msg[i ] = (unsigned char)( n >> 16 );
+ ssl->out_msg[i + 1] = (unsigned char)( n >> 8 );
+ ssl->out_msg[i + 2] = (unsigned char)( n );
+
+ i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
+ i += n; crt = crt->next;
+ }
+
+ ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 );
+ ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 );
+ ssl->out_msg[6] = (unsigned char)( ( i - 7 ) );
+
+ ssl->out_msglen = i;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_CERTIFICATE;
+
+write_msg:
+
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write certificate" ) );
+
+ return( 0 );
+}
+
+int ssl_parse_certificate( ssl_context *ssl )
+{
+ int ret;
+ size_t i, n;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+ if( ssl->endpoint == SSL_IS_SERVER &&
+ ssl->authmode == SSL_VERIFY_NONE )
+ {
+ ssl->verify_result = BADCERT_SKIP_VERIFY;
+ SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ ssl->state++;
+
+ /*
+ * Check if the client sent an empty certificate
+ */
+ if( ssl->endpoint == SSL_IS_SERVER &&
+ ssl->minor_ver == SSL_MINOR_VERSION_0 )
+ {
+ if( ssl->in_msglen == 2 &&
+ ssl->in_msgtype == SSL_MSG_ALERT &&
+ ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == SSL_ALERT_MSG_NO_CERT )
+ {
+ SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
+
+ ssl->verify_result = BADCERT_MISSING;
+ if( ssl->authmode == SSL_VERIFY_OPTIONAL )
+ return( 0 );
+ else
+ return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ }
+ }
+
+ if( ssl->endpoint == SSL_IS_SERVER &&
+ ssl->minor_ver != SSL_MINOR_VERSION_0 )
+ {
+ if( ssl->in_hslen == 7 &&
+ ssl->in_msgtype == SSL_MSG_HANDSHAKE &&
+ ssl->in_msg[0] == SSL_HS_CERTIFICATE &&
+ memcmp( ssl->in_msg + 4, "\0\0\0", 3 ) == 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
+
+ ssl->verify_result = BADCERT_MISSING;
+ if( ssl->authmode == SSL_VERIFY_REQUIRED )
+ return( POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ else
+ return( 0 );
+ }
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ if( ssl->in_msg[0] != SSL_HS_CERTIFICATE || ssl->in_hslen < 10 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ /*
+ * Same message structure as in ssl_write_certificate()
+ */
+ n = ( ssl->in_msg[5] << 8 ) | ssl->in_msg[6];
+
+ if( ssl->in_msg[4] != 0 || ssl->in_hslen != 7 + n )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ if( ( ssl->peer_cert = (x509_cert *) malloc(
+ sizeof( x509_cert ) ) ) == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed",
+ sizeof( x509_cert ) ) );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ memset( ssl->peer_cert, 0, sizeof( x509_cert ) );
+
+ i = 7;
+
+ while( i < ssl->in_hslen )
+ {
+ if( ssl->in_msg[i] != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
+ | (unsigned int) ssl->in_msg[i + 2];
+ i += 3;
+
+ if( n < 128 || i + n > ssl->in_hslen )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ ret = x509parse_crt( ssl->peer_cert, ssl->in_msg + i, n );
+ if( ret != 0 )
+ {
+ SSL_DEBUG_RET( 1, " x509parse_crt", ret );
+ return( ret );
+ }
+
+ i += n;
+ }
+
+ SSL_DEBUG_CRT( 3, "peer certificate", ssl->peer_cert );
+
+ if( ssl->authmode != SSL_VERIFY_NONE )
+ {
+ if( ssl->ca_chain == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
+ return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED );
+ }
+
+ ret = x509parse_verify( ssl->peer_cert, ssl->ca_chain, ssl->ca_crl,
+ ssl->peer_cn, &ssl->verify_result,
+ ssl->f_vrfy, ssl->p_vrfy );
+
+ if( ret != 0 )
+ SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
+
+ if( ssl->authmode != SSL_VERIFY_REQUIRED )
+ ret = 0;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
+
+ return( ret );
+}
+
+int ssl_write_change_cipher_spec( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
+
+ ssl->out_msgtype = SSL_MSG_CHANGE_CIPHER_SPEC;
+ ssl->out_msglen = 1;
+ ssl->out_msg[0] = 1;
+
+ ssl->do_crypt = 0;
+ ssl->state++;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
+
+ return( 0 );
+}
+
+int ssl_parse_change_cipher_spec( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
+
+ ssl->do_crypt = 0;
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
+ }
+
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
+
+ return( 0 );
+}
+
+void ssl_kickstart_checksum( ssl_context *ssl, int ciphersuite,
+ unsigned char *input_buf, size_t len )
+{
+ if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
+ {
+ md5_starts( (md5_context *) ssl->ctx_checksum );
+ sha1_starts( (sha1_context *) ( ssl->ctx_checksum +
+ sizeof(md5_context) ) );
+
+ ssl->update_checksum = ssl_update_checksum_md5sha1;
+ }
+ else if ( ciphersuite == SSL_RSA_AES_256_GCM_SHA384 ||
+ ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 )
+ {
+ sha4_starts( (sha4_context *) ssl->ctx_checksum, 1 );
+ ssl->update_checksum = ssl_update_checksum_sha384;
+ }
+ else
+ {
+ sha2_starts( (sha2_context *) ssl->ctx_checksum, 0 );
+ ssl->update_checksum = ssl_update_checksum_sha256;
+ }
+
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ ssl->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
+ ssl->update_checksum( ssl, input_buf, len );
+}
+
+static void ssl_update_checksum_start( ssl_context *ssl, unsigned char *buf,
+ size_t len )
+{
+ ((void) ssl);
+ ((void) buf);
+ ((void) len);
+}
+
+static void ssl_update_checksum_md5sha1( ssl_context *ssl, unsigned char *buf,
+ size_t len )
+{
+ md5_update( (md5_context *) ssl->ctx_checksum, buf, len );
+ sha1_update( (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
+ buf, len );
+}
+
+static void ssl_update_checksum_sha256( ssl_context *ssl, unsigned char *buf,
+ size_t len )
+{
+ sha2_update( (sha2_context *) ssl->ctx_checksum, buf, len );
+}
+
+static void ssl_update_checksum_sha384( ssl_context *ssl, unsigned char *buf,
+ size_t len )
+{
+ sha4_update( (sha4_context *) ssl->ctx_checksum, buf, len );
+}
+
+static void ssl_calc_finished_ssl(
+ ssl_context *ssl, unsigned char *buf, int from )
+{
+ char *sender;
+ md5_context md5;
+ sha1_context sha1;
+
+ unsigned char padbuf[48];
+ unsigned char md5sum[16];
+ unsigned char sha1sum[20];
+
+ SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) );
+
+ memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) );
+ memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
+ sizeof( sha1_context ) );
+
+ /*
+ * SSLv3:
+ * hash =
+ * MD5( master + pad2 +
+ * MD5( handshake + sender + master + pad1 ) )
+ * + SHA1( master + pad2 +
+ * SHA1( handshake + sender + master + pad1 ) )
+ */
+
+ SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *)
+ md5.state, sizeof( md5.state ) );
+
+ SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
+ sha1.state, sizeof( sha1.state ) );
+
+ sender = ( from == SSL_IS_CLIENT ) ? (char *) "CLNT"
+ : (char *) "SRVR";
+
+ memset( padbuf, 0x36, 48 );
+
+ md5_update( &md5, (unsigned char *) sender, 4 );
+ md5_update( &md5, ssl->session->master, 48 );
+ md5_update( &md5, padbuf, 48 );
+ md5_finish( &md5, md5sum );
+
+ sha1_update( &sha1, (unsigned char *) sender, 4 );
+ sha1_update( &sha1, ssl->session->master, 48 );
+ sha1_update( &sha1, padbuf, 40 );
+ sha1_finish( &sha1, sha1sum );
+
+ memset( padbuf, 0x5C, 48 );
+
+ md5_starts( &md5 );
+ md5_update( &md5, ssl->session->master, 48 );
+ md5_update( &md5, padbuf, 48 );
+ md5_update( &md5, md5sum, 16 );
+ md5_finish( &md5, buf );
+
+ sha1_starts( &sha1 );
+ sha1_update( &sha1, ssl->session->master, 48 );
+ sha1_update( &sha1, padbuf , 40 );
+ sha1_update( &sha1, sha1sum, 20 );
+ sha1_finish( &sha1, buf + 16 );
+
+ SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 );
+
+ memset( &md5, 0, sizeof( md5_context ) );
+ memset( &sha1, 0, sizeof( sha1_context ) );
+
+ memset( padbuf, 0, sizeof( padbuf ) );
+ memset( md5sum, 0, sizeof( md5sum ) );
+ memset( sha1sum, 0, sizeof( sha1sum ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
+}
+
+static void ssl_calc_finished_tls(
+ ssl_context *ssl, unsigned char *buf, int from )
+{
+ int len = 12;
+ char *sender;
+ md5_context md5;
+ sha1_context sha1;
+ unsigned char padbuf[36];
+
+ SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) );
+
+ memcpy( &md5 , (md5_context *) ssl->ctx_checksum, sizeof(md5_context) );
+ memcpy( &sha1, (sha1_context *) ( ssl->ctx_checksum + sizeof(md5_context) ),
+ sizeof( sha1_context ) );
+
+ /*
+ * TLSv1:
+ * hash = PRF( master, finished_label,
+ * MD5( handshake ) + SHA1( handshake ) )[0..11]
+ */
+
+ SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *)
+ md5.state, sizeof( md5.state ) );
+
+ SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
+ sha1.state, sizeof( sha1.state ) );
+
+ sender = ( from == SSL_IS_CLIENT )
+ ? (char *) "client finished"
+ : (char *) "server finished";
+
+ md5_finish( &md5, padbuf );
+ sha1_finish( &sha1, padbuf + 16 );
+
+ ssl->tls_prf( ssl->session->master, 48, sender,
+ padbuf, 36, buf, len );
+
+ SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+ memset( &md5, 0, sizeof( md5_context ) );
+ memset( &sha1, 0, sizeof( sha1_context ) );
+
+ memset( padbuf, 0, sizeof( padbuf ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
+}
+
+static void ssl_calc_finished_tls_sha256(
+ ssl_context *ssl, unsigned char *buf, int from )
+{
+ int len = 12;
+ char *sender;
+ sha2_context sha2;
+ unsigned char padbuf[32];
+
+ SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) );
+
+ memcpy( &sha2 , (sha2_context *) ssl->ctx_checksum, sizeof(sha2_context) );
+
+ /*
+ * TLSv1.2:
+ * hash = PRF( master, finished_label,
+ * Hash( handshake ) )[0.11]
+ */
+
+ SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *)
+ sha2.state, sizeof( sha2.state ) );
+
+ sender = ( from == SSL_IS_CLIENT )
+ ? (char *) "client finished"
+ : (char *) "server finished";
+
+ sha2_finish( &sha2, padbuf );
+
+ ssl->tls_prf( ssl->session->master, 48, sender,
+ padbuf, 32, buf, len );
+
+ SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+ memset( &sha2, 0, sizeof( sha2_context ) );
+
+ memset( padbuf, 0, sizeof( padbuf ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
+}
+
+static void ssl_calc_finished_tls_sha384(
+ ssl_context *ssl, unsigned char *buf, int from )
+{
+ int len = 12;
+ char *sender;
+ sha4_context sha4;
+ unsigned char padbuf[48];
+
+ SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) );
+
+ memcpy( &sha4 , (sha4_context *) ssl->ctx_checksum, sizeof(sha4_context) );
+
+ /*
+ * TLSv1.2:
+ * hash = PRF( master, finished_label,
+ * Hash( handshake ) )[0.11]
+ */
+
+ SSL_DEBUG_BUF( 4, "finished sha4 state", (unsigned char *)
+ sha4.state, sizeof( sha4.state ) );
+
+ sender = ( from == SSL_IS_CLIENT )
+ ? (char *) "client finished"
+ : (char *) "server finished";
+
+ sha4_finish( &sha4, padbuf );
+
+ ssl->tls_prf( ssl->session->master, 48, sender,
+ padbuf, 48, buf, len );
+
+ SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
+
+ memset( &sha4, 0, sizeof( sha4_context ) );
+
+ memset( padbuf, 0, sizeof( padbuf ) );
+
+ SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
+}
+
+int ssl_write_finished( ssl_context *ssl )
+{
+ int ret, hash_len;
+
+ SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
+
+ ssl->calc_finished( ssl, ssl->out_msg + 4, ssl->endpoint );
+
+ // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
+ hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
+
+ ssl->out_msglen = 4 + hash_len;
+ ssl->out_msgtype = SSL_MSG_HANDSHAKE;
+ ssl->out_msg[0] = SSL_HS_FINISHED;
+
+ /*
+ * In case of session resuming, invert the client and server
+ * ChangeCipherSpec messages order.
+ */
+ if( ssl->resume != 0 )
+ {
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ ssl->state = SSL_HANDSHAKE_OVER;
+ else
+ ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+ }
+ else
+ ssl->state++;
+
+ ssl->do_crypt = 1;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
+
+ return( 0 );
+}
+
+int ssl_parse_finished( ssl_context *ssl )
+{
+ int ret;
+ unsigned int hash_len;
+ unsigned char buf[36];
+
+ SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
+
+ ssl->calc_finished( ssl, buf, ssl->endpoint ^ 1 );
+
+ ssl->do_crypt = 1;
+
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ // TODO TLS/1.2 Hash length is determined by cipher suite (Page 63)
+ hash_len = ( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ? 36 : 12;
+
+ if( ssl->in_msg[0] != SSL_HS_FINISHED ||
+ ssl->in_hslen != 4 + hash_len )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
+ }
+
+ if( memcmp( ssl->in_msg + 4, buf, hash_len ) != 0 )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
+ return( POLARSSL_ERR_SSL_BAD_HS_FINISHED );
+ }
+
+ if( ssl->resume != 0 )
+ {
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ ssl->state = SSL_CLIENT_CHANGE_CIPHER_SPEC;
+
+ if( ssl->endpoint == SSL_IS_SERVER )
+ ssl->state = SSL_HANDSHAKE_OVER;
+ }
+ else
+ ssl->state++;
+
+ SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
+
+ return( 0 );
+}
+
+/*
+ * Initialize an SSL context
+ */
+int ssl_init( ssl_context *ssl )
+{
+ int len = SSL_BUFFER_LEN;
+
+ memset( ssl, 0, sizeof( ssl_context ) );
+
+ ssl->in_ctr = (unsigned char *) malloc( len );
+ ssl->in_hdr = ssl->in_ctr + 8;
+ ssl->in_msg = ssl->in_ctr + 13;
+
+ if( ssl->in_ctr == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ ssl->out_ctr = (unsigned char *) malloc( len );
+ ssl->out_hdr = ssl->out_ctr + 8;
+ ssl->out_msg = ssl->out_ctr + 13;
+
+ if( ssl->out_ctr == NULL )
+ {
+ SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
+ free( ssl-> in_ctr );
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+ }
+
+ memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN );
+ memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+
+ ssl->hostname = NULL;
+ ssl->hostname_len = 0;
+
+ ssl->update_checksum = ssl_update_checksum_start;
+
+ return( 0 );
+}
+
+/*
+ * Reset an initialized and used SSL context for re-use while retaining
+ * all application-set variables, function pointers and data.
+ */
+void ssl_session_reset( ssl_context *ssl )
+{
+ ssl->state = SSL_HELLO_REQUEST;
+
+ ssl->in_offt = NULL;
+
+ ssl->in_msgtype = 0;
+ ssl->in_msglen = 0;
+ ssl->in_left = 0;
+
+ ssl->in_hslen = 0;
+ ssl->nb_zero = 0;
+
+ ssl->out_msgtype = 0;
+ ssl->out_msglen = 0;
+ ssl->out_left = 0;
+
+ ssl->do_crypt = 0;
+ ssl->pmslen = 0;
+ ssl->keylen = 0;
+ ssl->minlen = 0;
+ ssl->ivlen = 0;
+ ssl->maclen = 0;
+
+ memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+ memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+ memset( ssl->randbytes, 0, 64 );
+ memset( ssl->premaster, 0, 256 );
+ memset( ssl->iv_enc, 0, 16 );
+ memset( ssl->iv_dec, 0, 16 );
+ memset( ssl->mac_enc, 0, 32 );
+ memset( ssl->mac_dec, 0, 32 );
+ memset( ssl->ctx_enc, 0, 128 );
+ memset( ssl->ctx_dec, 0, 128 );
+
+ ssl->update_checksum = ssl_update_checksum_start;
+}
+
+/*
+ * SSL set accessors
+ */
+void ssl_set_endpoint( ssl_context *ssl, int endpoint )
+{
+ ssl->endpoint = endpoint;
+}
+
+void ssl_set_authmode( ssl_context *ssl, int authmode )
+{
+ ssl->authmode = authmode;
+}
+
+void ssl_set_verify( ssl_context *ssl,
+ int (*f_vrfy)(void *, x509_cert *, int, int),
+ void *p_vrfy )
+{
+ ssl->f_vrfy = f_vrfy;
+ ssl->p_vrfy = p_vrfy;
+}
+
+void ssl_set_rng( ssl_context *ssl,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ ssl->f_rng = f_rng;
+ ssl->p_rng = p_rng;
+}
+
+void ssl_set_dbg( ssl_context *ssl,
+ void (*f_dbg)(void *, int, const char *),
+ void *p_dbg )
+{
+ ssl->f_dbg = f_dbg;
+ ssl->p_dbg = p_dbg;
+}
+
+void ssl_set_bio( ssl_context *ssl,
+ int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
+ int (*f_send)(void *, const unsigned char *, size_t), void *p_send )
+{
+ ssl->f_recv = f_recv;
+ ssl->f_send = f_send;
+ ssl->p_recv = p_recv;
+ ssl->p_send = p_send;
+}
+
+void ssl_set_scb( ssl_context *ssl,
+ int (*s_get)(ssl_context *),
+ int (*s_set)(ssl_context *) )
+{
+ ssl->s_get = s_get;
+ ssl->s_set = s_set;
+}
+
+void ssl_set_session( ssl_context *ssl, int resume, int timeout,
+ ssl_session *session )
+{
+ ssl->resume = resume;
+ ssl->timeout = timeout;
+ ssl->session = session;
+}
+
+void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites )
+{
+ ssl->ciphersuites = ciphersuites;
+}
+
+void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain,
+ x509_crl *ca_crl, const char *peer_cn )
+{
+ ssl->ca_chain = ca_chain;
+ ssl->ca_crl = ca_crl;
+ ssl->peer_cn = peer_cn;
+}
+
+void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
+ rsa_context *rsa_key )
+{
+ ssl->own_cert = own_cert;
+ ssl->rsa_key = rsa_key;
+}
+
+#if defined(POLARSSL_PKCS11_C)
+void ssl_set_own_cert_pkcs11( ssl_context *ssl, x509_cert *own_cert,
+ pkcs11_context *pkcs11_key )
+{
+ ssl->own_cert = own_cert;
+ ssl->pkcs11_key = pkcs11_key;
+}
+#endif
+
+int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G )
+{
+ int ret;
+
+ if( ( ret = mpi_read_string( &ssl->dhm_ctx.P, 16, dhm_P ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+ return( ret );
+ }
+
+ if( ( ret = mpi_read_string( &ssl->dhm_ctx.G, 16, dhm_G ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_read_string", ret );
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx )
+{
+ int ret;
+
+ if( ( ret = mpi_copy(&ssl->dhm_ctx.P, &dhm_ctx->P) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_copy", ret );
+ return( ret );
+ }
+
+ if( ( ret = mpi_copy(&ssl->dhm_ctx.G, &dhm_ctx->G) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_copy", ret );
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+int ssl_set_hostname( ssl_context *ssl, const char *hostname )
+{
+ if( hostname == NULL )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl->hostname_len = strlen( hostname );
+ ssl->hostname = (unsigned char *) malloc( ssl->hostname_len + 1 );
+
+ if( ssl->hostname == NULL )
+ return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+
+ memcpy( ssl->hostname, (unsigned char *) hostname,
+ ssl->hostname_len );
+
+ ssl->hostname[ssl->hostname_len] = '\0';
+
+ return( 0 );
+}
+
+void ssl_set_max_version( ssl_context *ssl, int major, int minor )
+{
+ ssl->max_major_ver = major;
+ ssl->max_minor_ver = minor;
+}
+
+/*
+ * SSL get accessors
+ */
+size_t ssl_get_bytes_avail( const ssl_context *ssl )
+{
+ return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
+}
+
+int ssl_get_verify_result( const ssl_context *ssl )
+{
+ return( ssl->verify_result );
+}
+
+const char *ssl_get_ciphersuite_name( const int ciphersuite_id )
+{
+ switch( ciphersuite_id )
+ {
+#if defined(POLARSSL_ARC4_C)
+ case SSL_RSA_RC4_128_MD5:
+ return( "SSL-RSA-RC4-128-MD5" );
+
+ case SSL_RSA_RC4_128_SHA:
+ return( "SSL-RSA-RC4-128-SHA" );
+#endif
+
+#if defined(POLARSSL_DES_C)
+ case SSL_RSA_DES_168_SHA:
+ return( "SSL-RSA-DES-168-SHA" );
+
+ case SSL_EDH_RSA_DES_168_SHA:
+ return( "SSL-EDH-RSA-DES-168-SHA" );
+#endif
+
+#if defined(POLARSSL_AES_C)
+ case SSL_RSA_AES_128_SHA:
+ return( "SSL-RSA-AES-128-SHA" );
+
+ case SSL_EDH_RSA_AES_128_SHA:
+ return( "SSL-EDH-RSA-AES-128-SHA" );
+
+ case SSL_RSA_AES_256_SHA:
+ return( "SSL-RSA-AES-256-SHA" );
+
+ case SSL_EDH_RSA_AES_256_SHA:
+ return( "SSL-EDH-RSA-AES-256-SHA" );
+
+#if defined(POLARSSL_SHA2_C)
+ case SSL_RSA_AES_128_SHA256:
+ return( "SSL-RSA-AES-128-SHA256" );
+
+ case SSL_EDH_RSA_AES_128_SHA256:
+ return( "SSL-EDH-RSA-AES-128-SHA256" );
+
+ case SSL_RSA_AES_256_SHA256:
+ return( "SSL-RSA-AES-256-SHA256" );
+
+ case SSL_EDH_RSA_AES_256_SHA256:
+ return( "SSL-EDH-RSA-AES-256-SHA256" );
+#endif
+
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ case SSL_RSA_AES_128_GCM_SHA256:
+ return( "SSL-RSA-AES-128-GCM-SHA256" );
+
+ case SSL_EDH_RSA_AES_128_GCM_SHA256:
+ return( "SSL-EDH-RSA-AES-128-GCM-SHA256" );
+#endif
+
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
+ case SSL_RSA_AES_256_GCM_SHA384:
+ return( "SSL-RSA-AES-256-GCM-SHA384" );
+
+ case SSL_EDH_RSA_AES_256_GCM_SHA384:
+ return( "SSL-EDH-RSA-AES-256-GCM-SHA384" );
+#endif
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+ case SSL_RSA_CAMELLIA_128_SHA:
+ return( "SSL-RSA-CAMELLIA-128-SHA" );
+
+ case SSL_EDH_RSA_CAMELLIA_128_SHA:
+ return( "SSL-EDH-RSA-CAMELLIA-128-SHA" );
+
+ case SSL_RSA_CAMELLIA_256_SHA:
+ return( "SSL-RSA-CAMELLIA-256-SHA" );
+
+ case SSL_EDH_RSA_CAMELLIA_256_SHA:
+ return( "SSL-EDH-RSA-CAMELLIA-256-SHA" );
+
+#if defined(POLARSSL_SHA2_C)
+ case SSL_RSA_CAMELLIA_128_SHA256:
+ return( "SSL-RSA-CAMELLIA-128-SHA256" );
+
+ case SSL_EDH_RSA_CAMELLIA_128_SHA256:
+ return( "SSL-EDH-RSA-CAMELLIA-128-SHA256" );
+
+ case SSL_RSA_CAMELLIA_256_SHA256:
+ return( "SSL-RSA-CAMELLIA-256-SHA256" );
+
+ case SSL_EDH_RSA_CAMELLIA_256_SHA256:
+ return( "SSL-EDH-RSA-CAMELLIA-256-SHA256" );
+#endif
+#endif
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ case SSL_RSA_NULL_MD5:
+ return( "SSL-RSA-NULL-MD5" );
+ case SSL_RSA_NULL_SHA:
+ return( "SSL-RSA-NULL-SHA" );
+ case SSL_RSA_NULL_SHA256:
+ return( "SSL-RSA-NULL-SHA256" );
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#if defined(POLARSSL_DES_C)
+ case SSL_RSA_DES_SHA:
+ return( "SSL-RSA-DES-SHA" );
+ case SSL_EDH_RSA_DES_SHA:
+ return( "SSL-EDH-RSA-DES-SHA" );
+#endif
+#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+ default:
+ break;
+ }
+
+ return( "unknown" );
+}
+
+int ssl_get_ciphersuite_id( const char *ciphersuite_name )
+{
+#if defined(POLARSSL_ARC4_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-RC4-128-MD5"))
+ return( SSL_RSA_RC4_128_MD5 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-RC4-128-SHA"))
+ return( SSL_RSA_RC4_128_SHA );
+#endif
+
+#if defined(POLARSSL_DES_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-DES-168-SHA"))
+ return( SSL_RSA_DES_168_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-DES-168-SHA"))
+ return( SSL_EDH_RSA_DES_168_SHA );
+#endif
+
+#if defined(POLARSSL_AES_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-SHA"))
+ return( SSL_RSA_AES_128_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-SHA"))
+ return( SSL_EDH_RSA_AES_128_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-SHA"))
+ return( SSL_RSA_AES_256_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-SHA"))
+ return( SSL_EDH_RSA_AES_256_SHA );
+
+#if defined(POLARSSL_SHA2_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-SHA256"))
+ return( SSL_RSA_AES_128_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-SHA256"))
+ return( SSL_EDH_RSA_AES_128_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-SHA256"))
+ return( SSL_RSA_AES_256_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-SHA256"))
+ return( SSL_EDH_RSA_AES_256_SHA256 );
+#endif
+
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-GCM-SHA256"))
+ return( SSL_RSA_AES_128_GCM_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-GCM-SHA256"))
+ return( SSL_EDH_RSA_AES_128_GCM_SHA256 );
+#endif
+
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-GCM-SHA384"))
+ return( SSL_RSA_AES_256_GCM_SHA384 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-GCM-SHA384"))
+ return( SSL_EDH_RSA_AES_256_GCM_SHA384 );
+#endif
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-128-SHA"))
+ return( SSL_RSA_CAMELLIA_128_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-128-SHA"))
+ return( SSL_EDH_RSA_CAMELLIA_128_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-256-SHA"))
+ return( SSL_RSA_CAMELLIA_256_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-256-SHA"))
+ return( SSL_EDH_RSA_CAMELLIA_256_SHA );
+
+#if defined(POLARSSL_SHA2_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-128-SHA256"))
+ return( SSL_RSA_CAMELLIA_128_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-128-SHA256"))
+ return( SSL_EDH_RSA_CAMELLIA_128_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-CAMELLIA-256-SHA256"))
+ return( SSL_RSA_CAMELLIA_256_SHA256 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-CAMELLIA-256-SHA256"))
+ return( SSL_EDH_RSA_CAMELLIA_256_SHA256 );
+#endif
+#endif
+
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-MD5"))
+ return( SSL_RSA_NULL_MD5 );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-SHA"))
+ return( SSL_RSA_NULL_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-NULL-SHA256"))
+ return( SSL_RSA_NULL_SHA256 );
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+#if defined(POLARSSL_DES_C)
+ if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-DES-SHA"))
+ return( SSL_RSA_DES_SHA );
+ if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-DES-SHA"))
+ return( SSL_EDH_RSA_DES_SHA );
+#endif
+#endif /* defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES) */
+
+ return( 0 );
+}
+
+const char *ssl_get_ciphersuite( const ssl_context *ssl )
+{
+ return ssl_get_ciphersuite_name( ssl->session->ciphersuite );
+}
+
+const char *ssl_get_version( const ssl_context *ssl )
+{
+ switch( ssl->minor_ver )
+ {
+ case SSL_MINOR_VERSION_0:
+ return( "SSLv3.0" );
+
+ case SSL_MINOR_VERSION_1:
+ return( "TLSv1.0" );
+
+ case SSL_MINOR_VERSION_2:
+ return( "TLSv1.1" );
+
+ case SSL_MINOR_VERSION_3:
+ return( "TLSv1.2" );
+
+ default:
+ break;
+ }
+ return( "unknown" );
+}
+
+int ssl_default_ciphersuites[] =
+{
+#if defined(POLARSSL_DHM_C)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+ SSL_EDH_RSA_AES_256_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
+ SSL_EDH_RSA_AES_256_GCM_SHA384,
+#endif
+ SSL_EDH_RSA_AES_256_SHA,
+#if defined(POLARSSL_SHA2_C)
+ SSL_EDH_RSA_AES_128_SHA256,
+#endif
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ SSL_EDH_RSA_AES_128_GCM_SHA256,
+#endif
+ SSL_EDH_RSA_AES_128_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+ SSL_EDH_RSA_CAMELLIA_256_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ SSL_EDH_RSA_CAMELLIA_256_SHA,
+#if defined(POLARSSL_SHA2_C)
+ SSL_EDH_RSA_CAMELLIA_128_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ SSL_EDH_RSA_CAMELLIA_128_SHA,
+#endif
+#if defined(POLARSSL_DES_C)
+ SSL_EDH_RSA_DES_168_SHA,
+#endif
+#endif
+
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+ SSL_RSA_AES_256_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C)
+ SSL_RSA_AES_256_GCM_SHA384,
+#endif /* POLARSSL_SHA2_C */
+ SSL_RSA_AES_256_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+ SSL_RSA_CAMELLIA_256_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ SSL_RSA_CAMELLIA_256_SHA,
+#endif
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA2_C)
+ SSL_RSA_AES_128_SHA256,
+#endif /* POLARSSL_SHA2_C */
+#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C)
+ SSL_RSA_AES_128_GCM_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ SSL_RSA_AES_128_SHA,
+#endif
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_SHA2_C)
+ SSL_RSA_CAMELLIA_128_SHA256,
+#endif /* POLARSSL_SHA2_C */
+ SSL_RSA_CAMELLIA_128_SHA,
+#endif
+#if defined(POLARSSL_DES_C)
+ SSL_RSA_DES_168_SHA,
+#endif
+#if defined(POLARSSL_ARC4_C)
+ SSL_RSA_RC4_128_SHA,
+ SSL_RSA_RC4_128_MD5,
+#endif
+ 0
+};
+
+/*
+ * Perform the SSL handshake
+ */
+int ssl_handshake( ssl_context *ssl )
+{
+ int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+
+ SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
+
+#if defined(POLARSSL_SSL_CLI_C)
+ if( ssl->endpoint == SSL_IS_CLIENT )
+ ret = ssl_handshake_client( ssl );
+#endif
+
+#if defined(POLARSSL_SSL_SRV_C)
+ if( ssl->endpoint == SSL_IS_SERVER )
+ ret = ssl_handshake_server( ssl );
+#endif
+
+ SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
+
+ return( ret );
+}
+
+/*
+ * Receive application data decrypted from the SSL layer
+ */
+int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
+{
+ int ret;
+ size_t n;
+
+ SSL_DEBUG_MSG( 2, ( "=> read" ) );
+
+ if( ssl->state != SSL_HANDSHAKE_OVER )
+ {
+ if( ( ret = ssl_handshake( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+ return( ret );
+ }
+ }
+
+ if( ssl->in_offt == NULL )
+ {
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_SSL_CONN_EOF )
+ return( 0 );
+
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msglen == 0 &&
+ ssl->in_msgtype == SSL_MSG_APPLICATION_DATA )
+ {
+ /*
+ * OpenSSL sends empty messages to randomize the IV
+ */
+ if( ( ret = ssl_read_record( ssl ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_SSL_CONN_EOF )
+ return( 0 );
+
+ SSL_DEBUG_RET( 1, "ssl_read_record", ret );
+ return( ret );
+ }
+ }
+
+ if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
+ {
+ SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
+ return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ ssl->in_offt = ssl->in_msg;
+ }
+
+ n = ( len < ssl->in_msglen )
+ ? len : ssl->in_msglen;
+
+ memcpy( buf, ssl->in_offt, n );
+ ssl->in_msglen -= n;
+
+ if( ssl->in_msglen == 0 )
+ /* all bytes consumed */
+ ssl->in_offt = NULL;
+ else
+ /* more data available */
+ ssl->in_offt += n;
+
+ SSL_DEBUG_MSG( 2, ( "<= read" ) );
+
+ return( (int) n );
+}
+
+/*
+ * Send application data to be encrypted by the SSL layer
+ */
+int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len )
+{
+ int ret;
+ size_t n;
+
+ SSL_DEBUG_MSG( 2, ( "=> write" ) );
+
+ if( ssl->state != SSL_HANDSHAKE_OVER )
+ {
+ if( ( ret = ssl_handshake( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_handshake", ret );
+ return( ret );
+ }
+ }
+
+ n = ( len < SSL_MAX_CONTENT_LEN )
+ ? len : SSL_MAX_CONTENT_LEN;
+
+ if( ssl->out_left != 0 )
+ {
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+ return( ret );
+ }
+ }
+ else
+ {
+ ssl->out_msglen = n;
+ ssl->out_msgtype = SSL_MSG_APPLICATION_DATA;
+ memcpy( ssl->out_msg, buf, n );
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write" ) );
+
+ return( (int) n );
+}
+
+/*
+ * Notify the peer that the connection is being closed
+ */
+int ssl_close_notify( ssl_context *ssl )
+{
+ int ret;
+
+ SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
+
+ if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_flush_output", ret );
+ return( ret );
+ }
+
+ if( ssl->state == SSL_HANDSHAKE_OVER )
+ {
+ ssl->out_msgtype = SSL_MSG_ALERT;
+ ssl->out_msglen = 2;
+ ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING;
+ ssl->out_msg[1] = SSL_ALERT_MSG_CLOSE_NOTIFY;
+
+ if( ( ret = ssl_write_record( ssl ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
+
+ return( ret );
+}
+
+/*
+ * Free an SSL context
+ */
+void ssl_free( ssl_context *ssl )
+{
+ SSL_DEBUG_MSG( 2, ( "=> free" ) );
+
+ if( ssl->peer_cert != NULL )
+ {
+ x509_free( ssl->peer_cert );
+ memset( ssl->peer_cert, 0, sizeof( x509_cert ) );
+ free( ssl->peer_cert );
+ }
+
+ if( ssl->out_ctr != NULL )
+ {
+ memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+ free( ssl->out_ctr );
+ }
+
+ if( ssl->in_ctr != NULL )
+ {
+ memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+ free( ssl->in_ctr );
+ }
+
+#if defined(POLARSSL_DHM_C)
+ dhm_free( &ssl->dhm_ctx );
+#endif
+
+ if ( ssl->hostname != NULL)
+ {
+ memset( ssl->hostname, 0, ssl->hostname_len );
+ free( ssl->hostname );
+ ssl->hostname_len = 0;
+ }
+
+ SSL_DEBUG_MSG( 2, ( "<= free" ) );
+
+ /* Actually free after last debug message */
+ memset( ssl, 0, sizeof( ssl_context ) );
+}
+
+#endif
diff --git a/polarssl/src/library/timing.c b/polarssl/src/library/timing.c
new file mode 100644
index 0000000..523dbe1
--- /dev/null
+++ b/polarssl/src/library/timing.c
@@ -0,0 +1,271 @@
+/*
+ * Portable interface to the CPU cycle counter
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_TIMING_C)
+
+#include "polarssl/timing.h"
+
+#if defined(_WIN32)
+
+#include <windows.h>
+#include <winbase.h>
+
+struct _hr_time
+{
+ LARGE_INTEGER start;
+};
+
+#else
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <time.h>
+
+struct _hr_time
+{
+ struct timeval start;
+};
+
+#endif
+
+#if defined(POLARSSL_HAVE_ASM) && \
+ (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+unsigned long hardclock( void )
+{
+ unsigned long tsc;
+ __asm rdtsc
+ __asm mov [tsc], eax
+ return( tsc );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
+
+unsigned long hardclock( void )
+{
+ unsigned long lo, hi;
+ asm( "rdtsc" : "=a" (lo), "=d" (hi) );
+ return( lo );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \
+ (defined(__amd64__) || defined(__x86_64__))
+
+unsigned long hardclock( void )
+{
+ unsigned long lo, hi;
+ asm( "rdtsc" : "=a" (lo), "=d" (hi) );
+ return( lo | (hi << 32) );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \
+ (defined(__powerpc__) || defined(__ppc__))
+
+unsigned long hardclock( void )
+{
+ unsigned long tbl, tbu0, tbu1;
+
+ do
+ {
+ asm( "mftbu %0" : "=r" (tbu0) );
+ asm( "mftb %0" : "=r" (tbl ) );
+ asm( "mftbu %0" : "=r" (tbu1) );
+ }
+ while( tbu0 != tbu1 );
+
+ return( tbl );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__sparc__)
+
+unsigned long hardclock( void )
+{
+ unsigned long tick;
+ asm( ".byte 0x83, 0x41, 0x00, 0x00" );
+ asm( "mov %%g1, %0" : "=r" (tick) );
+ return( tick );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__alpha__)
+
+unsigned long hardclock( void )
+{
+ unsigned long cc;
+ asm( "rpcc %0" : "=r" (cc) );
+ return( cc & 0xFFFFFFFF );
+}
+
+#else
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__ia64__)
+
+unsigned long hardclock( void )
+{
+ unsigned long itc;
+ asm( "mov %0 = ar.itc" : "=r" (itc) );
+ return( itc );
+}
+
+#else
+#if defined(_MSC_VER)
+
+unsigned long hardclock( void )
+{
+ LARGE_INTEGER offset;
+
+ QueryPerformanceCounter( &offset );
+
+ return (unsigned long)( offset.QuadPart );
+}
+
+#else
+
+static int hardclock_init = 0;
+static struct timeval tv_init;
+
+unsigned long hardclock( void )
+{
+ struct timeval tv_cur;
+
+ if( hardclock_init == 0 )
+ {
+ gettimeofday( &tv_init, NULL );
+ hardclock_init = 1;
+ }
+
+ gettimeofday( &tv_cur, NULL );
+ return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
+ + ( tv_cur.tv_usec - tv_init.tv_usec ) );
+}
+
+#endif /* generic */
+#endif /* WIN32 */
+#endif /* IA-64 */
+#endif /* Alpha */
+#endif /* SPARC8 */
+#endif /* PowerPC */
+#endif /* AMD64 */
+#endif /* i586+ */
+
+volatile int alarmed = 0;
+
+#if defined(_WIN32)
+
+unsigned long get_timer( struct hr_time *val, int reset )
+{
+ unsigned long delta;
+ LARGE_INTEGER offset, hfreq;
+ struct _hr_time *t = (struct _hr_time *) val;
+
+ QueryPerformanceCounter( &offset );
+ QueryPerformanceFrequency( &hfreq );
+
+ delta = (unsigned long)( ( 1000 *
+ ( offset.QuadPart - t->start.QuadPart ) ) /
+ hfreq.QuadPart );
+
+ if( reset )
+ QueryPerformanceCounter( &t->start );
+
+ return( delta );
+}
+
+DWORD WINAPI TimerProc( LPVOID uElapse )
+{
+ Sleep( (DWORD) uElapse );
+ alarmed = 1;
+ return( TRUE );
+}
+
+void set_alarm( int seconds )
+{
+ DWORD ThreadId;
+
+ alarmed = 0;
+ CloseHandle( CreateThread( NULL, 0, TimerProc,
+ (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
+}
+
+void m_sleep( int milliseconds )
+{
+ Sleep( milliseconds );
+}
+
+#else
+
+unsigned long get_timer( struct hr_time *val, int reset )
+{
+ unsigned long delta;
+ struct timeval offset;
+ struct _hr_time *t = (struct _hr_time *) val;
+
+ gettimeofday( &offset, NULL );
+
+ delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
+ + ( offset.tv_usec - t->start.tv_usec ) / 1000;
+
+ if( reset )
+ {
+ t->start.tv_sec = offset.tv_sec;
+ t->start.tv_usec = offset.tv_usec;
+ }
+
+ return( delta );
+}
+
+static void sighandler( int signum )
+{
+ alarmed = 1;
+ signal( signum, sighandler );
+}
+
+void set_alarm( int seconds )
+{
+ alarmed = 0;
+ signal( SIGALRM, sighandler );
+ alarm( seconds );
+}
+
+void m_sleep( int milliseconds )
+{
+ struct timeval tv;
+
+ tv.tv_sec = milliseconds / 1000;
+ tv.tv_usec = milliseconds * 1000;
+
+ select( 0, NULL, NULL, NULL, &tv );
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/version.c b/polarssl/src/library/version.c
new file mode 100644
index 0000000..c1080b7
--- /dev/null
+++ b/polarssl/src/library/version.c
@@ -0,0 +1,50 @@
+/*
+ * Version information
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_VERSION_C)
+
+#include "polarssl/version.h"
+#include <string.h>
+
+const char version[] = POLARSSL_VERSION_STRING;
+
+unsigned int version_get_number()
+{
+ return POLARSSL_VERSION_NUMBER;
+}
+
+void version_get_string( char *string )
+{
+ memcpy( string, POLARSSL_VERSION_STRING, sizeof( POLARSSL_VERSION_STRING ) );
+}
+
+void version_get_string_full( char *string )
+{
+ memcpy( string, POLARSSL_VERSION_STRING_FULL, sizeof( POLARSSL_VERSION_STRING_FULL ) );
+}
+
+#endif /* POLARSSL_VERSION_C */
diff --git a/polarssl/src/library/x509parse.c b/polarssl/src/library/x509parse.c
new file mode 100644
index 0000000..9d01a65
--- /dev/null
+++ b/polarssl/src/library/x509parse.c
@@ -0,0 +1,3425 @@
+/*
+ * X.509 certificate and private key decoding
+ *
+ * Copyright (C) 2006-2011, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ * The ITU-T X.509 standard defines a certificate format for PKI.
+ *
+ * http://www.ietf.org/rfc/rfc3279.txt
+ * http://www.ietf.org/rfc/rfc3280.txt
+ *
+ * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *
+ * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
+ * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_PARSE_C)
+
+#include "polarssl/x509.h"
+#include "polarssl/asn1.h"
+#include "polarssl/pem.h"
+#include "polarssl/des.h"
+#include "polarssl/md2.h"
+#include "polarssl/md4.h"
+#include "polarssl/md5.h"
+#include "polarssl/sha1.h"
+#include "polarssl/sha2.h"
+#include "polarssl/sha4.h"
+#include "polarssl/dhm.h"
+
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32)
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+/*
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ */
+static int x509_get_version( unsigned char **p,
+ const unsigned char *end,
+ int *ver )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ {
+ *ver = 0;
+ return( 0 );
+ }
+
+ return( ret );
+ }
+
+ end = *p + len;
+
+ if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_VERSION +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+/*
+ * Version ::= INTEGER { v1(0), v2(1) }
+ */
+static int x509_crl_get_version( unsigned char **p,
+ const unsigned char *end,
+ int *ver )
+{
+ int ret;
+
+ if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ {
+ *ver = 0;
+ return( 0 );
+ }
+
+ return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret );
+ }
+
+ return( 0 );
+}
+
+/*
+ * CertificateSerialNumber ::= INTEGER
+ */
+static int x509_get_serial( unsigned char **p,
+ const unsigned char *end,
+ x509_buf *serial )
+{
+ int ret;
+
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
+ **p != ASN1_INTEGER )
+ return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL +
+ POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+ serial->tag = *(*p)++;
+
+ if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL + ret );
+
+ serial->p = *p;
+ *p += serial->len;
+
+ return( 0 );
+}
+
+/*
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ */
+static int x509_get_alg( unsigned char **p,
+ const unsigned char *end,
+ x509_buf *alg )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
+
+ end = *p + len;
+ alg->tag = **p;
+
+ if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
+
+ alg->p = *p;
+ *p += alg->len;
+
+ if( *p == end )
+ return( 0 );
+
+ /*
+ * assume the algorithm parameters must be NULL
+ */
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret );
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_ALG +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+/*
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ *
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ */
+static int x509_get_attr_type_value( unsigned char **p,
+ const unsigned char *end,
+ x509_name *cur )
+{
+ int ret;
+ size_t len;
+ x509_buf *oid;
+ x509_buf *val;
+
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
+
+ oid = &cur->oid;
+ oid->tag = **p;
+
+ if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
+
+ oid->p = *p;
+ *p += oid->len;
+
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
+ **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
+ **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
+ return( POLARSSL_ERR_X509_CERT_INVALID_NAME +
+ POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+ val = &cur->val;
+ val->tag = *(*p)++;
+
+ if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
+
+ val->p = *p;
+ *p += val->len;
+
+ cur->next = NULL;
+
+ return( 0 );
+}
+
+/*
+ * RelativeDistinguishedName ::=
+ * SET OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ *
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ */
+static int x509_get_name( unsigned char **p,
+ const unsigned char *end,
+ x509_name *cur )
+{
+ int ret;
+ size_t len;
+ const unsigned char *end2;
+ x509_name *use;
+
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_NAME + ret );
+
+ end2 = end;
+ end = *p + len;
+ use = cur;
+
+ do
+ {
+ if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
+ return( ret );
+
+ if( *p != end )
+ {
+ use->next = (x509_name *) malloc(
+ sizeof( x509_name ) );
+
+ if( use->next == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ memset( use->next, 0, sizeof( x509_name ) );
+
+ use = use->next;
+ }
+ }
+ while( *p != end );
+
+ /*
+ * recurse until end of SEQUENCE is reached
+ */
+ if( *p == end2 )
+ return( 0 );
+
+ cur->next = (x509_name *) malloc(
+ sizeof( x509_name ) );
+
+ if( cur->next == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ return( x509_get_name( p, end2, cur->next ) );
+}
+
+/*
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ */
+static int x509_get_time( unsigned char **p,
+ const unsigned char *end,
+ x509_time *time )
+{
+ int ret;
+ size_t len;
+ char date[64];
+ unsigned char tag;
+
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ tag = **p;
+
+ if ( tag == ASN1_UTC_TIME )
+ {
+ (*p)++;
+ ret = asn1_get_len( p, end, &len );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
+
+ memset( date, 0, sizeof( date ) );
+ memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
+ len : sizeof( date ) - 1 );
+
+ if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
+ &time->year, &time->mon, &time->day,
+ &time->hour, &time->min, &time->sec ) < 5 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
+
+ time->year += 100 * ( time->year < 50 );
+ time->year += 1900;
+
+ *p += len;
+
+ return( 0 );
+ }
+ else if ( tag == ASN1_GENERALIZED_TIME )
+ {
+ (*p)++;
+ ret = asn1_get_len( p, end, &len );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
+
+ memset( date, 0, sizeof( date ) );
+ memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
+ len : sizeof( date ) - 1 );
+
+ if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
+ &time->year, &time->mon, &time->day,
+ &time->hour, &time->min, &time->sec ) < 5 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
+
+ *p += len;
+
+ return( 0 );
+ }
+ else
+ return( POLARSSL_ERR_X509_CERT_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+}
+
+
+/*
+ * Validity ::= SEQUENCE {
+ * notBefore Time,
+ * notAfter Time }
+ */
+static int x509_get_dates( unsigned char **p,
+ const unsigned char *end,
+ x509_time *from,
+ x509_time *to )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_DATE + ret );
+
+ end = *p + len;
+
+ if( ( ret = x509_get_time( p, end, from ) ) != 0 )
+ return( ret );
+
+ if( ( ret = x509_get_time( p, end, to ) ) != 0 )
+ return( ret );
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_DATE +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+/*
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ */
+static int x509_get_pubkey( unsigned char **p,
+ const unsigned char *end,
+ x509_buf *pk_alg_oid,
+ mpi *N, mpi *E )
+{
+ int ret, can_handle;
+ size_t len;
+ unsigned char *end2;
+
+ if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
+ return( ret );
+
+ /*
+ * only RSA public keys handled at this time
+ */
+ can_handle = 0;
+
+ if( pk_alg_oid->len == 9 &&
+ memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) == 0 )
+ can_handle = 1;
+
+ if( pk_alg_oid->len == 9 &&
+ memcmp( pk_alg_oid->p, OID_PKCS1, 8 ) == 0 )
+ {
+ if( pk_alg_oid->p[8] >= 2 && pk_alg_oid->p[8] <= 5 )
+ can_handle = 1;
+
+ if ( pk_alg_oid->p[8] >= 11 && pk_alg_oid->p[8] <= 14 )
+ can_handle = 1;
+ }
+
+ if( pk_alg_oid->len == 5 &&
+ memcmp( pk_alg_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 )
+ can_handle = 1;
+
+ if( can_handle == 0 )
+ return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
+
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ end2 = *p + len;
+
+ if( *(*p)++ != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
+
+ /*
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ */
+ if( ( ret = asn1_get_tag( p, end2, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
+
+ if( *p + len != end2 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
+ ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret );
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+static int x509_get_sig( unsigned char **p,
+ const unsigned char *end,
+ x509_buf *sig )
+{
+ int ret;
+ size_t len;
+
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ sig->tag = **p;
+
+ if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE + ret );
+
+
+ if( --len < 1 || *(*p)++ != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
+
+ sig->len = len;
+ sig->p = *p;
+
+ *p += len;
+
+ return( 0 );
+}
+
+/*
+ * X.509 v2/v3 unique identifier (not parsed)
+ */
+static int x509_get_uid( unsigned char **p,
+ const unsigned char *end,
+ x509_buf *uid, int n )
+{
+ int ret;
+
+ if( *p == end )
+ return( 0 );
+
+ uid->tag = **p;
+
+ if( ( ret = asn1_get_tag( p, end, &uid->len,
+ ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ return( 0 );
+
+ return( ret );
+ }
+
+ uid->p = *p;
+ *p += uid->len;
+
+ return( 0 );
+}
+
+/*
+ * X.509 Extensions (No parsing of extensions, pointer should
+ * be either manually updated or extensions should be parsed!
+ */
+static int x509_get_ext( unsigned char **p,
+ const unsigned char *end,
+ x509_buf *ext, int tag )
+{
+ int ret;
+ size_t len;
+
+ if( *p == end )
+ return( 0 );
+
+ ext->tag = **p;
+
+ if( ( ret = asn1_get_tag( p, end, &ext->len,
+ ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
+ return( ret );
+
+ ext->p = *p;
+ end = *p + ext->len;
+
+ /*
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ */
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ if( end != *p + len )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+/*
+ * X.509 CRL v2 extensions (no extensions parsed yet.)
+ */
+static int x509_get_crl_ext( unsigned char **p,
+ const unsigned char *end,
+ x509_buf *ext )
+{
+ int ret;
+ size_t len = 0;
+
+ /* Get explicit tag */
+ if( ( ret = x509_get_ext( p, end, ext, 0) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ return( 0 );
+
+ return( ret );
+ }
+
+ while( *p < end )
+ {
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ *p += len;
+ }
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+/*
+ * X.509 CRL v2 entry extensions (no extensions parsed yet.)
+ */
+static int x509_get_crl_entry_ext( unsigned char **p,
+ const unsigned char *end,
+ x509_buf *ext )
+{
+ int ret;
+ size_t len = 0;
+
+ /* OPTIONAL */
+ if (end <= *p)
+ return( 0 );
+
+ ext->tag = **p;
+ ext->p = *p;
+
+ /*
+ * Get CRL-entry extension sequence header
+ * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2
+ */
+ if( ( ret = asn1_get_tag( p, end, &ext->len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ {
+ ext->p = NULL;
+ return( 0 );
+ }
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+ }
+
+ end = *p + ext->len;
+
+ if( end != *p + ext->len )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ while( *p < end )
+ {
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ *p += len;
+ }
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+static int x509_get_basic_constraints( unsigned char **p,
+ const unsigned char *end,
+ int *ca_istrue,
+ int *max_pathlen )
+{
+ int ret;
+ size_t len;
+
+ /*
+ * BasicConstraints ::= SEQUENCE {
+ * cA BOOLEAN DEFAULT FALSE,
+ * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+ */
+ *ca_istrue = 0; /* DEFAULT FALSE */
+ *max_pathlen = 0; /* endless */
+
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ if( *p == end )
+ return 0;
+
+ if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ ret = asn1_get_int( p, end, ca_istrue );
+
+ if( ret != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ if( *ca_istrue != 0 )
+ *ca_istrue = 1;
+ }
+
+ if( *p == end )
+ return 0;
+
+ if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ (*max_pathlen)++;
+
+ return 0;
+}
+
+static int x509_get_ns_cert_type( unsigned char **p,
+ const unsigned char *end,
+ unsigned char *ns_cert_type)
+{
+ int ret;
+ x509_bitstring bs = { 0, 0, NULL };
+
+ if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ if( bs.len != 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+ /* Get actual bitstring */
+ *ns_cert_type = *bs.p;
+ return 0;
+}
+
+static int x509_get_key_usage( unsigned char **p,
+ const unsigned char *end,
+ unsigned char *key_usage)
+{
+ int ret;
+ x509_bitstring bs = { 0, 0, NULL };
+
+ if( ( ret = asn1_get_bitstring( p, end, &bs ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ if( bs.len > 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+ /* Get actual bitstring */
+ *key_usage = *bs.p;
+ return 0;
+}
+
+/*
+ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ */
+static int x509_get_ext_key_usage( unsigned char **p,
+ const unsigned char *end,
+ x509_sequence *ext_key_usage)
+{
+ int ret;
+
+ if( ( ret = asn1_get_sequence_of( p, end, ext_key_usage, ASN1_OID ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ /* Sequence length must be >= 1 */
+ if( ext_key_usage->buf.p == NULL )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_INVALID_LENGTH );
+
+ return 0;
+}
+
+/*
+ * SubjectAltName ::= GeneralNames
+ *
+ * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER }
+ *
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= SEQUENCE {
+ * nameAssigner [0] DirectoryString OPTIONAL,
+ * partyName [1] DirectoryString }
+ *
+ * NOTE: PolarSSL only parses and uses dNSName at this point.
+ */
+static int x509_get_subject_alt_name( unsigned char **p,
+ const unsigned char *end,
+ x509_sequence *subject_alt_name )
+{
+ int ret;
+ size_t len, tag_len;
+ asn1_buf *buf;
+ unsigned char tag;
+ asn1_sequence *cur = subject_alt_name;
+
+ /* Get main sequence tag */
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ if( *p + len != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ while( *p < end )
+ {
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ tag = **p;
+ (*p)++;
+ if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+ if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) )
+ {
+ *p += tag_len;
+ continue;
+ }
+
+ buf = &(cur->buf);
+ buf->tag = tag;
+ buf->p = *p;
+ buf->len = tag_len;
+ *p += buf->len;
+
+ /* Allocate and assign next pointer */
+ if (*p < end)
+ {
+ cur->next = (asn1_sequence *) malloc(
+ sizeof( asn1_sequence ) );
+
+ if( cur->next == NULL )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_MALLOC_FAILED );
+
+ cur = cur->next;
+ }
+ }
+
+ /* Set final sequence entry's next pointer to NULL */
+ cur->next = NULL;
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+/*
+ * X.509 v3 extensions
+ *
+ * TODO: Perform all of the basic constraints tests required by the RFC
+ * TODO: Set values for undetected extensions to a sane default?
+ *
+ */
+static int x509_get_crt_ext( unsigned char **p,
+ const unsigned char *end,
+ x509_cert *crt )
+{
+ int ret;
+ size_t len;
+ unsigned char *end_ext_data, *end_ext_octet;
+
+ if( ( ret = x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ return( 0 );
+
+ return( ret );
+ }
+
+ while( *p < end )
+ {
+ /*
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ */
+ x509_buf extn_oid = {0, 0, NULL};
+ int is_critical = 0; /* DEFAULT FALSE */
+
+ if( ( ret = asn1_get_tag( p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ end_ext_data = *p + len;
+
+ /* Get extension ID */
+ extn_oid.tag = **p;
+
+ if( ( ret = asn1_get_tag( p, end, &extn_oid.len, ASN1_OID ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ extn_oid.p = *p;
+ *p += extn_oid.len;
+
+ if( ( end - *p ) < 1 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+ /* Get optional critical */
+ if( ( ret = asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
+ ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ /* Data should be octet string type */
+ if( ( ret = asn1_get_tag( p, end_ext_data, &len,
+ ASN1_OCTET_STRING ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS + ret );
+
+ end_ext_octet = *p + len;
+
+ if( end_ext_octet != end_ext_data )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ /*
+ * Detect supported extensions
+ */
+ if( ( OID_SIZE( OID_BASIC_CONSTRAINTS ) == extn_oid.len ) &&
+ memcmp( extn_oid.p, OID_BASIC_CONSTRAINTS, extn_oid.len ) == 0 )
+ {
+ /* Parse basic constraints */
+ if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
+ &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
+ return ( ret );
+ crt->ext_types |= EXT_BASIC_CONSTRAINTS;
+ }
+ else if( ( OID_SIZE( OID_NS_CERT_TYPE ) == extn_oid.len ) &&
+ memcmp( extn_oid.p, OID_NS_CERT_TYPE, extn_oid.len ) == 0 )
+ {
+ /* Parse netscape certificate type */
+ if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
+ &crt->ns_cert_type ) ) != 0 )
+ return ( ret );
+ crt->ext_types |= EXT_NS_CERT_TYPE;
+ }
+ else if( ( OID_SIZE( OID_KEY_USAGE ) == extn_oid.len ) &&
+ memcmp( extn_oid.p, OID_KEY_USAGE, extn_oid.len ) == 0 )
+ {
+ /* Parse key usage */
+ if( ( ret = x509_get_key_usage( p, end_ext_octet,
+ &crt->key_usage ) ) != 0 )
+ return ( ret );
+ crt->ext_types |= EXT_KEY_USAGE;
+ }
+ else if( ( OID_SIZE( OID_EXTENDED_KEY_USAGE ) == extn_oid.len ) &&
+ memcmp( extn_oid.p, OID_EXTENDED_KEY_USAGE, extn_oid.len ) == 0 )
+ {
+ /* Parse extended key usage */
+ if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
+ &crt->ext_key_usage ) ) != 0 )
+ return ( ret );
+ crt->ext_types |= EXT_EXTENDED_KEY_USAGE;
+ }
+ else if( ( OID_SIZE( OID_SUBJECT_ALT_NAME ) == extn_oid.len ) &&
+ memcmp( extn_oid.p, OID_SUBJECT_ALT_NAME, extn_oid.len ) == 0 )
+ {
+ /* Parse extended key usage */
+ if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
+ &crt->subject_alt_names ) ) != 0 )
+ return ( ret );
+ crt->ext_types |= EXT_SUBJECT_ALT_NAME;
+ }
+ else
+ {
+ /* No parser found, skip extension */
+ *p = end_ext_octet;
+
+#if !defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+ if( is_critical )
+ {
+ /* Data is marked as critical: fail */
+ return ( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+ }
+#endif
+ }
+ }
+
+ if( *p != end )
+ return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+/*
+ * X.509 CRL Entries
+ */
+static int x509_get_entries( unsigned char **p,
+ const unsigned char *end,
+ x509_crl_entry *entry )
+{
+ int ret;
+ size_t entry_len;
+ x509_crl_entry *cur_entry = entry;
+
+ if( *p == end )
+ return( 0 );
+
+ if( ( ret = asn1_get_tag( p, end, &entry_len,
+ ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
+ {
+ if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ return( 0 );
+
+ return( ret );
+ }
+
+ end = *p + entry_len;
+
+ while( *p < end )
+ {
+ size_t len2;
+ const unsigned char *end2;
+
+ if( ( ret = asn1_get_tag( p, end, &len2,
+ ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ cur_entry->raw.tag = **p;
+ cur_entry->raw.p = *p;
+ cur_entry->raw.len = len2;
+ end2 = *p + len2;
+
+ if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
+ return( ret );
+
+ if( ( ret = x509_get_time( p, end2, &cur_entry->revocation_date ) ) != 0 )
+ return( ret );
+
+ if( ( ret = x509_get_crl_entry_ext( p, end2, &cur_entry->entry_ext ) ) != 0 )
+ return( ret );
+
+ if ( *p < end )
+ {
+ cur_entry->next = malloc( sizeof( x509_crl_entry ) );
+
+ if( cur_entry->next == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ cur_entry = cur_entry->next;
+ memset( cur_entry, 0, sizeof( x509_crl_entry ) );
+ }
+ }
+
+ return( 0 );
+}
+
+static int x509_get_sig_alg( const x509_buf *sig_oid, int *sig_alg )
+{
+ if( sig_oid->len == 9 &&
+ memcmp( sig_oid->p, OID_PKCS1, 8 ) == 0 )
+ {
+ if( sig_oid->p[8] >= 2 && sig_oid->p[8] <= 5 )
+ {
+ *sig_alg = sig_oid->p[8];
+ return( 0 );
+ }
+
+ if ( sig_oid->p[8] >= 11 && sig_oid->p[8] <= 14 )
+ {
+ *sig_alg = sig_oid->p[8];
+ return( 0 );
+ }
+
+ return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
+ }
+ if( sig_oid->len == 5 &&
+ memcmp( sig_oid->p, OID_RSA_SHA_OBS, 5 ) == 0 )
+ {
+ *sig_alg = SIG_RSA_SHA1;
+ return( 0 );
+ }
+
+ return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
+}
+
+/*
+ * Parse and fill a single X.509 certificate in DER format
+ */
+int x509parse_crt_der( x509_cert *crt, const unsigned char *buf, size_t buflen )
+{
+ int ret;
+ size_t len;
+ unsigned char *p, *end;
+
+ /*
+ * Check for valid input
+ */
+ if( crt == NULL || buf == NULL )
+ return( POLARSSL_ERR_X509_INVALID_INPUT );
+
+ p = (unsigned char *) malloc( len = buflen );
+
+ if( p == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ memcpy( p, buf, buflen );
+
+ buflen = 0;
+
+ crt->raw.p = p;
+ crt->raw.len = len;
+ end = p + len;
+
+ /*
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ */
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
+ }
+
+ if( len != (size_t) ( end - p ) )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+ /*
+ * TBSCertificate ::= SEQUENCE {
+ */
+ crt->tbs.p = p;
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+ crt->tbs.len = end - crt->tbs.p;
+
+ /*
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ *
+ * CertificateSerialNumber ::= INTEGER
+ *
+ * signature AlgorithmIdentifier
+ */
+ if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
+ ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
+ ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ crt->version++;
+
+ if( crt->version > 3 )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
+ }
+
+ if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_alg ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ /*
+ * issuer Name
+ */
+ crt->issuer_raw.p = p;
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ crt->issuer_raw.len = p - crt->issuer_raw.p;
+
+ /*
+ * Validity ::= SEQUENCE {
+ * notBefore Time,
+ * notAfter Time }
+ *
+ */
+ if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
+ &crt->valid_to ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ /*
+ * subject Name
+ */
+ crt->subject_raw.p = p;
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ crt->subject_raw.len = p - crt->subject_raw.p;
+
+ /*
+ * SubjectPublicKeyInfo ::= SEQUENCE
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ */
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
+ &crt->rsa.N, &crt->rsa.E ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ crt->rsa.len = mpi_size( &crt->rsa.N );
+
+ /*
+ * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ * -- If present, version shall be v2 or v3
+ * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ * -- If present, version shall be v2 or v3
+ * extensions [3] EXPLICIT Extensions OPTIONAL
+ * -- If present, version shall be v3
+ */
+ if( crt->version == 2 || crt->version == 3 )
+ {
+ ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
+ if( ret != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+ }
+
+ if( crt->version == 2 || crt->version == 3 )
+ {
+ ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
+ if( ret != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+ }
+
+ if( crt->version == 3 )
+ {
+ ret = x509_get_crt_ext( &p, end, crt);
+ if( ret != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+ }
+
+ if( p != end )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+ end = crt->raw.p + crt->raw.len;
+
+ /*
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING
+ */
+ if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
+ }
+
+ if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
+ {
+ x509_free( crt );
+ return( ret );
+ }
+
+ if( p != end )
+ {
+ x509_free( crt );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Parse one or more PEM certificates from a buffer and add them to the chained list
+ */
+int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen )
+{
+ int ret, success = 0, first_error = 0, total_failed = 0;
+ x509_cert *crt, *prev = NULL;
+ int buf_format = X509_FORMAT_DER;
+
+ crt = chain;
+
+ /*
+ * Check for valid input
+ */
+ if( crt == NULL || buf == NULL )
+ return( POLARSSL_ERR_X509_INVALID_INPUT );
+
+ while( crt->version != 0 && crt->next != NULL )
+ {
+ prev = crt;
+ crt = crt->next;
+ }
+
+ /*
+ * Add new certificate on the end of the chain if needed.
+ */
+ if ( crt->version != 0 && crt->next == NULL)
+ {
+ crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
+
+ if( crt->next == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ prev = crt;
+ crt = crt->next;
+ memset( crt, 0, sizeof( x509_cert ) );
+ }
+
+ /*
+ * Determine buffer content. Buffer contains either one DER certificate or
+ * one or more PEM certificates.
+ */
+#if defined(POLARSSL_PEM_C)
+ if( strstr( (char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
+ buf_format = X509_FORMAT_PEM;
+#endif
+
+ if( buf_format == X509_FORMAT_DER )
+ return x509parse_crt_der( crt, buf, buflen );
+
+#if defined(POLARSSL_PEM_C)
+ if( buf_format == X509_FORMAT_PEM )
+ {
+ pem_context pem;
+
+ while( buflen > 0 )
+ {
+ size_t use_len;
+ pem_init( &pem );
+
+ ret = pem_read_buffer( &pem,
+ "-----BEGIN CERTIFICATE-----",
+ "-----END CERTIFICATE-----",
+ buf, NULL, 0, &use_len );
+
+ if( ret == 0 )
+ {
+ /*
+ * Was PEM encoded
+ */
+ buflen -= use_len;
+ buf += use_len;
+ }
+ else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
+ {
+ pem_free( &pem );
+
+ if( first_error == 0 )
+ first_error = ret;
+
+ continue;
+ }
+ else
+ break;
+
+ ret = x509parse_crt_der( crt, pem.buf, pem.buflen );
+
+ pem_free( &pem );
+
+ if( ret != 0 )
+ {
+ /*
+ * quit parsing on a memory error
+ */
+ if( ret == POLARSSL_ERR_X509_MALLOC_FAILED )
+ {
+ if( prev )
+ prev->next = NULL;
+
+ if( crt != chain )
+ free( crt );
+
+ return( ret );
+ }
+
+ if( first_error == 0 )
+ first_error = ret;
+
+ total_failed++;
+
+ memset( crt, 0, sizeof( x509_cert ) );
+ continue;
+ }
+
+ success = 1;
+
+ /*
+ * Add new certificate to the list
+ */
+ crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
+
+ if( crt->next == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ prev = crt;
+ crt = crt->next;
+ memset( crt, 0, sizeof( x509_cert ) );
+ }
+ }
+#endif
+
+ if( crt->version == 0 )
+ {
+ if( prev )
+ prev->next = NULL;
+
+ if( crt != chain )
+ free( crt );
+ }
+
+ if( success )
+ return( total_failed );
+ else if( first_error )
+ return( first_error );
+ else
+ return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT );
+}
+
+/*
+ * Parse one or more CRLs and add them to the chained list
+ */
+int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen )
+{
+ int ret;
+ size_t len;
+ unsigned char *p, *end;
+ x509_crl *crl;
+#if defined(POLARSSL_PEM_C)
+ size_t use_len;
+ pem_context pem;
+#endif
+
+ crl = chain;
+
+ /*
+ * Check for valid input
+ */
+ if( crl == NULL || buf == NULL )
+ return( POLARSSL_ERR_X509_INVALID_INPUT );
+
+ while( crl->version != 0 && crl->next != NULL )
+ crl = crl->next;
+
+ /*
+ * Add new CRL on the end of the chain if needed.
+ */
+ if ( crl->version != 0 && crl->next == NULL)
+ {
+ crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
+
+ if( crl->next == NULL )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+ }
+
+ crl = crl->next;
+ memset( crl, 0, sizeof( x509_crl ) );
+ }
+
+#if defined(POLARSSL_PEM_C)
+ pem_init( &pem );
+ ret = pem_read_buffer( &pem,
+ "-----BEGIN X509 CRL-----",
+ "-----END X509 CRL-----",
+ buf, NULL, 0, &use_len );
+
+ if( ret == 0 )
+ {
+ /*
+ * Was PEM encoded
+ */
+ buflen -= use_len;
+ buf += use_len;
+
+ /*
+ * Steal PEM buffer
+ */
+ p = pem.buf;
+ pem.buf = NULL;
+ len = pem.buflen;
+ pem_free( &pem );
+ }
+ else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
+ {
+ pem_free( &pem );
+ return( ret );
+ }
+ else
+ {
+ /*
+ * nope, copy the raw DER data
+ */
+ p = (unsigned char *) malloc( len = buflen );
+
+ if( p == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ memcpy( p, buf, buflen );
+
+ buflen = 0;
+ }
+#else
+ p = (unsigned char *) malloc( len = buflen );
+
+ if( p == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ memcpy( p, buf, buflen );
+
+ buflen = 0;
+#endif
+
+ crl->raw.p = p;
+ crl->raw.len = len;
+ end = p + len;
+
+ /*
+ * CertificateList ::= SEQUENCE {
+ * tbsCertList TBSCertList,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ */
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
+ }
+
+ if( len != (size_t) ( end - p ) )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+ /*
+ * TBSCertList ::= SEQUENCE {
+ */
+ crl->tbs.p = p;
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+ crl->tbs.len = end - crl->tbs.p;
+
+ /*
+ * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
+ * -- if present, MUST be v2
+ *
+ * signature AlgorithmIdentifier
+ */
+ if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
+ ( ret = x509_get_alg( &p, end, &crl->sig_oid1 ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( ret );
+ }
+
+ crl->version++;
+
+ if( crl->version > 2 )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
+ }
+
+ if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_alg ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
+ }
+
+ /*
+ * issuer Name
+ */
+ crl->issuer_raw.p = p;
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( ret );
+ }
+
+ crl->issuer_raw.len = p - crl->issuer_raw.p;
+
+ /*
+ * thisUpdate Time
+ * nextUpdate Time OPTIONAL
+ */
+ if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( ret );
+ }
+
+ if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
+ {
+ if ( ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
+ POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
+ ret != ( POLARSSL_ERR_X509_CERT_INVALID_DATE +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
+ {
+ x509_crl_free( crl );
+ return( ret );
+ }
+ }
+
+ /*
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, MUST be v2
+ * } OPTIONAL
+ */
+ if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( ret );
+ }
+
+ /*
+ * crlExtensions EXPLICIT Extensions OPTIONAL
+ * -- if present, MUST be v2
+ */
+ if( crl->version == 2 )
+ {
+ ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
+
+ if( ret != 0 )
+ {
+ x509_crl_free( crl );
+ return( ret );
+ }
+ }
+
+ if( p != end )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+ end = crl->raw.p + crl->raw.len;
+
+ /*
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING
+ */
+ if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2 ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( ret );
+ }
+
+ if( memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
+ }
+
+ if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 )
+ {
+ x509_crl_free( crl );
+ return( ret );
+ }
+
+ if( p != end )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+ if( buflen > 0 )
+ {
+ crl->next = (x509_crl *) malloc( sizeof( x509_crl ) );
+
+ if( crl->next == NULL )
+ {
+ x509_crl_free( crl );
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+ }
+
+ crl = crl->next;
+ memset( crl, 0, sizeof( x509_crl ) );
+
+ return( x509parse_crl( crl, buf, buflen ) );
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ */
+int load_file( const char *path, unsigned char **buf, size_t *n )
+{
+ FILE *f;
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+ fseek( f, 0, SEEK_END );
+ *n = (size_t) ftell( f );
+ fseek( f, 0, SEEK_SET );
+
+ if( ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL )
+ return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+ if( fread( *buf, 1, *n, f ) != *n )
+ {
+ fclose( f );
+ free( *buf );
+ return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+
+ (*buf)[*n] = '\0';
+
+ return( 0 );
+}
+
+/*
+ * Load one or more certificates and add them to the chained list
+ */
+int x509parse_crtfile( x509_cert *chain, const char *path )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf;
+
+ if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+ return( ret );
+
+ ret = x509parse_crt( chain, buf, n );
+
+ memset( buf, 0, n + 1 );
+ free( buf );
+
+ return( ret );
+}
+
+/*
+ * Load one or more CRLs and add them to the chained list
+ */
+int x509parse_crlfile( x509_crl *chain, const char *path )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf;
+
+ if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+ return( ret );
+
+ ret = x509parse_crl( chain, buf, n );
+
+ memset( buf, 0, n + 1 );
+ free( buf );
+
+ return( ret );
+}
+
+/*
+ * Load and parse a private RSA key
+ */
+int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf;
+
+ if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+ return( ret );
+
+ if( pwd == NULL )
+ ret = x509parse_key( rsa, buf, n, NULL, 0 );
+ else
+ ret = x509parse_key( rsa, buf, n,
+ (unsigned char *) pwd, strlen( pwd ) );
+
+ memset( buf, 0, n + 1 );
+ free( buf );
+
+ return( ret );
+}
+
+/*
+ * Load and parse a public RSA key
+ */
+int x509parse_public_keyfile( rsa_context *rsa, const char *path )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf;
+
+ if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+ return( ret );
+
+ ret = x509parse_public_key( rsa, buf, n );
+
+ memset( buf, 0, n + 1 );
+ free( buf );
+
+ return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * Parse a private RSA key
+ */
+int x509parse_key( rsa_context *rsa, const unsigned char *key, size_t keylen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ int ret;
+ size_t len;
+ unsigned char *p, *end;
+ unsigned char *p_alt;
+ x509_buf pk_alg_oid;
+
+#if defined(POLARSSL_PEM_C)
+ pem_context pem;
+
+ pem_init( &pem );
+ ret = pem_read_buffer( &pem,
+ "-----BEGIN RSA PRIVATE KEY-----",
+ "-----END RSA PRIVATE KEY-----",
+ key, pwd, pwdlen, &len );
+
+ if( ret == POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
+ {
+ ret = pem_read_buffer( &pem,
+ "-----BEGIN PRIVATE KEY-----",
+ "-----END PRIVATE KEY-----",
+ key, pwd, pwdlen, &len );
+ }
+
+ if( ret == 0 )
+ {
+ /*
+ * Was PEM encoded
+ */
+ keylen = pem.buflen;
+ }
+ else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
+ {
+ pem_free( &pem );
+ return( ret );
+ }
+
+ p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
+#else
+ ((void) pwd);
+ ((void) pwdlen);
+ p = (unsigned char *) key;
+#endif
+ end = p + keylen;
+
+ /*
+ * Note: Depending on the type of private key file one can expect either a
+ * PrivatKeyInfo object (PKCS#8) or a RSAPrivateKey (PKCS#1) directly.
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * algorithm AlgorithmIdentifier,
+ * PrivateKey BIT STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ */
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+
+ if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ if( rsa->ver != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
+ }
+
+ p_alt = p;
+
+ if( ( ret = x509_get_alg( &p_alt, end, &pk_alg_oid ) ) != 0 )
+ {
+ // Assume that we have the PKCS#1 format if wrong
+ // tag was encountered
+ //
+ if( ret != POLARSSL_ERR_X509_CERT_INVALID_ALG +
+ POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
+ }
+ }
+ else
+ {
+ int can_handle;
+
+ /*
+ * only RSA keys handled at this time
+ */
+ can_handle = 0;
+
+ if( pk_alg_oid.len == 9 &&
+ memcmp( pk_alg_oid.p, OID_PKCS1_RSA, 9 ) == 0 )
+ can_handle = 1;
+
+ if( pk_alg_oid.len == 9 &&
+ memcmp( pk_alg_oid.p, OID_PKCS1, 8 ) == 0 )
+ {
+ if( pk_alg_oid.p[8] >= 2 && pk_alg_oid.p[8] <= 5 )
+ can_handle = 1;
+
+ if ( pk_alg_oid.p[8] >= 11 && pk_alg_oid.p[8] <= 14 )
+ can_handle = 1;
+ }
+
+ if( pk_alg_oid.len == 5 &&
+ memcmp( pk_alg_oid.p, OID_RSA_SHA_OBS, 5 ) == 0 )
+ can_handle = 1;
+
+ if( can_handle == 0 )
+ return( POLARSSL_ERR_X509_UNKNOWN_PK_ALG );
+
+ /*
+ * Parse the PKCS#8 format
+ */
+
+ p = p_alt;
+ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ if( ( end - p ) < 1 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_OUT_OF_DATA );
+ }
+
+ end = p + len;
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+
+ if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ if( rsa->ver != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret );
+ }
+ }
+
+ if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
+ ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
+ ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
+ ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
+ ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
+ ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
+ ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
+ ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ rsa->len = mpi_size( &rsa->N );
+
+ if( p != end )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+ if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( ret );
+ }
+
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+
+ return( 0 );
+}
+
+/*
+ * Parse a public RSA key
+ */
+int x509parse_public_key( rsa_context *rsa, const unsigned char *key, size_t keylen )
+{
+ int ret;
+ size_t len;
+ unsigned char *p, *end;
+ x509_buf alg_oid;
+#if defined(POLARSSL_PEM_C)
+ pem_context pem;
+
+ pem_init( &pem );
+ ret = pem_read_buffer( &pem,
+ "-----BEGIN PUBLIC KEY-----",
+ "-----END PUBLIC KEY-----",
+ key, NULL, 0, &len );
+
+ if( ret == 0 )
+ {
+ /*
+ * Was PEM encoded
+ */
+ keylen = pem.buflen;
+ }
+ else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
+ {
+ pem_free( &pem );
+ return( ret );
+ }
+
+ p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
+#else
+ p = (unsigned char *) key;
+#endif
+ end = p + keylen;
+
+ /*
+ * PublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * PublicKey BIT STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ */
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = x509_get_pubkey( &p, end, &alg_oid, &rsa->N, &rsa->E ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( ret );
+ }
+
+ rsa->len = mpi_size( &rsa->N );
+
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_DHM_C)
+/*
+ * Parse DHM parameters
+ */
+int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
+{
+ int ret;
+ size_t len;
+ unsigned char *p, *end;
+#if defined(POLARSSL_PEM_C)
+ pem_context pem;
+
+ pem_init( &pem );
+
+ ret = pem_read_buffer( &pem,
+ "-----BEGIN DH PARAMETERS-----",
+ "-----END DH PARAMETERS-----",
+ dhmin, NULL, 0, &dhminlen );
+
+ if( ret == 0 )
+ {
+ /*
+ * Was PEM encoded
+ */
+ dhminlen = pem.buflen;
+ }
+ else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
+ {
+ pem_free( &pem );
+ return( ret );
+ }
+
+ p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
+#else
+ p = (unsigned char *) dhmin;
+#endif
+ end = p + dhminlen;
+
+ memset( dhm, 0, sizeof( dhm_context ) );
+
+ /*
+ * DHParams ::= SEQUENCE {
+ * prime INTEGER, -- P
+ * generator INTEGER, -- g
+ * }
+ */
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+
+ if( ( ret = asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
+ ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ dhm_free( dhm );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret );
+ }
+
+ if( p != end )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ dhm_free( dhm );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT +
+ POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load and parse a private RSA key
+ */
+int x509parse_dhmfile( dhm_context *dhm, const char *path )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf;
+
+ if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
+ return( ret );
+
+ ret = x509parse_dhm( dhm, buf, n );
+
+ memset( buf, 0, n + 1 );
+ free( buf );
+
+ return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_DHM_C */
+
+#if defined _MSC_VER && !defined snprintf
+#include <stdarg.h>
+
+#if !defined vsnprintf
+#define vsnprintf _vsnprintf
+#endif // vsnprintf
+
+/*
+ * Windows _snprintf and _vsnprintf are not compatible to linux versions.
+ * Result value is not size of buffer needed, but -1 if no fit is possible.
+ *
+ * This fuction tries to 'fix' this by at least suggesting enlarging the
+ * size by 20.
+ */
+int compat_snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list ap;
+ int res = -1;
+
+ va_start( ap, format );
+
+ res = vsnprintf( str, size, format, ap );
+
+ va_end( ap );
+
+ // No quick fix possible
+ if ( res < 0 )
+ return( (int) size + 20 );
+
+ return res;
+}
+
+#define snprintf compat_snprintf
+#endif
+
+#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
+
+#define SAFE_SNPRINTF() \
+{ \
+ if( ret == -1 ) \
+ return( -1 ); \
+ \
+ if ( (unsigned int) ret > n ) { \
+ p[n - 1] = '\0'; \
+ return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
+ } \
+ \
+ n -= (unsigned int) ret; \
+ p += (unsigned int) ret; \
+}
+
+/*
+ * Store the name in printable form into buf; no more
+ * than size characters will be written
+ */
+int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn )
+{
+ int ret;
+ size_t i, n;
+ unsigned char c;
+ const x509_name *name;
+ char s[128], *p;
+
+ memset( s, 0, sizeof( s ) );
+
+ name = dn;
+ p = buf;
+ n = size;
+
+ while( name != NULL )
+ {
+ if( name != dn )
+ {
+ ret = snprintf( p, n, ", " );
+ SAFE_SNPRINTF();
+ }
+
+ if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
+ {
+ switch( name->oid.p[2] )
+ {
+ case X520_COMMON_NAME:
+ ret = snprintf( p, n, "CN=" ); break;
+
+ case X520_COUNTRY:
+ ret = snprintf( p, n, "C=" ); break;
+
+ case X520_LOCALITY:
+ ret = snprintf( p, n, "L=" ); break;
+
+ case X520_STATE:
+ ret = snprintf( p, n, "ST=" ); break;
+
+ case X520_ORGANIZATION:
+ ret = snprintf( p, n, "O=" ); break;
+
+ case X520_ORG_UNIT:
+ ret = snprintf( p, n, "OU=" ); break;
+
+ default:
+ ret = snprintf( p, n, "0x%02X=",
+ name->oid.p[2] );
+ break;
+ }
+ SAFE_SNPRINTF();
+ }
+ else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
+ {
+ switch( name->oid.p[8] )
+ {
+ case PKCS9_EMAIL:
+ ret = snprintf( p, n, "emailAddress=" ); break;
+
+ default:
+ ret = snprintf( p, n, "0x%02X=",
+ name->oid.p[8] );
+ break;
+ }
+ SAFE_SNPRINTF();
+ }
+ else
+ {
+ ret = snprintf( p, n, "\?\?=" );
+ SAFE_SNPRINTF();
+ }
+
+ for( i = 0; i < name->val.len; i++ )
+ {
+ if( i >= sizeof( s ) - 1 )
+ break;
+
+ c = name->val.p[i];
+ if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
+ s[i] = '?';
+ else s[i] = c;
+ }
+ s[i] = '\0';
+ ret = snprintf( p, n, "%s", s );
+ SAFE_SNPRINTF();
+ name = name->next;
+ }
+
+ return( (int) ( size - n ) );
+}
+
+/*
+ * Store the serial in printable form into buf; no more
+ * than size characters will be written
+ */
+int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial )
+{
+ int ret;
+ size_t i, n, nr;
+ char *p;
+
+ p = buf;
+ n = size;
+
+ nr = ( serial->len <= 32 )
+ ? serial->len : 28;
+
+ for( i = 0; i < nr; i++ )
+ {
+ if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
+ continue;
+
+ ret = snprintf( p, n, "%02X%s",
+ serial->p[i], ( i < nr - 1 ) ? ":" : "" );
+ SAFE_SNPRINTF();
+ }
+
+ if( nr != serial->len )
+ {
+ ret = snprintf( p, n, "...." );
+ SAFE_SNPRINTF();
+ }
+
+ return( (int) ( size - n ) );
+}
+
+/*
+ * Return an informational string about the certificate.
+ */
+int x509parse_cert_info( char *buf, size_t size, const char *prefix,
+ const x509_cert *crt )
+{
+ int ret;
+ size_t n;
+ char *p;
+
+ p = buf;
+ n = size;
+
+ ret = snprintf( p, n, "%scert. version : %d\n",
+ prefix, crt->version );
+ SAFE_SNPRINTF();
+ ret = snprintf( p, n, "%sserial number : ",
+ prefix );
+ SAFE_SNPRINTF();
+
+ ret = x509parse_serial_gets( p, n, &crt->serial);
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%sissuer name : ", prefix );
+ SAFE_SNPRINTF();
+ ret = x509parse_dn_gets( p, n, &crt->issuer );
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%ssubject name : ", prefix );
+ SAFE_SNPRINTF();
+ ret = x509parse_dn_gets( p, n, &crt->subject );
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%sissued on : " \
+ "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+ crt->valid_from.year, crt->valid_from.mon,
+ crt->valid_from.day, crt->valid_from.hour,
+ crt->valid_from.min, crt->valid_from.sec );
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%sexpires on : " \
+ "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+ crt->valid_to.year, crt->valid_to.mon,
+ crt->valid_to.day, crt->valid_to.hour,
+ crt->valid_to.min, crt->valid_to.sec );
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
+ SAFE_SNPRINTF();
+
+ switch( crt->sig_alg )
+ {
+ case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
+ case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
+ case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
+ case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
+ case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
+ case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
+ case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
+ case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
+ default: ret = snprintf( p, n, "???" ); break;
+ }
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%sRSA key size : %d bits\n", prefix,
+ (int) crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
+ SAFE_SNPRINTF();
+
+ return( (int) ( size - n ) );
+}
+
+/* Compare a given OID string with an OID x509_buf * */
+#define OID_CMP(oid_str, oid_buf) \
+ ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \
+ memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0)
+
+/*
+ * Return an informational string describing the given OID
+ */
+const char *x509_oid_get_description( x509_buf *oid )
+{
+ if ( oid == NULL )
+ return ( NULL );
+
+ else if( OID_CMP( OID_SERVER_AUTH, oid ) )
+ return( STRING_SERVER_AUTH );
+
+ else if( OID_CMP( OID_CLIENT_AUTH, oid ) )
+ return( STRING_CLIENT_AUTH );
+
+ else if( OID_CMP( OID_CODE_SIGNING, oid ) )
+ return( STRING_CODE_SIGNING );
+
+ else if( OID_CMP( OID_EMAIL_PROTECTION, oid ) )
+ return( STRING_EMAIL_PROTECTION );
+
+ else if( OID_CMP( OID_TIME_STAMPING, oid ) )
+ return( STRING_TIME_STAMPING );
+
+ else if( OID_CMP( OID_OCSP_SIGNING, oid ) )
+ return( STRING_OCSP_SIGNING );
+
+ return( NULL );
+}
+
+/* Return the x.y.z.... style numeric string for the given OID */
+int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
+{
+ int ret;
+ size_t i, n;
+ unsigned int value;
+ char *p;
+
+ p = buf;
+ n = size;
+
+ /* First byte contains first two dots */
+ if( oid->len > 0 )
+ {
+ ret = snprintf( p, n, "%d.%d", oid->p[0]/40, oid->p[0]%40 );
+ SAFE_SNPRINTF();
+ }
+
+ /* TODO: value can overflow in value. */
+ value = 0;
+ for( i = 1; i < oid->len; i++ )
+ {
+ value <<= 7;
+ value += oid->p[i] & 0x7F;
+
+ if( !( oid->p[i] & 0x80 ) )
+ {
+ /* Last byte */
+ ret = snprintf( p, n, ".%d", value );
+ SAFE_SNPRINTF();
+ value = 0;
+ }
+ }
+
+ return( (int) ( size - n ) );
+}
+
+/*
+ * Return an informational string about the CRL.
+ */
+int x509parse_crl_info( char *buf, size_t size, const char *prefix,
+ const x509_crl *crl )
+{
+ int ret;
+ size_t n;
+ char *p;
+ const x509_crl_entry *entry;
+
+ p = buf;
+ n = size;
+
+ ret = snprintf( p, n, "%sCRL version : %d",
+ prefix, crl->version );
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%sissuer name : ", prefix );
+ SAFE_SNPRINTF();
+ ret = x509parse_dn_gets( p, n, &crl->issuer );
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%sthis update : " \
+ "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+ crl->this_update.year, crl->this_update.mon,
+ crl->this_update.day, crl->this_update.hour,
+ crl->this_update.min, crl->this_update.sec );
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n%snext update : " \
+ "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+ crl->next_update.year, crl->next_update.mon,
+ crl->next_update.day, crl->next_update.hour,
+ crl->next_update.min, crl->next_update.sec );
+ SAFE_SNPRINTF();
+
+ entry = &crl->entry;
+
+ ret = snprintf( p, n, "\n%sRevoked certificates:",
+ prefix );
+ SAFE_SNPRINTF();
+
+ while( entry != NULL && entry->raw.len != 0 )
+ {
+ ret = snprintf( p, n, "\n%sserial number: ",
+ prefix );
+ SAFE_SNPRINTF();
+
+ ret = x509parse_serial_gets( p, n, &entry->serial);
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, " revocation date: " \
+ "%04d-%02d-%02d %02d:%02d:%02d",
+ entry->revocation_date.year, entry->revocation_date.mon,
+ entry->revocation_date.day, entry->revocation_date.hour,
+ entry->revocation_date.min, entry->revocation_date.sec );
+ SAFE_SNPRINTF();
+
+ entry = entry->next;
+ }
+
+ ret = snprintf( p, n, "\n%ssigned using : RSA+", prefix );
+ SAFE_SNPRINTF();
+
+ switch( crl->sig_alg )
+ {
+ case SIG_RSA_MD2 : ret = snprintf( p, n, "MD2" ); break;
+ case SIG_RSA_MD4 : ret = snprintf( p, n, "MD4" ); break;
+ case SIG_RSA_MD5 : ret = snprintf( p, n, "MD5" ); break;
+ case SIG_RSA_SHA1 : ret = snprintf( p, n, "SHA1" ); break;
+ case SIG_RSA_SHA224 : ret = snprintf( p, n, "SHA224" ); break;
+ case SIG_RSA_SHA256 : ret = snprintf( p, n, "SHA256" ); break;
+ case SIG_RSA_SHA384 : ret = snprintf( p, n, "SHA384" ); break;
+ case SIG_RSA_SHA512 : ret = snprintf( p, n, "SHA512" ); break;
+ default: ret = snprintf( p, n, "???" ); break;
+ }
+ SAFE_SNPRINTF();
+
+ ret = snprintf( p, n, "\n" );
+ SAFE_SNPRINTF();
+
+ return( (int) ( size - n ) );
+}
+
+/*
+ * Return 0 if the x509_time is still valid, or 1 otherwise.
+ */
+int x509parse_time_expired( const x509_time *to )
+{
+ int year, mon, day;
+ int hour, min, sec;
+
+#if defined(_WIN32)
+ SYSTEMTIME st;
+
+ GetLocalTime(&st);
+
+ year = st.wYear;
+ mon = st.wMonth;
+ day = st.wDay;
+ hour = st.wHour;
+ min = st.wMinute;
+ sec = st.wSecond;
+#else
+ struct tm *lt;
+ time_t tt;
+
+ tt = time( NULL );
+ lt = localtime( &tt );
+
+ year = lt->tm_year + 1900;
+ mon = lt->tm_mon + 1;
+ day = lt->tm_mday;
+ hour = lt->tm_hour;
+ min = lt->tm_min;
+ sec = lt->tm_sec;
+#endif
+
+ if( year > to->year )
+ return( 1 );
+
+ if( year == to->year &&
+ mon > to->mon )
+ return( 1 );
+
+ if( year == to->year &&
+ mon == to->mon &&
+ day > to->day )
+ return( 1 );
+
+ if( year == to->year &&
+ mon == to->mon &&
+ day == to->day &&
+ hour > to->hour )
+ return( 1 );
+
+ if( year == to->year &&
+ mon == to->mon &&
+ day == to->day &&
+ hour == to->hour &&
+ min > to->min )
+ return( 1 );
+
+ if( year == to->year &&
+ mon == to->mon &&
+ day == to->day &&
+ hour == to->hour &&
+ min == to->min &&
+ sec > to->sec )
+ return( 1 );
+
+ return( 0 );
+}
+
+/*
+ * Return 1 if the certificate is revoked, or 0 otherwise.
+ */
+int x509parse_revoked( const x509_cert *crt, const x509_crl *crl )
+{
+ const x509_crl_entry *cur = &crl->entry;
+
+ while( cur != NULL && cur->serial.len != 0 )
+ {
+ if( crt->serial.len == cur->serial.len &&
+ memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
+ {
+ if( x509parse_time_expired( &cur->revocation_date ) )
+ return( 1 );
+ }
+
+ cur = cur->next;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Wrapper for x509 hashes.
+ *
+ * \param out Buffer to receive the hash (Should be at least 64 bytes)
+ */
+static void x509_hash( const unsigned char *in, size_t len, int alg,
+ unsigned char *out )
+{
+ switch( alg )
+ {
+#if defined(POLARSSL_MD2_C)
+ case SIG_RSA_MD2 : md2( in, len, out ); break;
+#endif
+#if defined(POLARSSL_MD4_C)
+ case SIG_RSA_MD4 : md4( in, len, out ); break;
+#endif
+#if defined(POLARSSL_MD5_C)
+ case SIG_RSA_MD5 : md5( in, len, out ); break;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ case SIG_RSA_SHA1 : sha1( in, len, out ); break;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
+ case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
+#endif
+#if defined(POLARSSL_SHA4_C)
+ case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
+ case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
+#endif
+ default:
+ memset( out, '\xFF', 64 );
+ break;
+ }
+}
+
+/*
+ * Check that the given certificate is valid accoring to the CRL.
+ */
+static int x509parse_verifycrl(x509_cert *crt, x509_cert *ca,
+ x509_crl *crl_list)
+{
+ int flags = 0;
+ int hash_id;
+ unsigned char hash[64];
+
+ /*
+ * TODO: What happens if no CRL is present?
+ * Suggestion: Revocation state should be unknown if no CRL is present.
+ * For backwards compatibility this is not yet implemented.
+ */
+
+ while( ca != NULL && crl_list != NULL && crl_list->version != 0 )
+ {
+ if( crl_list->issuer_raw.len != ca->subject_raw.len ||
+ memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
+ crl_list->issuer_raw.len ) != 0 )
+ {
+ crl_list = crl_list->next;
+ continue;
+ }
+
+ /*
+ * Check if CRL is correctly signed by the trusted CA
+ */
+ hash_id = crl_list->sig_alg;
+
+ x509_hash( crl_list->tbs.p, crl_list->tbs.len, hash_id, hash );
+
+ if( !rsa_pkcs1_verify( &ca->rsa, RSA_PUBLIC, hash_id,
+ 0, hash, crl_list->sig.p ) == 0 )
+ {
+ /*
+ * CRL is not trusted
+ */
+ flags |= BADCRL_NOT_TRUSTED;
+ break;
+ }
+
+ /*
+ * Check for validity of CRL (Do not drop out)
+ */
+ if( x509parse_time_expired( &crl_list->next_update ) )
+ flags |= BADCRL_EXPIRED;
+
+ /*
+ * Check if certificate is revoked
+ */
+ if( x509parse_revoked(crt, crl_list) )
+ {
+ flags |= BADCERT_REVOKED;
+ break;
+ }
+
+ crl_list = crl_list->next;
+ }
+ return flags;
+}
+
+int x509_wildcard_verify( const char *cn, x509_buf *name )
+{
+ size_t i;
+ size_t cn_idx = 0;
+
+ if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
+ return( 0 );
+
+ for( i = 0; i < strlen( cn ); ++i )
+ {
+ if( cn[i] == '.' )
+ {
+ cn_idx = i;
+ break;
+ }
+ }
+
+ if( cn_idx == 0 )
+ return( 0 );
+
+ if( memcmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 &&
+ strlen( cn ) - cn_idx == name->len - 1 )
+ {
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Verify the certificate validity
+ */
+int x509parse_verify( x509_cert *crt,
+ x509_cert *trust_ca,
+ x509_crl *ca_crl,
+ const char *cn, int *flags,
+ int (*f_vrfy)(void *, x509_cert *, int, int),
+ void *p_vrfy )
+{
+ size_t cn_len;
+ int hash_id;
+ int pathlen;
+ x509_cert *parent;
+ x509_name *name;
+ unsigned char hash[64];
+ x509_sequence *cur = NULL;
+
+ *flags = 0;
+
+ if( x509parse_time_expired( &crt->valid_to ) )
+ *flags = BADCERT_EXPIRED;
+
+ if( cn != NULL )
+ {
+ name = &crt->subject;
+ cn_len = strlen( cn );
+
+ while( name != NULL )
+ {
+ if( memcmp( name->oid.p, OID_CN, 3 ) == 0 )
+ {
+ if( memcmp( name->val.p, cn, cn_len ) == 0 &&
+ name->val.len == cn_len )
+ break;
+
+ if( memcmp( name->val.p, "*.", 2 ) == 0 &&
+ x509_wildcard_verify( cn, &name->val ) )
+ break;
+ }
+
+ name = name->next;
+ }
+
+ if( name == NULL )
+ {
+ if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
+ {
+ cur = &crt->subject_alt_names;
+
+ while( cur != NULL )
+ {
+ if( memcmp( cn, cur->buf.p, cn_len ) == 0 &&
+ cur->buf.len == cn_len )
+ break;
+
+ if( memcmp( cur->buf.p, "*.", 2 ) == 0 &&
+ x509_wildcard_verify( cn, &cur->buf ) )
+ break;
+
+ cur = cur->next;
+ }
+ }
+
+ if( cur == NULL )
+ *flags |= BADCERT_CN_MISMATCH;
+ }
+ }
+
+ /*
+ * Iterate upwards in the given cert chain,
+ * ignoring any upper cert with CA != TRUE.
+ */
+ parent = crt->next;
+
+ pathlen = 1;
+
+ while( parent != NULL && parent->version != 0 )
+ {
+ if( parent->ca_istrue == 0 ||
+ crt->issuer_raw.len != parent->subject_raw.len ||
+ memcmp( crt->issuer_raw.p, parent->subject_raw.p,
+ crt->issuer_raw.len ) != 0 )
+ {
+ parent = parent->next;
+ continue;
+ }
+
+ hash_id = crt->sig_alg;
+
+ x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
+
+ if( rsa_pkcs1_verify( &parent->rsa, RSA_PUBLIC, hash_id, 0, hash,
+ crt->sig.p ) != 0 )
+ *flags |= BADCERT_NOT_TRUSTED;
+
+ /* Check trusted CA's CRL for the given crt */
+ *flags |= x509parse_verifycrl(crt, parent, ca_crl);
+
+ /* crt is verified to be a child of the parent cur, call verify callback */
+ if( NULL != f_vrfy )
+ {
+ if( f_vrfy( p_vrfy, crt, pathlen - 1, ( *flags == 0 ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+ else
+ *flags = 0;
+ }
+ else if( *flags != 0 )
+ return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+
+ pathlen++;
+
+ crt = parent;
+ parent = crt->next;
+ }
+
+ /*
+ * Attempt to validate topmost cert with our CA chain.
+ */
+ *flags |= BADCERT_NOT_TRUSTED;
+
+ while( trust_ca != NULL && trust_ca->version != 0 )
+ {
+ if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
+ memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
+ crt->issuer_raw.len ) != 0 )
+ {
+ trust_ca = trust_ca->next;
+ continue;
+ }
+
+ if( trust_ca->max_pathlen > 0 &&
+ trust_ca->max_pathlen < pathlen )
+ break;
+
+ hash_id = crt->sig_alg;
+
+ x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
+
+ if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
+ 0, hash, crt->sig.p ) == 0 )
+ {
+ /*
+ * cert. is signed by a trusted CA
+ */
+ *flags &= ~BADCERT_NOT_TRUSTED;
+ break;
+ }
+
+ trust_ca = trust_ca->next;
+ }
+
+ /* Check trusted CA's CRL for the given crt */
+ *flags |= x509parse_verifycrl( crt, trust_ca, ca_crl );
+
+ /* Verification succeeded, call callback on top cert */
+ if( NULL != f_vrfy )
+ {
+ if( f_vrfy(p_vrfy, crt, pathlen-1, ( *flags == 0 ) ) != 0 )
+ return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+ else
+ *flags = 0;
+ }
+ else if( *flags != 0 )
+ return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
+
+ return( 0 );
+}
+
+/*
+ * Unallocate all certificate data
+ */
+void x509_free( x509_cert *crt )
+{
+ x509_cert *cert_cur = crt;
+ x509_cert *cert_prv;
+ x509_name *name_cur;
+ x509_name *name_prv;
+ x509_sequence *seq_cur;
+ x509_sequence *seq_prv;
+
+ if( crt == NULL )
+ return;
+
+ do
+ {
+ rsa_free( &cert_cur->rsa );
+
+ name_cur = cert_cur->issuer.next;
+ while( name_cur != NULL )
+ {
+ name_prv = name_cur;
+ name_cur = name_cur->next;
+ memset( name_prv, 0, sizeof( x509_name ) );
+ free( name_prv );
+ }
+
+ name_cur = cert_cur->subject.next;
+ while( name_cur != NULL )
+ {
+ name_prv = name_cur;
+ name_cur = name_cur->next;
+ memset( name_prv, 0, sizeof( x509_name ) );
+ free( name_prv );
+ }
+
+ seq_cur = cert_cur->ext_key_usage.next;
+ while( seq_cur != NULL )
+ {
+ seq_prv = seq_cur;
+ seq_cur = seq_cur->next;
+ memset( seq_prv, 0, sizeof( x509_sequence ) );
+ free( seq_prv );
+ }
+
+ seq_cur = cert_cur->subject_alt_names.next;
+ while( seq_cur != NULL )
+ {
+ seq_prv = seq_cur;
+ seq_cur = seq_cur->next;
+ memset( seq_prv, 0, sizeof( x509_sequence ) );
+ free( seq_prv );
+ }
+
+ if( cert_cur->raw.p != NULL )
+ {
+ memset( cert_cur->raw.p, 0, cert_cur->raw.len );
+ free( cert_cur->raw.p );
+ }
+
+ cert_cur = cert_cur->next;
+ }
+ while( cert_cur != NULL );
+
+ cert_cur = crt;
+ do
+ {
+ cert_prv = cert_cur;
+ cert_cur = cert_cur->next;
+
+ memset( cert_prv, 0, sizeof( x509_cert ) );
+ if( cert_prv != crt )
+ free( cert_prv );
+ }
+ while( cert_cur != NULL );
+}
+
+/*
+ * Unallocate all CRL data
+ */
+void x509_crl_free( x509_crl *crl )
+{
+ x509_crl *crl_cur = crl;
+ x509_crl *crl_prv;
+ x509_name *name_cur;
+ x509_name *name_prv;
+ x509_crl_entry *entry_cur;
+ x509_crl_entry *entry_prv;
+
+ if( crl == NULL )
+ return;
+
+ do
+ {
+ name_cur = crl_cur->issuer.next;
+ while( name_cur != NULL )
+ {
+ name_prv = name_cur;
+ name_cur = name_cur->next;
+ memset( name_prv, 0, sizeof( x509_name ) );
+ free( name_prv );
+ }
+
+ entry_cur = crl_cur->entry.next;
+ while( entry_cur != NULL )
+ {
+ entry_prv = entry_cur;
+ entry_cur = entry_cur->next;
+ memset( entry_prv, 0, sizeof( x509_crl_entry ) );
+ free( entry_prv );
+ }
+
+ if( crl_cur->raw.p != NULL )
+ {
+ memset( crl_cur->raw.p, 0, crl_cur->raw.len );
+ free( crl_cur->raw.p );
+ }
+
+ crl_cur = crl_cur->next;
+ }
+ while( crl_cur != NULL );
+
+ crl_cur = crl;
+ do
+ {
+ crl_prv = crl_cur;
+ crl_cur = crl_cur->next;
+
+ memset( crl_prv, 0, sizeof( x509_crl ) );
+ if( crl_prv != crl )
+ free( crl_prv );
+ }
+ while( crl_cur != NULL );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include "polarssl/certs.h"
+
+/*
+ * Checkup routine
+ */
+int x509_self_test( int verbose )
+{
+#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
+ int ret;
+ int flags;
+ size_t i, j;
+ x509_cert cacert;
+ x509_cert clicert;
+ rsa_context rsa;
+#if defined(POLARSSL_DHM_C)
+ dhm_context dhm;
+#endif
+
+ if( verbose != 0 )
+ printf( " X.509 certificate load: " );
+
+ memset( &clicert, 0, sizeof( x509_cert ) );
+
+ ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
+ strlen( test_cli_crt ) );
+ if( ret != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( ret );
+ }
+
+ memset( &cacert, 0, sizeof( x509_cert ) );
+
+ ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
+ strlen( test_ca_crt ) );
+ if( ret != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( ret );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n X.509 private key load: " );
+
+ i = strlen( test_ca_key );
+ j = strlen( test_ca_pwd );
+
+ rsa_init( &rsa, RSA_PKCS_V15, 0 );
+
+ if( ( ret = x509parse_key( &rsa,
+ (unsigned char *) test_ca_key, i,
+ (unsigned char *) test_ca_pwd, j ) ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( ret );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n X.509 signature verify: ");
+
+ ret = x509parse_verify( &clicert, &cacert, NULL, "PolarSSL Client 2", &flags, NULL, NULL );
+ if( ret != 0 )
+ {
+ printf("%02x", flags);
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( ret );
+ }
+
+#if defined(POLARSSL_DHM_C)
+ if( verbose != 0 )
+ printf( "passed\n X.509 DHM parameter load: " );
+
+ i = strlen( test_dhm_params );
+ j = strlen( test_ca_pwd );
+
+ if( ( ret = x509parse_dhm( &dhm, (unsigned char *) test_dhm_params, i ) ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( ret );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n\n" );
+#endif
+
+ x509_free( &cacert );
+ x509_free( &clicert );
+ rsa_free( &rsa );
+#if defined(POLARSSL_DHM_C)
+ dhm_free( &dhm );
+#endif
+
+ return( 0 );
+#else
+ ((void) verbose);
+ return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+#endif
+}
+
+#endif
+
+#endif
diff --git a/polarssl/src/library/x509write.c b/polarssl/src/library/x509write.c
new file mode 100644
index 0000000..400ffa0
--- /dev/null
+++ b/polarssl/src/library/x509write.c
@@ -0,0 +1,287 @@
+/*
+ * X509 buffer writing functionality
+ *
+ * Copyright (C) 2006-2012, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_X509_WRITE_C)
+
+#include "polarssl/asn1write.h"
+#include "polarssl/x509write.h"
+#include "polarssl/x509.h"
+#include "polarssl/sha1.h"
+#include "polarssl/sha2.h"
+#include "polarssl/sha4.h"
+#include "polarssl/md4.h"
+#include "polarssl/md5.h"
+
+int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa )
+{
+ int ret;
+ unsigned char *c;
+ size_t len = 0;
+
+ c = buf + size - 1;
+
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
+
+ ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ if( c - buf < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--c = 0;
+ len += 1;
+
+ ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) );
+
+ ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, OID_PKCS1_RSA ) );
+
+ ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ return( len );
+}
+
+int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa )
+{
+ int ret;
+ unsigned char *c;
+ size_t len = 0;
+
+ c = buf + size - 1;
+
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) );
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) );
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) );
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) );
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) );
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) );
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) );
+ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) );
+ ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
+
+ ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ // TODO: Make NON RSA Specific variant later on
+/* *--c = 0;
+ len += 1;
+
+ len += asn1_write_len( &c, len);
+ len += asn1_write_tag( &c, ASN1_BIT_STRING );
+
+ len += asn1_write_oid( &c, OID_PKCS1_RSA );
+
+ len += asn1_write_int( &c, 0 );
+
+ len += asn1_write_len( &c, len);
+ len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/
+
+/* for(i = 0; i < len; ++i)
+ {
+ if (i % 16 == 0 ) printf("\n");
+ printf("%02x ", c[i]);
+ }
+ printf("\n");*/
+
+ return( len );
+}
+
+int x509_write_name( unsigned char **p, unsigned char *start, char *oid,
+ char *name )
+{
+ int ret;
+ size_t string_len = 0;
+ size_t oid_len = 0;
+ size_t len = 0;
+
+ // Write PrintableString for all except OID_PKCS9_EMAIL
+ //
+ if( OID_SIZE( OID_PKCS9_EMAIL ) == strlen( oid ) &&
+ memcmp( oid, OID_PKCS9_EMAIL, strlen( oid ) ) == 0 )
+ {
+ ASN1_CHK_ADD( string_len, asn1_write_ia5_string( p, start, name ) );
+ }
+ else
+ ASN1_CHK_ADD( string_len, asn1_write_printable_string( p, start, name ) );
+
+ // Write OID
+ //
+ ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) );
+
+ len = oid_len + string_len;
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + string_len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
+
+ return( len );
+}
+
+/*
+ * Wrapper for x509 hashes.
+ *
+ * \param out Buffer to receive the hash (Should be at least 64 bytes)
+ */
+static void x509_hash( const unsigned char *in, size_t len, int alg,
+ unsigned char *out )
+{
+ switch( alg )
+ {
+#if defined(POLARSSL_MD2_C)
+ case SIG_RSA_MD2 : md2( in, len, out ); break;
+#endif
+#if defined(POLARSSL_MD4_C)
+ case SIG_RSA_MD4 : md4( in, len, out ); break;
+#endif
+#if defined(POLARSSL_MD5_C)
+ case SIG_RSA_MD5 : md5( in, len, out ); break;
+#endif
+#if defined(POLARSSL_SHA1_C)
+ case SIG_RSA_SHA1 : sha1( in, len, out ); break;
+#endif
+#if defined(POLARSSL_SHA2_C)
+ case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
+ case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
+#endif
+#if defined(POLARSSL_SHA4_C)
+ case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
+ case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
+#endif
+ default:
+ memset( out, '\xFF', 64 );
+ break;
+ }
+}
+
+int x509_write_sig( unsigned char **p, unsigned char *start, char *oid,
+ unsigned char *sig, size_t size )
+{
+ int ret;
+ size_t len = 0;
+
+ if( *p - start < (int) size + 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ len = size;
+ (*p) -= len;
+ memcpy( *p, sig, len );
+
+ *--(*p) = 0;
+ len += 1;
+
+ ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
+
+ // Write OID
+ //
+ ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid ) );
+
+ return( len );
+}
+
+int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa,
+ x509_req_name *req_name, int hash_id )
+{
+ int ret;
+ char sig_oid[10];
+ unsigned char *c, *c2;
+ unsigned char hash[64];
+ unsigned char sig[POLARSSL_MPI_MAX_SIZE];
+ unsigned char tmp_buf[2048];
+ size_t sub_len = 0, pub_len = 0, sig_len = 0;
+ size_t len = 0;
+ x509_req_name *cur = req_name;
+
+ c = tmp_buf + 2048 - 1;
+
+ ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, 0 ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
+
+ ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->E ) );
+ ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->N ) );
+
+ ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
+ ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ if( c - tmp_buf < 1 )
+ return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--c = 0;
+ pub_len += 1;
+
+ ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) );
+ ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_BIT_STRING ) );
+
+ ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) );
+
+ len += pub_len;
+ ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ while( cur != NULL )
+ {
+ ASN1_CHK_ADD( sub_len, x509_write_name( &c, tmp_buf, cur->oid, cur->name ) );
+
+ cur = cur->next;
+ }
+
+ len += sub_len;
+ ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
+
+ ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ x509_hash( c, len, hash_id, hash );
+
+ rsa_pkcs1_sign( rsa, NULL, NULL, RSA_PRIVATE, hash_id, 0, hash, sig );
+
+ // Generate correct OID
+ //
+ memcpy( sig_oid, OID_PKCS1, 8 );
+ sig_oid[8] = hash_id;
+ sig_oid[9] = '\0';
+
+ c2 = buf + size - 1;
+ ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, rsa->len ) );
+
+ c2 -= len;
+ memcpy( c2, c, len );
+
+ len += sig_len;
+ ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
+ ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+ return( len );
+}
+
+#endif
diff --git a/polarssl/src/library/xtea.c b/polarssl/src/library/xtea.c
new file mode 100644
index 0000000..bc473e5
--- /dev/null
+++ b/polarssl/src/library/xtea.c
@@ -0,0 +1,248 @@
+/*
+ * An 32-bit implementation of the XTEA algorithm
+ *
+ * Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ * This file is part of PolarSSL (http://www.polarssl.org)
+ * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "polarssl/config.h"
+
+#if defined(POLARSSL_XTEA_C)
+
+#include "polarssl/xtea.h"
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * XTEA key schedule
+ */
+void xtea_setup( xtea_context *ctx, unsigned char key[16] )
+{
+ int i;
+
+ memset(ctx, 0, sizeof(xtea_context));
+
+ for( i = 0; i < 4; i++ )
+ {
+ GET_ULONG_BE( ctx->k[i], key, i << 2 );
+ }
+}
+
+/*
+ * XTEA encrypt function
+ */
+int xtea_crypt_ecb( xtea_context *ctx, int mode, unsigned char input[8],
+ unsigned char output[8])
+{
+ uint32_t *k, v0, v1, i;
+
+ k = ctx->k;
+
+ GET_ULONG_BE( v0, input, 0 );
+ GET_ULONG_BE( v1, input, 4 );
+
+ if( mode == XTEA_ENCRYPT )
+ {
+ uint32_t sum = 0, delta = 0x9E3779B9;
+
+ for( i = 0; i < 32; i++ )
+ {
+ v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
+ sum += delta;
+ v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
+ }
+ }
+ else /* XTEA_DECRYPT */
+ {
+ uint32_t delta = 0x9E3779B9, sum = delta * 32;
+
+ for( i = 0; i < 32; i++ )
+ {
+ v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
+ sum -= delta;
+ v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
+ }
+ }
+
+ PUT_ULONG_BE( v0, output, 0 );
+ PUT_ULONG_BE( v1, output, 4 );
+
+ return( 0 );
+}
+
+/*
+ * XTEA-CBC buffer encryption/decryption
+ */
+int xtea_crypt_cbc( xtea_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ unsigned char *input,
+ unsigned char *output)
+{
+ int i;
+ unsigned char temp[8];
+
+ if(length % 8)
+ return( POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH );
+
+ if( mode == XTEA_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 8 );
+ xtea_crypt_ecb( ctx, mode, input, output );
+
+ for(i = 0; i < 8; i++)
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ xtea_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+
+ return( 0 );
+}
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * XTEA tests vectors (non-official)
+ */
+
+static const unsigned char xtea_test_key[6][16] =
+{
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char xtea_test_pt[6][8] =
+{
+ { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+ { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
+ { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+ { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }
+};
+
+static const unsigned char xtea_test_ct[6][8] =
+{
+ { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 },
+ { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+ { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 },
+ { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
+};
+
+/*
+ * Checkup routine
+ */
+int xtea_self_test( int verbose )
+{
+ int i;
+ unsigned char buf[8];
+ xtea_context ctx;
+
+ for( i = 0; i < 6; i++ )
+ {
+ if( verbose != 0 )
+ printf( " XTEA test #%d: ", i + 1 );
+
+ memcpy( buf, xtea_test_pt[i], 8 );
+
+ xtea_setup( &ctx, (unsigned char *) xtea_test_key[i] );
+ xtea_crypt_ecb( &ctx, XTEA_ENCRYPT, buf, buf );
+
+ if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 )
+ {
+ if( verbose != 0 )
+ printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ printf( "\n" );
+
+ return( 0 );
+}
+
+#endif
+
+#endif