summaryrefslogtreecommitdiffhomepage
path: root/libs/luci-lib-nixio/axTLS/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'libs/luci-lib-nixio/axTLS/ssl')
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/BigIntConfig.in132
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/Config.in336
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/Makefile123
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/asn1.c510
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/cert.h43
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/crypto_misc.h164
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/gen_cert.c363
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/loader.c465
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/openssl.c322
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/os_port.c158
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/os_port.h207
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/p12.c486
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/private_key.h54
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/ssl.h474
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/Makefile97
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_key.pem15
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_x509.cerbin0 -> 483 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_x509.pem13
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.device_keybin0 -> 609 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.device_key.pem15
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.encrypted.p8bin0 -> 385 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.encrypted_pem.p811
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_1024bin0 -> 609 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_1024.pem15
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_2048bin0 -> 1191 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_2048.pem27
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_4096bin0 -> 2349 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_4096.pem51
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_512bin0 -> 321 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_512.pem9
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_aes128.pem12
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_aes256.pem12
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.noname.p12bin0 -> 1483 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.unencrypted.p8bin0 -> 347 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.unencrypted_pem.p810
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.withCA.p12bin0 -> 2089 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.withoutCA.p12bin0 -> 1573 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_1024.cerbin0 -> 475 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_1024.pem12
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_2048.cerbin0 -> 607 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_2048.pem15
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_4096.cerbin0 -> 863 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_4096.pem20
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_512.cerbin0 -> 406 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_512.pem11
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_aes128.pem11
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_aes256.pem11
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_bad_after.pem11
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_bad_before.pem11
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_device.cerbin0 -> 401 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_device.pem24
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/datatest.c43
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/datatest.c.old280
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/deutsche_telecom.x509_cabin0 -> 670 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/equifax.x509_cabin0 -> 646 bytes
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/test/gnutls.cerbin0 -> 599 bytes
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/test/header_issue.datbin0 -> 1159 bytes
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/test/killopenssl.sh2
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/test/make_certs.sh174
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/microsoft.x509_cabin0 -> 1046 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/microsoft.x509_ca.pem24
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/test/ms_iis.cer13
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/perf_bigint.c228
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/test/socgen.cerbin0 -> 980 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c1983
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c.bak1940
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/test/test_axssl.sh163
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/thawte.x509_cabin0 -> 811 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_cabin0 -> 668 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_ca.pem16
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_my_certbin0 -> 1095 bytes
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_my_cert.pem25
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/tls1.c2057
-rwxr-xr-xlibs/luci-lib-nixio/axTLS/ssl/tls1.h289
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/tls1_clnt.c386
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/tls1_svr.c476
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/version.h1
-rw-r--r--libs/luci-lib-nixio/axTLS/ssl/x509.c502
78 files changed, 12852 insertions, 0 deletions
diff --git a/libs/luci-lib-nixio/axTLS/ssl/BigIntConfig.in b/libs/luci-lib-nixio/axTLS/ssl/BigIntConfig.in
new file mode 100644
index 0000000000..04c7438c07
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/BigIntConfig.in
@@ -0,0 +1,132 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/config/Kconfig-language.txt
+#
+
+menu "BigInt Options"
+ depends on !CONFIG_SSL_SKELETON_MODE
+
+choice
+ prompt "Reduction Algorithm"
+ default CONFIG_BIGINT_BARRETT
+
+config CONFIG_BIGINT_CLASSICAL
+ bool "Classical"
+ help
+ Classical uses standard division. It has no limitations and is
+ theoretically the slowest due to the divisions used. For this particular
+ implementation it is surprisingly quite fast.
+
+config CONFIG_BIGINT_MONTGOMERY
+ bool "Montgomery"
+ help
+ Montgomery uses simple addition and multiplication to achieve its
+ performance. In this implementation it is slower than classical,
+ and it has the limitation that 0 <= x, y < m, and so is not used
+ when CRT is active.
+
+ This option will not be normally selected.
+
+config CONFIG_BIGINT_BARRETT
+ bool "Barrett"
+ help
+ Barrett performs expensive precomputation before reduction and partial
+ multiplies for computational speed. It can't be used with some of the
+ calculations when CRT is used, and so defaults to classical when this
+ occurs.
+
+ It is about 40% faster than Classical/Montgomery with the expense of
+ about 2kB, and so this option is normally selected.
+
+endchoice
+
+config CONFIG_BIGINT_CRT
+ bool "Chinese Remainder Theorem (CRT)"
+ default y
+ help
+ Allow the Chinese Remainder Theorem (CRT) to be used.
+
+ Uses a number of extra coefficients from the private key to improve the
+ performance of a decryption. This feature is one of the most
+ significant performance improvements (it reduces a decryption time by
+ over 3 times).
+
+ This option should be selected.
+
+config CONFIG_BIGINT_KARATSUBA
+ bool "Karatsuba Multiplication"
+ default n
+ help
+ Allow Karasuba multiplication to be used.
+
+ Uses 3 multiplications (plus a number of additions/subtractions)
+ instead of 4. Multiplications are O(N^2) but addition/subtraction
+ is O(N) hence for large numbers is beneficial. For this project, the
+ effect was only useful for 4096 bit keys. As these aren't likely to
+ be used, the feature is disabled by default.
+
+ It costs about 2kB to enable it.
+
+config MUL_KARATSUBA_THRESH
+ int "Karatsuba Multiplication Theshold"
+ default 20
+ depends on CONFIG_BIGINT_KARATSUBA
+ help
+ The minimum number of components needed before Karasuba muliplication
+ is used.
+
+ This is very dependent on the speed/implementation of bi_add()/
+ bi_subtract(). There is a bit of trial and error here and will be
+ at a different point for different architectures.
+
+config SQU_KARATSUBA_THRESH
+ int "Karatsuba Square Threshold"
+ default 40
+ depends on CONFIG_BIGINT_KARATSUBA && CONFIG_BIGINT_SQUARE
+ help
+ The minimum number of components needed before Karatsuba squaring
+ is used.
+
+ This is very dependent on the speed/implementation of bi_add()/
+ bi_subtract(). There is a bit of trial and error here and will be
+ at a different point for different architectures.
+
+config CONFIG_BIGINT_SLIDING_WINDOW
+ bool "Sliding Window Exponentiation"
+ default y
+ help
+ Allow Sliding-Window Exponentiation to be used.
+
+ Potentially processes more than 1 bit at a time when doing
+ exponentiation. The sliding-window technique reduces the number of
+ precomputations compared to other precomputed techniques.
+
+ It results in a considerable performance improvement with it enabled
+ (it halves the decryption time) and so should be selected.
+
+config CONFIG_BIGINT_SQUARE
+ bool "Square Algorithm"
+ default y
+ help
+ Allow squaring to be used instead of a multiplication.
+
+ Squaring is theoretically 50% faster than a standard multiply
+ (but is actually about 25% faster).
+
+ It gives a 20% speed improvement and so should be selected.
+
+config CONFIG_BIGINT_CHECK_ON
+ bool "BigInt Integrity Checking"
+ default n if !CONFIG_DEBUG
+ default y if CONFIG_DEBUG
+ help
+ This is used when developing bigint algorithms. It performs a sanity
+ check on all operations at the expense of speed.
+
+ This option is only selected when developing and should normally be
+ turned off.
+
+endmenu
+
+
+
diff --git a/libs/luci-lib-nixio/axTLS/ssl/Config.in b/libs/luci-lib-nixio/axTLS/ssl/Config.in
new file mode 100644
index 0000000000..d047d420ec
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/Config.in
@@ -0,0 +1,336 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/config/Kconfig-language.txt
+#
+
+menu "SSL Library"
+
+choice
+ prompt "Mode"
+ default CONFIG_SSL_FULL_MODE
+
+config CONFIG_SSL_SERVER_ONLY
+ bool "Server only - no verification"
+ help
+ Enable server functionality (no client functionality).
+ This mode still supports sessions and chaining (which can be turned
+ off in configuration).
+
+ The axssl sample runs with the minimum of features.
+
+ This is the most space efficient of the modes with the library
+ about 45kB in size. Use this mode if you are doing standard SSL server
+ work.
+
+config CONFIG_SSL_CERT_VERIFICATION
+ bool "Server only - with verification"
+ help
+ Enable server functionality with client authentication (no client
+ functionality).
+
+ The axssl sample runs with the "-verify" and "-CAfile" options.
+
+ This mode produces a library about 49kB in size. Use this mode if you
+ have an SSL server which requires client authentication (which is
+ uncommon in browser applications).
+
+config CONFIG_SSL_ENABLE_CLIENT
+ bool "Client/Server enabled"
+ help
+ Enable client/server functionality (including peer authentication).
+
+ The axssl sample runs with the "s_client" option enabled.
+
+ This mode produces a library about 51kB in size. Use this mode if you
+ require axTLS to use SSL client functionality (the SSL server code
+ is always enabled).
+
+config CONFIG_SSL_FULL_MODE
+ bool "Client/Server enabled with diagnostics"
+ help
+ Enable client/server functionality including diagnostics. Most of the
+ extra size in this mode is due to the storage of various strings that
+ are used.
+
+ The axssl sample has 3 more options, "-debug", "-state" and "-show-rsa"
+
+ This mode produces a library about 58kB in size. It is suggested that
+ this mode is used only during development, or systems that have more
+ generous memory limits.
+
+ It is the default to demonstrate the features of axTLS.
+
+config CONFIG_SSL_SKELETON_MODE
+ bool "Skeleton mode - the smallest server mode"
+ help
+ This is an experiment to build the smallest library at the expense of
+ features and speed.
+
+ * Server mode only.
+ * The AES cipher is disabled.
+ * No session resumption.
+ * No external keys/certificates are supported.
+ * The bigint library has most of the performance features disabled.
+ * Some other features/API calls may not work.
+
+ This mode produces a library about 37kB in size. The main
+ disadvantage of this mode is speed - it will be much slower than the
+ other build modes.
+
+endchoice
+
+choice
+ prompt "Protocol Preference"
+ depends on !CONFIG_SSL_SKELETON_MODE
+ default CONFIG_SSL_PROT_MEDIUM
+
+config CONFIG_SSL_PROT_LOW
+ bool "Low"
+ help
+ Chooses the cipher in the order of RC4-SHA, AES128-SHA, AES256-SHA.
+
+ This will use the fastest cipher(s) but at the expense of security.
+
+config CONFIG_SSL_PROT_MEDIUM
+ bool "Medium"
+ help
+ Chooses the cipher in the order of AES128-SHA, AES256-SHA, RC4-SHA.
+
+ This mode is a balance between speed and security and is the default.
+
+config CONFIG_SSL_PROT_HIGH
+ bool "High"
+ help
+ Chooses the cipher in the order of AES256-SHA, AES128-SHA, RC4-SHA.
+
+ This will use the strongest cipher(s) at the cost of speed.
+
+endchoice
+
+config CONFIG_SSL_USE_DEFAULT_KEY
+ bool "Enable default key"
+ depends on !CONFIG_SSL_SKELETON_MODE
+ default y
+ help
+ Some applications will not require the default private key/certificate
+ that is built in. This is one way to save on a couple of kB's if an
+ external private key/certificate is used.
+
+ The private key is in ssl/private_key.h and the certificate is in
+ ssl/cert.h.
+
+ The advantage of a built-in private key/certificate is that no file
+ system is required for access. Both the certificate and the private
+ key will be automatically loaded on a ssl_ctx_new().
+
+ However this private key/certificate can never be changed (without a
+ code update).
+
+ This mode is enabled by default. Disable this mode if the
+ built-in key/certificate is not used.
+
+config CONFIG_SSL_PRIVATE_KEY_LOCATION
+ string "Private key file location"
+ depends on !CONFIG_SSL_USE_DEFAULT_KEY && !CONFIG_SSL_SKELETON_MODE
+ help
+ The file location of the private key which will be automatically
+ loaded on a ssl_ctx_new().
+
+config CONFIG_SSL_PRIVATE_KEY_PASSWORD
+ string "Private key password"
+ depends on !CONFIG_SSL_USE_DEFAULT_KEY && CONFIG_SSL_HAS_PEM
+ help
+ The password required to decrypt a PEM-encoded password file.
+
+config CONFIG_SSL_X509_CERT_LOCATION
+ string "X.509 certificate file location"
+ depends on !CONFIG_SSL_GENERATE_X509_CERT && !CONFIG_SSL_USE_DEFAULT_KEY && !CONFIG_SSL_SKELETON_MODE
+ help
+ The file location of the X.509 certificate which will be automatically
+ loaded on a ssl_ctx_new().
+
+config CONFIG_SSL_GENERATE_X509_CERT
+ bool "Generate X.509 Certificate"
+ default n
+ help
+ An X.509 certificate can be automatically generated on a
+ ssl_ctx_new(). A private key still needs to be provided (the private
+ key in ss/private_key.h will be used unless
+ CONFIG_SSL_PRIVATE_KEY_LOCATION is set).
+
+ The certificate is generated on the fly, and so a minor start-up time
+ penalty is to be expected. This feature adds around 5kB to the
+ library.
+
+ This feature is disabled by default.
+
+config CONFIG_SSL_X509_COMMON_NAME
+ string "X.509 Common Name"
+ depends on CONFIG_SSL_GENERATE_X509_CERT
+ help
+ The common name for the X.509 certificate. This should be the fully
+ qualified domain name (FQDN), e.g. www.foo.com.
+
+ If this is blank, then this will be value from gethostname() and
+ getdomainname().
+
+config CONFIG_SSL_X509_ORGANIZATION_NAME
+ string "X.509 Organization Name"
+ depends on CONFIG_SSL_GENERATE_X509_CERT
+ help
+ The organization name for the generated X.509 certificate.
+
+ This field is optional.
+
+config CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME
+ string "X.509 Organization Unit Name"
+ depends on CONFIG_SSL_GENERATE_X509_CERT
+ help
+ The organization unit name for the generated X.509 certificate.
+
+ This field is optional.
+
+config CONFIG_SSL_ENABLE_V23_HANDSHAKE
+ bool "Enable v23 Handshake"
+ default y
+ help
+ Some browsers use the v23 handshake client hello message
+ (an SSL2 format message which all SSL servers can understand).
+ It may be used if SSL2 is enabled in the browser.
+
+ Since this feature takes a kB or so, this feature may be disabled - at
+ the risk of making it incompatible with some browsers (IE6 is ok,
+ Firefox 1.5 and below use it).
+
+ Disable if backwards compatibility is not an issue (i.e. the client is
+ always using TLS1.0)
+
+config CONFIG_SSL_HAS_PEM
+ bool "Enable PEM"
+ default n if !CONFIG_SSL_FULL_MODE
+ default y if CONFIG_SSL_FULL_MODE
+ depends on !CONFIG_SSL_SKELETON_MODE
+ help
+ Enable the use of PEM format for certificates and private keys.
+
+ PEM is not normally needed - PEM files can be converted into DER files
+ quite easily. However they have the convenience of allowing multiple
+ certificates/keys in the same file.
+
+ This feature will add a couple of kB to the library.
+
+ Disable if PEM is not used (which will be in most cases).
+
+config CONFIG_SSL_USE_PKCS12
+ bool "Use PKCS8/PKCS12"
+ default n if !CONFIG_SSL_FULL_MODE
+ default y if CONFIG_SSL_FULL_MODE
+ depends on !CONFIG_SSL_SERVER_ONLY && !CONFIG_SSL_SKELETON_MODE
+ help
+ PKCS#12 certificates combine private keys and certificates together in
+ one file.
+
+ PKCS#8 private keys are also suppported (as it is a subset of PKCS#12).
+
+ The decryption of these certificates uses RC4-128 (and these
+ certificates must be encrypted using this cipher). The actual
+ algorithm is "PBE-SHA1-RC4-128".
+
+ Disable if PKCS#12 is not used (which will be in most cases).
+
+config CONFIG_SSL_EXPIRY_TIME
+ int "Session expiry time (in hours)"
+ depends on !CONFIG_SSL_SKELETON_MODE
+ default 24
+ help
+ The time (in hours) before a session expires.
+
+ A longer time means that the expensive parts of a handshake don't
+ need to be run when a client reconnects later.
+
+ The default is 1 day.
+
+config CONFIG_X509_MAX_CA_CERTS
+ int "Maximum number of certificate authorites"
+ default 4
+ depends on !CONFIG_SSL_SERVER_ONLY && !CONFIG_SSL_SKELETON_MODE
+ help
+ Determines the number of CA's allowed.
+
+ Increase this figure if more trusted sites are allowed. Each
+ certificate adds about 300 bytes (when added).
+
+ The default is to allow four certification authorities.
+
+config CONFIG_SSL_MAX_CERTS
+ int "Maximum number of chained certificates"
+ default 2
+ help
+ Determines the number of certificates used in a certificate
+ chain. The chain length must be at least 1.
+
+ Increase this figure if more certificates are to be added to the
+ chain. Each certificate adds about 300 bytes (when added).
+
+ The default is to allow one certificate + 1 certificate in the chain
+ (which may be the certificate authority certificate).
+
+config CONFIG_SSL_CTX_MUTEXING
+ bool "Enable SSL_CTX mutexing"
+ default n
+ help
+ Normally mutexing is not required - each SSL_CTX object can deal with
+ many SSL objects (as long as each SSL_CTX object is using a single
+ thread).
+
+ If the SSL_CTX object is not thread safe e.g. the case where a
+ new thread is created for each SSL object, then mutexing is required.
+
+ Select y when a mutex on the SSL_CTX object is required.
+
+config CONFIG_USE_DEV_URANDOM
+ bool "Use /dev/urandom"
+ default y
+ depends on !CONFIG_PLATFORM_WIN32
+ help
+ Use /dev/urandom. Otherwise a custom RNG is used.
+
+ This will be the default on most Linux systems.
+
+config CONFIG_WIN32_USE_CRYPTO_LIB
+ bool "Use Win32 Crypto Library"
+ depends on CONFIG_PLATFORM_WIN32
+ help
+ Microsoft produce a Crypto API which requires the Platform SDK to be
+ installed. It's used for the RNG.
+
+ This will be the default on most Win32 systems.
+
+config CONFIG_OPENSSL_COMPATIBLE
+ bool "Enable openssl API compatibility"
+ default n
+ help
+ To ease the porting of openssl applications, a subset of the openssl
+ API is wrapped around the axTLS API.
+
+ Note: not all the API is implemented, so parts may still break. And
+ it's definitely not 100% compatible.
+
+config CONFIG_PERFORMANCE_TESTING
+ bool "Build the bigint performance test tool"
+ default n
+ help
+ Used for performance testing of bigint.
+
+ This is a testing tool and is normally disabled.
+
+config CONFIG_SSL_TEST
+ bool "Build the SSL testing tool"
+ default n
+ depends on CONFIG_SSL_FULL_MODE && !CONFIG_SSL_GENERATE_X509_CERT
+ help
+ Used for sanity checking the SSL handshaking.
+
+ This is a testing tool and is normally disabled.
+
+endmenu
diff --git a/libs/luci-lib-nixio/axTLS/ssl/Makefile b/libs/luci-lib-nixio/axTLS/ssl/Makefile
new file mode 100644
index 0000000000..704d90a9b2
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/Makefile
@@ -0,0 +1,123 @@
+#
+# 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.
+#
+
+AXTLS_HOME=..
+
+include $(AXTLS_HOME)/config/.config
+include $(AXTLS_HOME)/config/makefile.conf
+
+all: libs
+ifdef CONFIG_PERFORMANCE_TESTING
+ $(MAKE) -C test
+else
+ifdef CONFIG_SSL_TEST
+ $(MAKE) -C test
+endif
+endif
+
+ifndef CONFIG_PLATFORM_WIN32
+TARGET1=$(AXTLS_HOME)/$(STAGE)/libaxtls.a
+BASETARGET=libaxtls.so
+CRYPTO_PATH=$(AXTLS_HOME)/crypto/
+ifdef CONFIG_PLATFORM_CYGWIN
+TARGET2=$(AXTLS_HOME)/$(STAGE)/libaxtls.dll.a
+else
+TARGET2=$(AXTLS_HOME)/$(STAGE)/$(LIBMINOR)
+endif
+
+# shared library major/minor numbers
+LIBMAJOR=$(BASETARGET).1
+LIBMINOR=$(BASETARGET).1.2
+else
+TARGET1=$(AXTLS_HOME)/$(STAGE)/axtls.lib
+TARGET2=$(AXTLS_HOME)/$(STAGE)/axtls.dll
+STATIC_LIB=$(AXTLS_HOME)/$(STAGE)/axtls.static.lib
+CRYPTO_PATH=$(AXTLS_HOME)\\crypto\\
+endif
+
+libs: $(TARGET1) $(TARGET2)
+
+CRYPTO_OBJ=\
+ $(CRYPTO_PATH)aes.o \
+ $(CRYPTO_PATH)bigint.o \
+ $(CRYPTO_PATH)crypto_misc.o \
+ $(CRYPTO_PATH)hmac.o \
+ $(CRYPTO_PATH)md2.o \
+ $(CRYPTO_PATH)md5.o \
+ $(CRYPTO_PATH)rc4.o \
+ $(CRYPTO_PATH)rsa.o \
+ $(CRYPTO_PATH)sha1.o
+
+OBJ=\
+ asn1.o \
+ gen_cert.o \
+ loader.o \
+ openssl.o \
+ os_port.o \
+ p12.o \
+ tls1.o \
+ tls1_svr.o \
+ tls1_clnt.o \
+ x509.o
+
+include $(AXTLS_HOME)/config/makefile.post
+
+ifndef CONFIG_PLATFORM_WIN32 # Linux/Unix/Cygwin
+
+$(TARGET1) : $(OBJ)
+ $(AR) -r $@ $(CRYPTO_OBJ) $(OBJ)
+
+$(TARGET2) : $(OBJ)
+ifndef CONFIG_PLATFORM_CYGWIN
+ $(LD) $(LDFLAGS) $(LDSHARED) -o $(AXTLS_HOME)/$(STAGE)/$(LIBMINOR) $(CRYPTO_OBJ) $(OBJ)
+ cd $(AXTLS_HOME)/$(STAGE); ln -sf $(LIBMINOR) $(LIBMAJOR); ln -sf $(LIBMAJOR) $(BASETARGET); cd -
+else
+ $(LD) $(LDFLAGS) $(LDSHARED) -o $(AXTLS_HOME)/$(STAGE)/cygaxtls.dll \
+ -Wl,--out-implib=$(AXTLS_HOME)/$(STAGE)/libaxtls.dll.a \
+ -Wl,--export-all-symbols \
+ -Wl,--enable-auto-import $(CRYPTO_OBJ) $(OBJ)
+endif
+
+else # Win32
+CRYPTO_OBJ:=$(CRYPTO_OBJ:.o=.obj)
+
+$(TARGET1) : $(OBJ)
+ $(AR) /out:$@ $(CRYPTO_OBJ) $(OBJ)
+
+$(TARGET2) : $(OBJ)
+ cp $(TARGET1) $(STATIC_LIB)
+ $(LD) $(LDFLAGS) $(LDSHARED) /out:$@ $(CRYPTO_OBJ) $(OBJ)
+
+endif
+
+clean::
+ $(MAKE) -C test clean
+ -@rm -f $(AXTLS_HOME)/$(STAGE)/* *.a $(TARGET1) $(TARGET2)
+
diff --git a/libs/luci-lib-nixio/axTLS/ssl/asn1.c b/libs/luci-lib-nixio/axTLS/ssl/asn1.c
new file mode 100644
index 0000000000..4f2e6db240
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/asn1.c
@@ -0,0 +1,510 @@
+/*
+ * 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
+
+/* 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_iis6_oid[SIG_IIS6_OID_SIZE] =
+{
+ 0x2b, 0x0e, 0x03, 0x02, 0x1d
+};
+
+/* 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_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 = NULL;
+
+ 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;
+
+ 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 = 1;
+
+ if ((dn1 && dn2 == NULL) || (dn1 == NULL && dn2)) goto err_no_match;
+
+ ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 0;
+
+err_no_match:
+ 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 */
+}
+
+#endif
+
+/**
+ * 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_iis6_oid, &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/libs/luci-lib-nixio/axTLS/ssl/cert.h b/libs/luci-lib-nixio/axTLS/ssl/cert.h
new file mode 100644
index 0000000000..7a85d2d843
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/cert.h
@@ -0,0 +1,43 @@
+unsigned char default_certificate[] = {
+ 0x30, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0x40, 0x02, 0x09, 0x00, 0xf1,
+ 0xc3, 0x87, 0xc0, 0xd4, 0xf4, 0x57, 0xc3, 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, 0x30, 0x36, 0x30, 0x36,
+ 0x30, 0x37, 0x31, 0x31, 0x34, 0x34, 0x33, 0x32, 0x5a, 0x17, 0x0d, 0x33,
+ 0x33, 0x31, 0x30, 0x32, 0x33, 0x31, 0x31, 0x34, 0x34, 0x33, 0x32, 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, 0xd8, 0xe0, 0xbf, 0x15, 0xde, 0xea, 0xaf, 0xe8, 0xd5,
+ 0xfd, 0x0b, 0xa8, 0xa8, 0xb3, 0xd7, 0x46, 0x5d, 0xa7, 0x26, 0x6c, 0x0c,
+ 0xb5, 0xd9, 0xbc, 0xc6, 0xf8, 0xc0, 0x78, 0xd0, 0xf6, 0x56, 0x65, 0xf8,
+ 0x29, 0x48, 0x0e, 0x7b, 0x0b, 0xa6, 0x25, 0x7e, 0xe8, 0x7b, 0x79, 0x6f,
+ 0x38, 0xe5, 0xb5, 0xb7, 0xf4, 0xe0, 0x9c, 0x91, 0x60, 0xf4, 0x06, 0xf3,
+ 0x40, 0x1e, 0xf9, 0x91, 0x19, 0xa9, 0x2f, 0x47, 0x43, 0xb5, 0x9b, 0x1e,
+ 0xdc, 0xf6, 0xaa, 0x1c, 0x49, 0x79, 0x21, 0x28, 0xcb, 0xaa, 0x49, 0x73,
+ 0xd9, 0x09, 0x05, 0x4c, 0x02, 0xf2, 0x4c, 0x4d, 0x6c, 0x1c, 0x80, 0xa7,
+ 0x14, 0x91, 0x44, 0xfc, 0x12, 0xb3, 0xe1, 0xe7, 0xe3, 0x4f, 0x44, 0xba,
+ 0x8c, 0xc3, 0x74, 0x39, 0xe8, 0x4c, 0xd0, 0xd4, 0x4c, 0x24, 0x61, 0xb4,
+ 0x40, 0x95, 0x8c, 0xc0, 0x0a, 0xb7, 0x02, 0x39, 0x31, 0x85, 0x93, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x0b,
+ 0x47, 0x24, 0x52, 0x7d, 0xb6, 0x63, 0x78, 0xbc, 0x80, 0xdd, 0x87, 0x6c,
+ 0x90, 0x4c, 0x33, 0xc3, 0x5c, 0xa7, 0x97, 0x09, 0x1c, 0x09, 0x4f, 0x9b,
+ 0x6e, 0xb3, 0x5a, 0x3e, 0x46, 0x92, 0x1a, 0xc7, 0x87, 0x15, 0x59, 0xe1,
+ 0x88, 0x5c, 0xce, 0x6a, 0xe2, 0x96, 0xaa, 0x32, 0xec, 0xc2, 0xed, 0x78,
+ 0x8b, 0xe0, 0x90, 0x66, 0x93, 0x14, 0xc3, 0x98, 0xab, 0x33, 0x35, 0xd3,
+ 0x7d, 0x5d, 0x51, 0x0a, 0x9c, 0xb9, 0x10, 0x58, 0x47, 0x7a, 0x98, 0x95,
+ 0x64, 0xff, 0x4c, 0x5d, 0x82, 0x19, 0xf9, 0xea, 0x0f, 0x5e, 0x9a, 0xcb,
+ 0x32, 0x27, 0x64, 0xca, 0x6f, 0x58, 0x8a, 0xd0, 0xc0, 0x36, 0xf4, 0xb9,
+ 0x63, 0x34, 0xa5, 0xda, 0x36, 0x50, 0x36, 0x49, 0xd2, 0xb7, 0x3a, 0x21,
+ 0x33, 0x5b, 0x3e, 0xd6, 0x5f, 0x0c, 0x99, 0x83, 0xb7, 0xb2, 0xf7, 0x8b,
+ 0x44, 0xc4, 0x5e, 0x73, 0x41, 0xa9, 0x02
+};
+unsigned int default_certificate_len = 475;
diff --git a/libs/luci-lib-nixio/axTLS/ssl/crypto_misc.h b/libs/luci-lib-nixio/axTLS/ssl/crypto_misc.h
new file mode 100644
index 0000000000..97cb0f2d23
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/crypto_misc.h
@@ -0,0 +1,164 @@
+/*
+ * 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];
+ 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;
+ 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_OID 0x06
+#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_SET 0x31
+#define ASN1_IMPLICIT_TAG 0x80
+#define ASN1_EXPLICIT_TAG 0xa0
+
+#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_compare_dn(char * const dn1[], char * const dn2[]);
+#endif
+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/libs/luci-lib-nixio/axTLS/ssl/gen_cert.c b/libs/luci-lib-nixio/axTLS/ssl/gen_cert.c
new file mode 100644
index 0000000000..94b74903ca
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/gen_cert.c
@@ -0,0 +1,363 @@
+/*
+ * 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 "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/libs/luci-lib-nixio/axTLS/ssl/loader.c b/libs/luci-lib-nixio/axTLS/ssl/loader.c
new file mode 100644
index 0000000000..4232f7eec0
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/loader.c
@@ -0,0 +1,465 @@
+/*
+ * 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 "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 (strncmp((char *)ssl_obj->buf, begin, strlen(begin)) == 0)
+ {
+#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:
+ ret = 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 3
+#define IV_SIZE 16
+#define IS_RSA_PRIVATE_KEY 0
+#define IS_ENCRYPTED_PRIVATE_KEY 1
+#define IS_CERTIFICATE 2
+
+static const char * const begins[NUM_PEM_TYPES] =
+{
+ "-----BEGIN RSA PRIVATE KEY-----",
+ "-----BEGIN ENCRYPTED PRIVATE KEY-----",
+ "-----BEGIN CERTIFICATE-----",
+};
+
+static const char * const ends[NUM_PEM_TYPES] =
+{
+ "-----END RSA PRIVATE KEY-----",
+ "-----END ENCRYPTED 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_OK;
+ SSLObjLoader *ssl_obj = NULL;
+ 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-start);
+ 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)
+ goto error;
+ }
+ else if (base64_decode(start, pem_size,
+ ssl_obj->buf, &ssl_obj->len) != 0)
+ goto error;
+
+ switch (i)
+ {
+ case IS_RSA_PRIVATE_KEY:
+ obj_type = SSL_OBJ_RSA_KEY;
+ break;
+
+ case IS_ENCRYPTED_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:
+ 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--;
+ }
+
+ break;
+ }
+ }
+
+ if (i == NUM_PEM_TYPES)
+ goto error;
+
+ /* more PEM stuff to process? */
+ if (remain)
+ ret = new_pem_obj(ssl_ctx, is_cacert, end, remain, password);
+
+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/libs/luci-lib-nixio/axTLS/ssl/openssl.c b/libs/luci-lib-nixio/axTLS/ssl/openssl.c
new file mode 100644
index 0000000000..b6b955008b
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/openssl.c
@@ -0,0 +1,322 @@
+/*
+ * 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 "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/libs/luci-lib-nixio/axTLS/ssl/os_port.c b/libs/luci-lib-nixio/axTLS/ssl/os_port.c
new file mode 100644
index 0000000000..6a71000b47
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/os_port.c
@@ -0,0 +1,158 @@
+/*
+ * 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 WIN32
+/**
+ * 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/libs/luci-lib-nixio/axTLS/ssl/os_port.h b/libs/luci-lib-nixio/axTLS/ssl/os_port.h
new file mode 100644
index 0000000000..262c4dd705
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/os_port.h
@@ -0,0 +1,207 @@
+/*
+ * 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 SOCKET_BLOCK(A) u_long argp = 0; \
+ ioctlsocket(A, FIONBIO, &argp)
+#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.
+ */
+#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 /* 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 <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) close(A)
+#define SOCKET_BLOCK(A) int fd = fcntl(A, F_GETFL, NULL); \
+ fcntl(A, F_SETFL, fd & ~O_NONBLOCK)
+#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/libs/luci-lib-nixio/axTLS/ssl/p12.c b/libs/luci-lib-nixio/axTLS/ssl/p12.c
new file mode 100644
index 0000000000..6ed92e431d
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/p12.c
@@ -0,0 +1,486 @@
+/*
+ * 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 "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 all_ok = 0, 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;
+ int error_code = SSL_ERROR_NOT_SUPPORTED;
+ 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)
+ {
+ error_code = 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))
+ {
+ error_code = SSL_ERROR_INVALID_HMAC;
+ goto error;
+ }
+
+ all_ok = 1;
+
+error:
+ free(version);
+ free(uni_pass);
+ free(auth_safes);
+ return all_ok ? SSL_OK : error_code;
+}
+
+/*
+ * 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/libs/luci-lib-nixio/axTLS/ssl/private_key.h b/libs/luci-lib-nixio/axTLS/ssl/private_key.h
new file mode 100644
index 0000000000..96a5253312
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/private_key.h
@@ -0,0 +1,54 @@
+unsigned char default_private_key[] = {
+ 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xd8,
+ 0xe0, 0xbf, 0x15, 0xde, 0xea, 0xaf, 0xe8, 0xd5, 0xfd, 0x0b, 0xa8, 0xa8,
+ 0xb3, 0xd7, 0x46, 0x5d, 0xa7, 0x26, 0x6c, 0x0c, 0xb5, 0xd9, 0xbc, 0xc6,
+ 0xf8, 0xc0, 0x78, 0xd0, 0xf6, 0x56, 0x65, 0xf8, 0x29, 0x48, 0x0e, 0x7b,
+ 0x0b, 0xa6, 0x25, 0x7e, 0xe8, 0x7b, 0x79, 0x6f, 0x38, 0xe5, 0xb5, 0xb7,
+ 0xf4, 0xe0, 0x9c, 0x91, 0x60, 0xf4, 0x06, 0xf3, 0x40, 0x1e, 0xf9, 0x91,
+ 0x19, 0xa9, 0x2f, 0x47, 0x43, 0xb5, 0x9b, 0x1e, 0xdc, 0xf6, 0xaa, 0x1c,
+ 0x49, 0x79, 0x21, 0x28, 0xcb, 0xaa, 0x49, 0x73, 0xd9, 0x09, 0x05, 0x4c,
+ 0x02, 0xf2, 0x4c, 0x4d, 0x6c, 0x1c, 0x80, 0xa7, 0x14, 0x91, 0x44, 0xfc,
+ 0x12, 0xb3, 0xe1, 0xe7, 0xe3, 0x4f, 0x44, 0xba, 0x8c, 0xc3, 0x74, 0x39,
+ 0xe8, 0x4c, 0xd0, 0xd4, 0x4c, 0x24, 0x61, 0xb4, 0x40, 0x95, 0x8c, 0xc0,
+ 0x0a, 0xb7, 0x02, 0x39, 0x31, 0x85, 0x93, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x02, 0x81, 0x81, 0x00, 0x94, 0x07, 0x72, 0xe5, 0xbe, 0xad, 0x79, 0x3b,
+ 0xf7, 0x33, 0x2c, 0x8e, 0x05, 0xf8, 0x1a, 0x6b, 0xd0, 0xe8, 0x91, 0xf5,
+ 0x16, 0x07, 0xd9, 0x82, 0x5c, 0x5c, 0xd5, 0x22, 0xa1, 0x9e, 0x42, 0x02,
+ 0x7f, 0x8b, 0xcd, 0xbe, 0xf4, 0x85, 0x52, 0xf6, 0x2c, 0xd5, 0x09, 0xd2,
+ 0x2c, 0xf4, 0x2c, 0xf6, 0x07, 0x85, 0x80, 0xf9, 0xdc, 0xd0, 0xcc, 0x3f,
+ 0x22, 0x31, 0x15, 0xf3, 0x49, 0xf2, 0xb5, 0xe2, 0x69, 0x99, 0x04, 0x04,
+ 0x49, 0x21, 0xdb, 0x9f, 0xa1, 0x54, 0x5a, 0xfa, 0xe4, 0xd9, 0xf9, 0x07,
+ 0x05, 0xff, 0x9a, 0x65, 0xa4, 0xeb, 0xf2, 0x47, 0xce, 0x56, 0xc7, 0x72,
+ 0x49, 0x48, 0x5c, 0xe8, 0x14, 0xd7, 0x8f, 0x25, 0xcc, 0x49, 0x29, 0x06,
+ 0x6a, 0x54, 0x7b, 0x17, 0xdc, 0x9e, 0xd4, 0x53, 0xf0, 0xf5, 0x9e, 0x85,
+ 0x25, 0xa1, 0xeb, 0x3d, 0xe9, 0x2f, 0xb9, 0x9c, 0xf6, 0xe1, 0x80, 0x81,
+ 0x02, 0x41, 0x00, 0xee, 0x02, 0x78, 0xc7, 0x78, 0x85, 0x04, 0x97, 0xcc,
+ 0x36, 0xbd, 0xd6, 0x11, 0xe2, 0xc7, 0x39, 0xd9, 0x34, 0x51, 0x72, 0x6f,
+ 0x8a, 0x0f, 0xcd, 0x88, 0x32, 0x33, 0x9b, 0xc7, 0xa7, 0x03, 0x77, 0xd9,
+ 0x82, 0x35, 0xb6, 0xdd, 0x1f, 0xc2, 0xc1, 0x13, 0x40, 0x83, 0x55, 0xeb,
+ 0x60, 0xeb, 0x81, 0x8e, 0x0c, 0x16, 0x62, 0xb4, 0xb4, 0x3c, 0xeb, 0x08,
+ 0x80, 0x9c, 0x79, 0xd3, 0x38, 0xca, 0xf1, 0x02, 0x41, 0x00, 0xe9, 0x45,
+ 0x5f, 0x2e, 0x16, 0xcc, 0x93, 0x50, 0x40, 0xb6, 0x79, 0xbc, 0x38, 0xe0,
+ 0x56, 0x68, 0x50, 0xd3, 0x2f, 0x73, 0x8c, 0x8c, 0x2a, 0x0e, 0x81, 0x4a,
+ 0x8a, 0xbb, 0xcc, 0xf0, 0x64, 0x34, 0x46, 0x9f, 0x07, 0x7d, 0x22, 0xb6,
+ 0xf9, 0x46, 0xac, 0x57, 0x23, 0x8c, 0x1e, 0xeb, 0xd3, 0x05, 0x4d, 0xa8,
+ 0x83, 0x6a, 0x67, 0xf6, 0xa6, 0xb1, 0xab, 0x8e, 0xc1, 0xef, 0xef, 0x7d,
+ 0xf0, 0xc3, 0x02, 0x40, 0x2f, 0xc6, 0x59, 0x3e, 0x18, 0xe8, 0x02, 0x73,
+ 0x01, 0xef, 0xdf, 0x0d, 0x30, 0x4b, 0xe8, 0x17, 0xa9, 0x8c, 0xc1, 0xe8,
+ 0x89, 0x91, 0x19, 0xf8, 0xf4, 0xa4, 0xb7, 0x0d, 0x46, 0xf7, 0x34, 0x50,
+ 0x03, 0x5e, 0x0a, 0xb0, 0x29, 0x14, 0xae, 0x00, 0x19, 0x80, 0x32, 0x9c,
+ 0xb5, 0x81, 0x9f, 0xe4, 0x42, 0x82, 0x14, 0xa0, 0x3d, 0x8b, 0x8c, 0x4a,
+ 0xd5, 0x4b, 0x13, 0x9d, 0xb4, 0x93, 0x4a, 0xd1, 0x02, 0x40, 0x64, 0x8c,
+ 0x83, 0x77, 0x61, 0x5a, 0x73, 0x11, 0x3f, 0xa3, 0xa8, 0x1b, 0x8a, 0xc4,
+ 0xa0, 0x5a, 0x3c, 0xa4, 0x9b, 0x2a, 0x8a, 0x65, 0x8c, 0x67, 0x4e, 0x31,
+ 0xac, 0x55, 0x41, 0x04, 0x49, 0x9d, 0x02, 0xe7, 0xdf, 0x99, 0x7f, 0xd2,
+ 0x30, 0xe6, 0xd6, 0xb8, 0x84, 0xd9, 0x0c, 0x27, 0x08, 0x81, 0x9b, 0xb4,
+ 0xcc, 0x58, 0x9c, 0x51, 0x84, 0x0e, 0xc7, 0x6d, 0x34, 0x89, 0x50, 0xc9,
+ 0x0f, 0x73, 0x02, 0x41, 0x00, 0xda, 0xde, 0x5e, 0x1a, 0xac, 0x1d, 0x1d,
+ 0xd7, 0xb9, 0x65, 0x26, 0x00, 0xf5, 0xd4, 0xe4, 0x28, 0x84, 0x86, 0x2f,
+ 0x00, 0x9c, 0x41, 0x00, 0x52, 0xe1, 0x47, 0x91, 0xc0, 0x52, 0x05, 0x4e,
+ 0x0f, 0x2f, 0x0d, 0xca, 0x9b, 0x3d, 0x89, 0x41, 0xbf, 0xee, 0x9f, 0xa1,
+ 0xe6, 0x9d, 0xa4, 0xeb, 0x45, 0x7f, 0xe3, 0xcb, 0xa4, 0x6b, 0x0a, 0xe2,
+ 0x7e, 0xb0, 0x87, 0x5c, 0x40, 0xb1, 0x51, 0x11, 0x1d
+};
+unsigned int default_private_key_len = 609;
diff --git a/libs/luci-lib-nixio/axTLS/ssl/ssl.h b/libs/luci-lib-nixio/axTLS/ssl/ssl.h
new file mode 100644
index 0000000000..539d0a3058
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/ssl.h
@@ -0,0 +1,474 @@
+/*
+ * 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>
+//#include "crypto.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
+
+/* errors that can be generated */
+#define SSL_OK 0
+#define SSL_NOT_OK -1
+#define SSL_ERROR_DEAD -2
+#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_NOT_SUPPORTED -274
+#define SSL_X509_OFFSET -512
+#define SSL_X509_ERROR(A) (SSL_X509_OFFSET+A)
+
+/* 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
+
+/* 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.
+ *
+ * @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 blocking call - it will finish when the handshake is complete (or
+ * has failed).
+ * @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.
+ * The socket must be in blocking mode.
+ * @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.
+ * The socket must be in blocking mode.
+ * @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.
+ *
+ * A full handshake needs to occur for this call to work properly.
+ *
+ * @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 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/libs/luci-lib-nixio/axTLS/ssl/test/Makefile b/libs/luci-lib-nixio/axTLS/ssl/test/Makefile
new file mode 100644
index 0000000000..56c711f197
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/Makefile
@@ -0,0 +1,97 @@
+#
+# 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.
+#
+
+all:
+
+AXTLS_HOME=../..
+
+include $(AXTLS_HOME)/config/.config
+include $(AXTLS_HOME)/config/makefile.conf
+
+ifdef CONFIG_PERFORMANCE_TESTING
+all: performance
+endif
+
+ifdef CONFIG_SSL_TEST
+all: ssltesting
+endif
+
+include $(AXTLS_HOME)/config/makefile.post
+
+ifndef CONFIG_PLATFORM_WIN32
+performance: $(AXTLS_HOME)/$(STAGE)/perf_bigint
+ssltesting: $(AXTLS_HOME)/$(STAGE)/ssltest
+LIBS=$(AXTLS_HOME)/$(STAGE)
+
+$(AXTLS_HOME)/$(STAGE)/perf_bigint: perf_bigint.o $(LIBS)/libaxtls.a
+ $(CC) $(LDFLAGS) -o $@ $^ -L $(LIBS) -laxtls
+
+$(AXTLS_HOME)/$(STAGE)/ssltest: ssltest.o $(LIBS)/libaxtls.a
+ $(CC) $(LDFLAGS) -o $@ $^ -lpthread -L $(LIBS) -laxtls
+else
+performance: $(AXTLS_HOME)/$(STAGE)/perf_bigint.exe
+ssltesting: $(AXTLS_HOME)/$(STAGE)/ssltest.exe
+
+CRYPTO_PATH="$(AXTLS_INCLUDE)crypto\\"
+AXTLS_SSL_PATH="$(AXTLS_INCLUDE)ssl\\"
+
+CRYPTO_OBJ=\
+ $(CRYPTO_PATH)aes.obj \
+ $(CRYPTO_PATH)bigint.obj \
+ $(CRYPTO_PATH)crypto_misc.obj \
+ $(CRYPTO_PATH)hmac.obj \
+ $(CRYPTO_PATH)md2.obj \
+ $(CRYPTO_PATH)md5.obj \
+ $(CRYPTO_PATH)rc4.obj \
+ $(CRYPTO_PATH)rsa.obj \
+ $(CRYPTO_PATH)sha1.obj
+
+OBJ=\
+ $(AXTLS_SSL_PATH)asn1.obj \
+ $(AXTLS_SSL_PATH)gen_cert.obj \
+ $(AXTLS_SSL_PATH)loader.obj \
+ $(AXTLS_SSL_PATH)openssl.obj \
+ $(AXTLS_SSL_PATH)os_port.obj \
+ $(AXTLS_SSL_PATH)p12.obj \
+ $(AXTLS_SSL_PATH)x509.obj \
+ $(AXTLS_SSL_PATH)tls1.obj \
+ $(AXTLS_SSL_PATH)tls1_svr.obj \
+ $(AXTLS_SSL_PATH)tls1_clnt.obj
+
+$(AXTLS_HOME)/$(STAGE)/perf_bigint.exe: perf_bigint.obj
+ $(LD) $(LDFLAGS) /out:$@ $? $(CRYPTO_OBJ) $(OBJ)
+
+$(AXTLS_HOME)/$(STAGE)/ssltest.exe: ssltest.obj
+ $(LD) $(LDFLAGS) /out:$@ $? $(CRYPTO_OBJ) $(OBJ)
+endif
+
+clean::
+ -@rm -f $(AXTLS_HOME)/$(STAGE)/perf_bigint* $(AXTLS_HOME)/$(STAGE)/ssltest*
+
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_key.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_key.pem
new file mode 100644
index 0000000000..7c8ac8af28
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICWwIBAAKBgQCnZdk20fYWh8O6kDTt0AuJWyp0YIrb7W1UNNMPXI5wA4J59IVj
+Nmk5wocm9+Hqzbg7rORAN/mHPBhzLAjhnm1HODs36hW15DtbDkkH4wCM/Tsyv79m
+n0xq1V6peK3t9vi2D4p/IRjHkYR2jm+BeknopijhY0kHHfpGTHa2DnVirwIDAQAB
+AoGAd4Ia5SxYiBU9A0BYyT8yPUm8sYELIaAL4YYk+F6Xwhh/Whnb8MyzquzaGFP4
+Ee30jYYNHlvX5VheDDtvy8OTN5FgKNNdzvW15iA4Hxje04ZI7W87G7OIxm7aYRid
+sG4XqZBtsOdj33IRd9hgozywGJ2qRqS6nn2KxRv1w07RniECQQDZAlKxijdn+vQ7
+8/8mXzC+FwQtzeTUCuLrBJcos9I/591ABoxYkWcYLxpFqgCEVwb1qfPBJkL07JPt
+Fu6CTnBFAkEAxXmUBs47x5QM99qyBO5UwW0Ksrm/WD4guaaxzQShMt/HzgJl613z
+/x4FtxiQJHAr6r2K0t5xTJx89LVKuouYYwJAImue6DAvJ5wDfzrtXo28snn+HLHK
+uONdKL/apgcXszE4w74GJsoxWwGlniUf3d3b6b1iP2GtPyIDOJjpjduZLQJAE4jS
+VtYB3d1MZxxQLeKxqayyuTlcr0r+C79sqT5C//hZGIzuLhlOMLd0k0cvwxsBjSgQ
+2ok8pfp49fAVI1z5xwJAVmJgLc/mSti5A2q3c8HW8qvMJEDPWbpb7p8pg4ePtpa8
+EE3TO4O4J2H+k40C397km4yZXdkNQsiT1zVljJZpiw==
+-----END RSA PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_x509.cer b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_x509.cer
new file mode 100644
index 0000000000..9c9936b8e9
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_x509.cer
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_x509.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_x509.pem
new file mode 100644
index 0000000000..86f659710c
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.ca_x509.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB3zCCAUgCCQCdbnM4pjqlWjANBgkqhkiG9w0BAQUFADA0MTIwMAYDVQQKEylh
+eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
+MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMDQxMjAwBgNVBAoTKWF4VExTIFByb2pl
+Y3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQCnZdk20fYWh8O6kDTt0AuJWyp0YIrb7W1UNNMPXI5wA4J59IVj
+Nmk5wocm9+Hqzbg7rORAN/mHPBhzLAjhnm1HODs36hW15DtbDkkH4wCM/Tsyv79m
+n0xq1V6peK3t9vi2D4p/IRjHkYR2jm+BeknopijhY0kHHfpGTHa2DnVirwIDAQAB
+MA0GCSqGSIb3DQEBBQUAA4GBAB0LgNo0oCcwIie5plgwwFybQ8x95q6e3wndM/Mp
+3gjcAFbGuchpo3dfFlTcRI0KyERb3q1MVxPM4sff9nT7EdHVyK9s8/ITkP2dcTKc
+flbcTEfJVIeM8L2P5F41Hvn9GuGcMW8EmsC06gdbp1LLnqsdrXdMNBsAUBXfgPrU
++UcZ
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.device_key b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.device_key
new file mode 100644
index 0000000000..4e981d143e
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.device_key
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.device_key.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.device_key.pem
new file mode 100644
index 0000000000..2bcf5e37b3
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.device_key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDUIg4NEiu/diDAlbsWbTAhMKw4iBf2X5ohGJdTO6vhGQdEkhBR
+Bgzdl9+0LbVDJY8YStUghwnuztT+IpNCrUtXtRK8Cn3QP+buzSe2ZGPVoEJIbvV/
+QudK/WuUDyTNSRTtW4S3RO36KqtbT6xh1QGTXV3I8sp7qwmcysklqZW8GwIDAQAB
+AoGBAKBEDkuPw9+Ftp7pQIxj963LoQGgyEHJ3p9Mfd9TQLrydsw2cf9Uy9mKiWcN
+9VkCgkZ/Gt/VRgrW1pIduxXv6O+8S14An+2mTayy3Ga1N6MulD7OHQP9kqR4j8TT
+xaYPR/1skjhQ+Y0Uw4NEa3OkQp6lAUEp1aVX/mTfIZBguaUxAkEA/H543Ha6wbUV
+iB+pHaBgj1nzarmuEey6kqqs7X0zoZory1X6bdpJ6l0/4qICa6aq+pt/7ywJCNoI
+CPK3mL2zGQJBANcUHRBe7/HRWrJNIqB2WDA/gJshq4xOAiIBXWk1wpabvpkCnUjQ
+rip5CAL3hXDnCQswZxRN/v7B4IlSxkKiY1MCQQCsL0MUdRMejfLFBXI6defjWiAZ
+I86FAr6oziNnQP44sf4zh8pjp3zIihbK4lhsORhYFjrES29NzgG0uHBjhNnhAj97
+gBEwVVNyh8SMnb5EZbA+BDjU24CmECUpYZ9Bypzx3nyTX+zw4uMfgGAZVAhLzF5l
+DmYiQqcpoipMsDsoCBcCQQCxBYSicXIPG8G6ZuFbgXFcZR7llgq74mbhfGuVEGbP
+qS6ldhJb/IG9O3MFlRwdU44YyJ8QGpBKWF94OpIduF6w
+-----END RSA PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.encrypted.p8 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.encrypted.p8
new file mode 100644
index 0000000000..8b0a7eb411
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.encrypted.p8
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.encrypted_pem.p8 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.encrypted_pem.p8
new file mode 100644
index 0000000000..19ca3c5eae
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.encrypted_pem.p8
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBfTAcBgoqhkiG9w0BDAEBMA4ECN+YmhCv0ILdAgIIAASCAVu0QEfMkp0xUsNq
+0Ek4Nsa/uxcs8N/2P7Ae7qCakkvsdRvvPPH0y+wuj5NgrG6WpPeeEx9fI2oNNTfC
+pwncH0Xm99ofVrgMX6XC45LDZtzXNSZd4TdBP6xvlYXbuGegp5GPJ8emzscHCFhC
+JfPHemRAcB7DhiWukPosuSUr5R8OluEMJrQLHuQtlDAvMjLEI98lSchPxF8LKCk3
+SS2uCcmc+4WiR0nHG9BOaGi38+PytHAnbfo1mfVSQzLfgLicMAVGysfQ9QOgpQOO
+ygYfM/s7Duwbl0rshyXVJP+7BpYJnPtHvO4BTiizU7ZEr4WBiEnnANDrupSdsxeH
++cxZo70YJVdoPdgMd2ke6EIkUhp7HughFg+okldlEtJA4muKeEzwAxZu0TqxOtZ8
+UYRS4Ygk+rN7Y0qTKSYwSkrFBwUDkpctYjRUOeAZ/mYMKWmMn1ejAb5Is7bjEIxl
+tw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_1024 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_1024
new file mode 100644
index 0000000000..5b6ba1d037
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_1024
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_1024.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_1024.pem
new file mode 100644
index 0000000000..4f5ad4ece6
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_1024.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDY4L8V3uqv6NX9C6ios9dGXacmbAy12bzG+MB40PZWZfgpSA57
+C6Ylfuh7eW845bW39OCckWD0BvNAHvmRGakvR0O1mx7c9qocSXkhKMuqSXPZCQVM
+AvJMTWwcgKcUkUT8ErPh5+NPRLqMw3Q56EzQ1EwkYbRAlYzACrcCOTGFkwIDAQAB
+AoGBAJQHcuW+rXk79zMsjgX4GmvQ6JH1FgfZglxc1SKhnkICf4vNvvSFUvYs1QnS
+LPQs9geFgPnc0Mw/IjEV80nyteJpmQQESSHbn6FUWvrk2fkHBf+aZaTr8kfOVsdy
+SUhc6BTXjyXMSSkGalR7F9ye1FPw9Z6FJaHrPekvuZz24YCBAkEA7gJ4x3iFBJfM
+Nr3WEeLHOdk0UXJvig/NiDIzm8enA3fZgjW23R/CwRNAg1XrYOuBjgwWYrS0POsI
+gJx50zjK8QJBAOlFXy4WzJNQQLZ5vDjgVmhQ0y9zjIwqDoFKirvM8GQ0Rp8HfSK2
++UasVyOMHuvTBU2og2pn9qaxq47B7+998MMCQC/GWT4Y6AJzAe/fDTBL6BepjMHo
+iZEZ+PSktw1G9zRQA14KsCkUrgAZgDKctYGf5EKCFKA9i4xK1UsTnbSTStECQGSM
+g3dhWnMRP6OoG4rEoFo8pJsqimWMZ04xrFVBBEmdAuffmX/SMObWuITZDCcIgZu0
+zFicUYQOx200iVDJD3MCQQDa3l4arB0d17llJgD11OQohIYvAJxBAFLhR5HAUgVO
+Dy8Nyps9iUG/7p+h5p2k60V/48ukawrifrCHXECxUREd
+-----END RSA PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_2048 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_2048
new file mode 100644
index 0000000000..0af642de23
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_2048
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_2048.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_2048.pem
new file mode 100644
index 0000000000..beddb721bf
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_2048.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAwqC/2/rPcAZEs5/ejT3ZL8Q3Pfdna2WC44i6HYCnCnbOIcW+
+6Xub2IXGwRwQBFy+mRE9WjqJ8kuOEkSt6e+8wAhLdag7WXJ6cxoag110t5FEHSyd
+GfvFFyUNjMJhLd+EmaQTTpEv9MJPJj0Zdruh1EjyRxa4HJmiD9t7XmWyCfSmM0qM
+kgJ0J6s62rRMBX+l/NEEX2VzJugdZAU671RWYOncuxX/2jUYlvIqI1l3SP8acMU5
+BtfLsYMj08lNHOjgZCPRwkdjsl6U5EqIizKZygw1FNugVEDHnL2MAYXwqzX3pGr/
+72Biy+J4TSH6lt0stszS5m8BirMgYr2FFHslrQIDAQABAoIBAQDBTa0gzEupJOCp
+UvhUagBDO+vuBMJX3XuRh6PqV3QQpYz36BJEjXttIvkTpU6XNpIrLv8zlX6bAsW5
+iTL+bRiX1eU0l4FSxqutlFiO7oxVIdd37m6edvv6j9eUXR7t09k8S8TNPNBXlYHN
+JdQbpCIH2OehCYSVC1X1z/UI/ZJF5VSn7UsYgwReK102svfHtll85K0TgHMir9Rx
+Dlh0vYx3IJi2nDOTyJ4JekkyEAcYd3D6JUd0JujcN3Ev3EOsns5GXzN6KYvinmYf
+Z1bA/HEMNb9ZS9bdsoAvyeJAeGp8ejzuJVHGL0kATgrAamb58fPS+A8Guk5eN5KY
+5zvzNrJVAoGBAPVWvPrDOJX2ZI7poJ269xFteTWWIYA+r+YRRkhMBMcD08H5gs6e
+QMWU9w8qjgSmbNkx8skkhn/gV5R3CbVYYRR2osrZIoOayWAsJmY0bHFTIvooYhfp
+3lPVNIPzUpRObFksamtrsK+zpx5qOdigNhComXLsGWKfrN9Yvkb7YzIDAoGBAMsV
+4UVH9WH0IKV1vx3QtrGEb69SZMpbmM8ZsPvaPgq00In9udY4w5V2ZygfTiq0ChUY
+fYy6BeO6Gyp2DSABdz1AUH+0wcnNrHJghFtxtsq4Thu4MHU6ftc+JCGfSeWUapfh
+KiHS0TEguRFcYSHnM1IDEiU4aTHY59FRUWMI2hKPAoGAIVfviTk9GIyLMC0qaiV9
+7L1vKsxDs1VRvLf+UFcckxu/DO7nS0OQ1Amh5krHUHR5+K7kK1gue3S3EnN3O1FO
+qGRTTbRjD3XbBpoZgeyADIrbBxqz8kITuFsSrxhD0eoyqY/yyrSxJ8AH54dSY1Gq
+52qyqD7UWGYRLa229pi165cCgYAd7/rGWMY+i1toqMPkpEjaQFiqcq3y+q+7D+F8
+Lv7oWyFGxkVn4/RJCyxHyN2gA+xckcCoRx/pIx0wFDj5F945BEsZmE7c7dnW/o1k
+YY39sk+pXGygS2A5YKq43h9pnYhdHU81rzsxT86YVZLoCYoSM+uv2vH+7Ce4PpGN
+1Nc41wKBgDUrYyfDB1RzdB63FwPRax5uLjewnuMXyZhy70ZkiGh0XBuQt2aCLeCZ
+HpAyGcJryxdDFYA+UwJoSWjaW9ku0lp+GxX1F+cResrRHTi70w9czwGVaKmcG3kI
+fFjG7w8nkiw5J7IRH7SxmNbmAv8L0Iy6jvoWLFB+EdUGWllkjCmJ
+-----END RSA PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_4096 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_4096
new file mode 100644
index 0000000000..c205382ab7
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_4096
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_4096.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_4096.pem
new file mode 100644
index 0000000000..9929467f45
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_4096.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEA/Ce0mV0qytAwDPrjXRBlUh2gdKs2thDw3N18owXVrSUFq9Sw
+AaMNrmep9DR9MEALcdMm3GCEJ7sOOiEQcqTz25di36WJDe+jo1z5nD2XZsPIsp9+
+k51Vz+W3B4vsXJAgzV+XZbmv9L0598VEwkpeI3Uc9et8ZhGvDPoHZyBQG1KAj6h3
+AKZ1+NthrhajxlrndQZ5Du/R5DSUQOBcCHHdzZgihdfF97Yn/kp1mele1ElZMlqg
+BtpDi1TEQJ9XBtjCW0epFAm5THQ3gMx5DCcqB/cNYdZWqpZ0AuwATm61+46m4fFK
+g3YAYPOi/74aKFuIQBw/lc8W//SV1x8SL/hf2XIdvSa9QhroNN0d3Xu2EUQzXZxo
+PRMKzOqKfwlZW7ozT6hFBwPMh8yfhoPugq2TvqBjke1s3gmvwTgEcf+gY97qXiZC
+X5bh/ehmnZ7vIblYFUD2yMlsKaXGJYweh3WKJlQnh71wQUg2Mxa6ig8ijrEozNlw
+YfPCQFrNLqQfJOwdx90dy7hpUyUn1wo39p6wmC6n9ex4zeKbO4ndSp+/AJ+d5Qp8
+zoMzwneYV9LBQG8ry4uwzDkSWKb/WghsEbQ9O3sGIuI13SlT/B64v3bLb5AHagI8
+zS3kPsshjKhkcc2W9MKRBU2wIeCsNS052kaUq3rPMSBROrALmLk3en/Dq48CAwEA
+AQKCAgEArPMy7So5Cqjm/FAtGI0BYeRORReWTCSsgGEudsauu7a0ABq+qjDDVodl
+y8kgwLJ85xKUCf3tRy8G4BoDpQ688DYSrCFnMvbWP1urHV4ldWf+RX4eHHODAzil
+ZHi1ovt8dEEHn89P/8a2dtqIgdbuYNWYCpj9Vyjz7yujXjmMmGDrKx26meiS7CDV
+C8odhRSewuawq+0UArmJokIA/g3Tu4uIylKoR3JaVhGOPgYSc/rnQiFkt66HO47l
+mQlxcJHGJUOulb7hqK3hz+bvc8V9D7+FH0EbaqANbF+hCirniWZb0odku2x5cAZM
+G6uxV1MIzihR+Jf1R5PkHowCNoLegfM45tnuadP1+8Kezv1SsqkrkMEwfb0QN19C
+2+bmnwYXagUgg/A2q2Shg9h4/3cpwdrDzGHD8IttGlzLR8HnlHkcAK3qRNqy9h60
+JDEW/tOurUSZBXjU9ZyoZSukcK3+yUjCDWS92wMOBlUQGh4/HCOOizahe6lhn2nT
++jkBvl38c+7GBKR0VyCisFi++FukMBbyU/hNNFByZxOj0b/+YVYI0qwM5oDzLhJH
+69/VhxMx0xVt9/kOOO3yhdGjKCZztPZZm5mg2OzzXmf4im+hPSg0/OrdXrVNk4v/
+w7ouUQHSa3+rAAu8BJFF2rTWA7rjecVEnk6c77I6dEVYXdCfz8kCggEBAP+IJLHo
+7Cs51qPcRKQc633phJa3pFGf6O8xN6pl8z1ZQX0voZyROKJLTytSH+zmPdmggUeg
+7CRoV8BKY49YiOxO2Kx8BPfftItS9yvA3O9ztcdzQa72nYusMWwvj0yFU8DbYfnx
+yYw59F/1pdPKFN83Sj4MJAOb4nAxBP1GiZvsPAgcTpf/197NLNHwUDdk/TXDtTLa
+lx4uTn/SJDQuvsCCLBKyx7FdN5NPRN2kIKUWZLd7HRu2EhcSlATwf4TUPZz7atKN
+2FD0svErpPOAspNPtnNj3RgeunGVqS2oi/XueuveNNCYLkcV8/UaZm85LBrPoEre
+23qK9/ZN0SD534sCggEBAPyd+nD71pScrM0TI4Lc3jMNUKeZj3sT5rlhlkWlARhQ
+WPEWYYg5vs3zDiRpG4Xy3n9ey+M6Tuw+/XpcJZxhrLYFOqparxXPP4qc+3EvtzpF
+OskLR/2/bVnESf6+pQspmwW6G4IJ9vOmIJeUj9zeU0txuxKkjhAmInCnMxJOlYRm
+xeLymuo5LZxrXmSXcX4cyZ0/4bF2L3IE5vH7ffdWXWYzW9wP7M4sFp+0iKjHuhC1
+gB6Qg0Mp0TVNUt0ZEelFLEJdA2lbbZ5yHhNXuhOxW/l3ASSe9tjTpy7yBSwBOpFG
+l7QGISfJVEFfjyn7yWBYj5LDGnitlP4TtN8zyy6cJI0CggEAPRwY8ncqq7e8Thmq
+TLkh1E3ZSJYIdQDSGwnhLx4MirpiwAZ5FtFgAugRueF9AxGY7wfEgxXIA3j0q2be
+4nQg4qqEhNNv+LuGGN+xfsQz0gwRB+7XYXlW+gUnGKFTGtCz0+ZjSvv44FEn0R8V
+Fk44qZ02YxpSLo7EG2KNt+h7lk9rl+D1JsKnpH/a3SYkeOrs50OzfMLr6urWGRlv
+UQ9wzOcUlTAuM4uAc/k8FelfaTuuwHZv4qWrM9tcjMXbKS/8wCMcS9hiSBINDUIL
+w7QegL5KetQCFveaTPmmqOWq+xiaSvgsF0qdnqBwZEh5ANZiZtMKmX0sbeT4Ie5A
+OiunuwKCAQBlSlrvDqu9rwzCtdfZUwJtaftbGIGlkhdDYdPFXSIRQ7ZGBPlai/zr
+y3dyNgrpLLb2T2ZlWC3pIGC2vVf/WlLMMVCSmgX2MsGBrOxNOBq57KRjlHhrUGRi
+SAh7cqnuzeHw6+y3uZMhow0Semks4KB5ccLW+NBVvVS14vThdE0TZ7oVA74GCKM3
+Qv34S5kgPh7BRKoUZBUmHL0VbgfWMvUEU7eTh3cmPBteMh9RvbPnmz8iAkP/nDbc
+roJ5UOITrL7QZUdG6XgMvik9DEH6P3Vnk8YLjwnfaw5wDm7wdBWtxqZxcru8nkeA
+ZvaamPDoBtqauExW8xL4xaISlUv1BnrJAoIBAQCiEZk93GeRzYJFCO1YafsGYueX
+Pffgd9wM2TpObgaEw8OIfEpGQKDiR35fb0uVzNyI5fVU5D5tP0b3LfvtQXV12ryQ
+sVTA5YJcb8mRuUGy/AkjL54kNiZthUnlGHQjY3lqSyI1r5WxRIZBBRn5+g1eSZVq
+CYCGjEryKm7vw8Qcvy1+H2crcZ0rRyLTcfFCr1ZXlyEZu48ScOtxcIDHc7j4J0LO
+Peq2z0tbBojGkxFLX94J7zpRkWMPX9VHorEavDv7ZJwtgoXn3Lom0xHhO+JQaxY9
+FtJ79Ps9+SquXAnkhna4bbkrqrPM3+MAAV/S7bd1T1/8d4YiRQyaMHGS4Yr8
+-----END RSA PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_512 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_512
new file mode 100644
index 0000000000..7ae50f23bd
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_512
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_512.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_512.pem
new file mode 100644
index 0000000000..1e2fb41f87
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_512.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBPQIBAAJBANE7MF+pAUI9hm1yvkBuUcFJf1d1oS025cE9DyAa0SNt+nTSPiOw
+cPygat7sQYiE/lQVa2HFFmK4k0HxTz3/Lr0CAwEAAQJBAJF5xO2ONajX3GK2+B8W
+VVO+BYNK71DfranJCX46BxXI/Ra7wOSY0UWZYHVsZGWJxx41os0UBTg5FRq4DwWW
+AQECIQDo69eo39iQqjwhpAQxatMh2CWYT7gokyu56V+5o2V3fQIhAOX2b+tQxDsB
+w0J9UDN6CdwI5XbzveoP5fHTPS9j4rhBAiEA3c+y6Zx6dZHYf8TdRV5QwDtB2iGY
+4/L7Qimvwm6Lc1UCIQDDXWrVsocTTjsReJ6zLOHFcjVnqklU2W7T1E8tvKE3QQIh
+AMRpCFM7MrS2axuc8/HzGkqW/3AlIBqdZbilj5zHd2R0
+-----END RSA PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_aes128.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_aes128.pem
new file mode 100644
index 0000000000..8961bd9a59
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_aes128.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,B3A0D2BCEF4DE916D0BBA30A6885251B
+
+v8y74AGReaPLmDt6O8wir6hX1Ze8K4fVNkrLqfDMdW5E7jBXKO8riCMNmSjQ9fyh
+eTicej93+8krcIvSXKW18TdO+EWezQevgnLrAZQWaNPH2j4B+K5gm701uiiKFKVa
+1zngAOByePYlN6z4JLbiCyJRhxSo5zCaUYkKC2eGh8mlE64QmokPSCAj0wcCDzGh
+hdhBg1vm0GmaQwIDVn+8zMfahscXVMtBmyQf5YP4PQW2nqOt7aZHjBNdg9qnBpGw
+b6YuY7eZ4FgQvYcsNCi34NroJb9pkTrrF2F9Meb6+3So7jtMFG/YaJdCuXtf01g/
+Qm+XA5pJUtIUr/hLQjhkaOVUtXv/k0o/MR4k5CbAmboLt6YHf5V8+01vk0bvv5dI
+70pVdXMmx26xDZOGmjYzd93PWc+75jak3GN2fbWryQs=
+-----END RSA PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_aes256.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_aes256.pem
new file mode 100644
index 0000000000..7671a302fb
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.key_aes256.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,F076229CDC2BCB3B8722E3865855B45C
+
+WFV9QWzr4tNmD+1OeQ7BceQg5LVQHp20Jo1Ax29lq8JTPzeObhtaU2MUHlcPKHUS
+vK4FyQxJ25CyMubbnaZqCCz9pNbseFuJ1tob9UqRmXkZ8HV3snRjJRbcctD+V9x+
+Ymi1GreXoDQtMp0FtMiFjPvIYciBQnaRv2ChMAnGXNbZXCxWWA9E5S3a+yWzo+gd
+wEcowL+SUac1PEDGHokhKn7nctvI9cC4hE6JmKM1sD68/U3rRPXMGqmC7umqyT5P
+gjWBb1uu0iRjFC9eQUsaKPxey5Be710GFlyf/Ff/tep7RhkryIWEPvIzYCBf6rhk
+3pysFgTjfiUuBYUNumjXr/q5hgdtb75788XUDxKwAoUx+m8gi0nJg35CN2nmQ054
+VJxcZlNv0wqnJ+GTTZeN6fiAhTpVtHsqHQomRSfaBiw=
+-----END RSA PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.noname.p12 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.noname.p12
new file mode 100644
index 0000000000..9d27999fa0
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.noname.p12
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.unencrypted.p8 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.unencrypted.p8
new file mode 100644
index 0000000000..d04694b1fd
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.unencrypted.p8
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.unencrypted_pem.p8 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.unencrypted_pem.p8
new file mode 100644
index 0000000000..e07375a848
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.unencrypted_pem.p8
@@ -0,0 +1,10 @@
+-----BEGIN PRIVATE KEY-----
+MIIBVwIBADANBgkqhkiG9w0BAQEFAASCAUEwggE9AgEAAkEA0TswX6kBQj2GbXK+
+QG5RwUl/V3WhLTblwT0PIBrRI236dNI+I7Bw/KBq3uxBiIT+VBVrYcUWYriTQfFP
+Pf8uvQIDAQABAkEAkXnE7Y41qNfcYrb4HxZVU74Fg0rvUN+tqckJfjoHFcj9FrvA
+5JjRRZlgdWxkZYnHHjWizRQFODkVGrgPBZYBAQIhAOjr16jf2JCqPCGkBDFq0yHY
+JZhPuCiTK7npX7mjZXd9AiEA5fZv61DEOwHDQn1QM3oJ3AjldvO96g/l8dM9L2Pi
+uEECIQDdz7LpnHp1kdh/xN1FXlDAO0HaIZjj8vtCKa/CbotzVQIhAMNdatWyhxNO
+OxF4nrMs4cVyNWeqSVTZbtPUTy28oTdBAiEAxGkIUzsytLZrG5zz8fMaSpb/cCUg
+Gp1luKWPnMd3ZHQ=
+-----END PRIVATE KEY-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.withCA.p12 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.withCA.p12
new file mode 100644
index 0000000000..ae029dee0f
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.withCA.p12
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.withoutCA.p12 b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.withoutCA.p12
new file mode 100644
index 0000000000..c4eb54c444
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.withoutCA.p12
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_1024.cer b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_1024.cer
new file mode 100644
index 0000000000..fc92d05642
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_1024.cer
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_1024.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_1024.pem
new file mode 100644
index 0000000000..81f3eaf1c4
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_1024.pem
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIB1zCCAUACCQDxw4fA1PRXwzANBgkqhkiG9w0BAQUFADA0MTIwMAYDVQQKEylh
+eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
+MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
+Y3QxEjAQBgNVBAMTCTEyNy4wLjAuMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEA2OC/Fd7qr+jV/QuoqLPXRl2nJmwMtdm8xvjAeND2VmX4KUgOewumJX7oe3lv
+OOW1t/TgnJFg9AbzQB75kRmpL0dDtZse3PaqHEl5ISjLqklz2QkFTALyTE1sHICn
+FJFE/BKz4efjT0S6jMN0OehM0NRMJGG0QJWMwAq3AjkxhZMCAwEAATANBgkqhkiG
+9w0BAQUFAAOBgQALRyRSfbZjeLyA3YdskEwzw1ynlwkcCU+bbrNaPkaSGseHFVnh
+iFzOauKWqjLswu14i+CQZpMUw5irMzXTfV1RCpy5EFhHepiVZP9MXYIZ+eoPXprL
+Midkym9YitDANvS5YzSl2jZQNknStzohM1s+1l8MmYO3sveLRMRec0GpAg==
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_2048.cer b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_2048.cer
new file mode 100644
index 0000000000..c0badf7288
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_2048.cer
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_2048.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_2048.pem
new file mode 100644
index 0000000000..1ed0141afb
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_2048.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICWzCCAcQCCQDxw4fA1PRXxDANBgkqhkiG9w0BAQQFADA0MTIwMAYDVQQKEylh
+eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
+MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
+Y3QxEjAQBgNVBAMTCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMKgv9v6z3AGRLOf3o092S/ENz33Z2tlguOIuh2Apwp2ziHFvul7m9iF
+xsEcEARcvpkRPVo6ifJLjhJErenvvMAIS3WoO1lyenMaGoNddLeRRB0snRn7xRcl
+DYzCYS3fhJmkE06RL/TCTyY9GXa7odRI8kcWuByZog/be15lsgn0pjNKjJICdCer
+Otq0TAV/pfzRBF9lcyboHWQFOu9UVmDp3LsV/9o1GJbyKiNZd0j/GnDFOQbXy7GD
+I9PJTRzo4GQj0cJHY7JelORKiIsymcoMNRTboFRAx5y9jAGF8Ks196Rq/+9gYsvi
+eE0h+pbdLLbM0uZvAYqzIGK9hRR7Ja0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQA8
+L1Zz9K6M/PQCYWrfnTjbPKY2rTB1OvSV0Uwy5KKPQRS1+oK9dx4K0miX+1ZvI1bo
+f7/1aFXOsW3dpTwYUSjJvTMjSwNUPKiB/q/xwA1mzsbIZsbnhIITU95mOJ3xFhgc
+YFdJ4saL7pppTzfOxZ+h9jWbDwgJJAwx/q+O72uE5w==
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_4096.cer b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_4096.cer
new file mode 100644
index 0000000000..40bbe94fdd
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_4096.cer
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_4096.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_4096.pem
new file mode 100644
index 0000000000..b7aed1caba
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_4096.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDWzCCAsQCCQDxw4fA1PRXxTANBgkqhkiG9w0BAQQFADA0MTIwMAYDVQQKEylh
+eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
+MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
+Y3QxEjAQBgNVBAMTCTEyNy4wLjAuMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
+AgoCggIBAPwntJldKsrQMAz6410QZVIdoHSrNrYQ8NzdfKMF1a0lBavUsAGjDa5n
+qfQ0fTBAC3HTJtxghCe7DjohEHKk89uXYt+liQ3vo6Nc+Zw9l2bDyLKffpOdVc/l
+tweL7FyQIM1fl2W5r/S9OffFRMJKXiN1HPXrfGYRrwz6B2cgUBtSgI+odwCmdfjb
+Ya4Wo8Za53UGeQ7v0eQ0lEDgXAhx3c2YIoXXxfe2J/5KdZnpXtRJWTJaoAbaQ4tU
+xECfVwbYwltHqRQJuUx0N4DMeQwnKgf3DWHWVqqWdALsAE5utfuOpuHxSoN2AGDz
+ov++GihbiEAcP5XPFv/0ldcfEi/4X9lyHb0mvUIa6DTdHd17thFEM12caD0TCszq
+in8JWVu6M0+oRQcDzIfMn4aD7oKtk76gY5HtbN4Jr8E4BHH/oGPe6l4mQl+W4f3o
+Zp2e7yG5WBVA9sjJbCmlxiWMHod1iiZUJ4e9cEFINjMWuooPIo6xKMzZcGHzwkBa
+zS6kHyTsHcfdHcu4aVMlJ9cKN/aesJgup/XseM3imzuJ3UqfvwCfneUKfM6DM8J3
+mFfSwUBvK8uLsMw5Elim/1oIbBG0PTt7BiLiNd0pU/weuL92y2+QB2oCPM0t5D7L
+IYyoZHHNlvTCkQVNsCHgrDUtOdpGlKt6zzEgUTqwC5i5N3p/w6uPAgMBAAEwDQYJ
+KoZIhvcNAQEEBQADgYEAcrCtPXmZyPX01uNMh2X1VkgmUn/zLemierou7WD/h7xL
+dOl4eeKjFBqIiC19382m1DK4h1F8MceqaMgTueCJpLM7A2cwN3ta8/pGP2yEVhdp
+h10PkdRPF/AU8JmxnFaADsc6+6xWbbrdNv5xcvP1bJKWWW+30EhRF9PxjXiETXc=
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_512.cer b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_512.cer
new file mode 100644
index 0000000000..48c6e13aa0
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_512.cer
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_512.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_512.pem
new file mode 100644
index 0000000000..8191e489f3
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_512.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBkjCB/AIJAPHDh8DU9FfCMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
+VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA2MDYw
+NzExNDQzMloXDTMzMTAyMzExNDQzMlowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
+dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANE7
+MF+pAUI9hm1yvkBuUcFJf1d1oS025cE9DyAa0SNt+nTSPiOwcPygat7sQYiE/lQV
+a2HFFmK4k0HxTz3/Lr0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQAKRT6LwFr1xedJ
+b4qrvjB+EwV/0p4TNNXUS9S30rMSFvRar7VxvLP1lpYj9PR1JGSZMG/B6hR4yumF
+Rjwel9FPgNcWCW4DXAWqz3UQF7oZtJL6K+XJpQ0gwC+Nxc+RRGNLMlK7dLiqFh/V
+qZLej5Xy93M0JyZBiLV88P+c08gd7A==
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_aes128.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_aes128.pem
new file mode 100644
index 0000000000..9a75fe960e
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_aes128.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBkjCB/AIJAPHDh8DU9FfHMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
+VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA2MDYw
+NzExNDQzMloXDTMzMTAyMzExNDQzMlowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
+dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMDo
+g6K2iXFftW+Qk+rrzkMGWrtfY6YSxPstPRrI7akluUEoyWGITXbK6L3QfERrf2eu
+CnWyciQiHVRoHC0EgZUCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBT6YhR8x/bBteK
+lr8E0l4mATOnYlsmge+z/SFYs4bDBofqlwQCVJXNSBA4ZsEjgP9qIWTu/85QrVGq
+LrkewSM6Oeh95LGnE+uhJVtIX++O+Hsex3H1UL067dCG99XmDhqbEU9AI6YSZu2p
+cjoSowFELtOoG667+id9QObfV3EQoQ==
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_aes256.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_aes256.pem
new file mode 100644
index 0000000000..4f3074e011
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_aes256.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBkjCB/AIJAPHDh8DU9FfIMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
+VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA2MDYw
+NzExNDQzMloXDTMzMTAyMzExNDQzMlowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
+dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANAW
+9PdXa5u4gWi5VB5p/eQmOtteRq9/54JkiEs8cVNrTQgZsjjU1LGedE3JwBqZ1EIW
+HGPjcGg5dVxFjkn7RekCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBmJMt0Crdd/BPn
+EdmzsVXou0zTizTC8wyUPMVpg/KzzP7fhZux/ZIrH9/RVcJd9y+B2/mXc3C+K99+
+TXQoYKsLGArfDPzmpy1wPrdEcB1A9gkWDl1Uq6xRyvrVm3gX8NTITRuGKL9njgWx
+2SrApIBtOOUOinYtfH3745cVVl5HOA==
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_bad_after.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_bad_after.pem
new file mode 100644
index 0000000000..79eb9ccd68
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_bad_after.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBkjCB/AIJAPHDh8DU9FfKMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
+VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA2MDYw
+NzExNDQzMloXDTA1MDYwNzExNDQzMlowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
+dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANE7
+MF+pAUI9hm1yvkBuUcFJf1d1oS025cE9DyAa0SNt+nTSPiOwcPygat7sQYiE/lQV
+a2HFFmK4k0HxTz3/Lr0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQCmPSs9EceViMZD
+ZTXDZpQWJFcXaeInrXWgYWyVgnHBY/eSuqNCxkV/ehv/Wc5pWBGnrX+4cSvQ+TpQ
+FdZegeOjvgipjtJb/0TJCcvgcdHTntEM0h7VXjfbsJXAHwJPFzWIKxV4jeFXnaaw
+W+YHrj9GQ8PnFmapPuh4h/y6LyHAcg==
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_bad_before.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_bad_before.pem
new file mode 100644
index 0000000000..fe72b541b2
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_bad_before.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBkjCB/AIJAPHDh8DU9FfJMA0GCSqGSIb3DQEBBQUAMDQxMjAwBgNVBAoTKWF4
+VExTIFByb2plY3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTI0MTIz
+MTE0MDAwMFoXDTI1MTIzMTE0MDAwMFowLDEWMBQGA1UEChMNYXhUTFMgUHJvamVj
+dDESMBAGA1UEAxMJMTI3LjAuMC4xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANE7
+MF+pAUI9hm1yvkBuUcFJf1d1oS025cE9DyAa0SNt+nTSPiOwcPygat7sQYiE/lQV
+a2HFFmK4k0HxTz3/Lr0CAwEAATANBgkqhkiG9w0BAQUFAAOBgQApbldYefE8A0ez
+SYvAuCtYxx/2KHwBRD/cR0q7widl9WGjVC/dsnbFo109vHEr3FP1HVYSI0aweiaK
+XZmpUyJ9DprbbWQqaLuDnqIH8X7kfiMuO7/LGQc812iDJI2Akxp9cIlPBFBD8GVx
++0EphzSodDDlLD8bPqLaWTE+8Ydtjw==
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_device.cer b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_device.cer
new file mode 100644
index 0000000000..c966743c9c
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_device.cer
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_device.pem b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_device.pem
new file mode 100644
index 0000000000..e9cbaaf314
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/axTLS.x509_device.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIBjTCCATcCCQDxw4fA1PRXxjANBgkqhkiG9w0BAQUFADAsMRYwFAYDVQQKEw1h
+eFRMUyBQcm9qZWN0MRIwEAYDVQQDEwkxMjcuMC4wLjEwHhcNMDYwNjA3MTE0NDMy
+WhcNMzMxMDIzMTE0NDMyWjArMSkwJwYDVQQKEyBheFRMUyBQcm9qZWN0IERldmlj
+ZSBDZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1CIODRIr
+v3YgwJW7Fm0wITCsOIgX9l+aIRiXUzur4RkHRJIQUQYM3ZfftC21QyWPGErVIIcJ
+7s7U/iKTQq1LV7USvAp90D/m7s0ntmRj1aBCSG71f0LnSv1rlA8kzUkU7VuEt0Tt
++iqrW0+sYdUBk11dyPLKe6sJnMrJJamVvBsCAwEAATANBgkqhkiG9w0BAQUFAANB
+ABC3Uc6uImIpcLl1WYu8K8qkGnVT4K9JkdXHQFbhFZs37lvITrOHQ3j2oGXTbdAx
+JFJ3II9xXkm+nc7oLHqhXlc=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIB3zCCAUgCCQCdbnM4pjqlWjANBgkqhkiG9w0BAQUFADA0MTIwMAYDVQQKEylh
+eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0wNjA2
+MDcxMTQ0MzJaFw0zMzEwMjMxMTQ0MzJaMDQxMjAwBgNVBAoTKWF4VExTIFByb2pl
+Y3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQCnZdk20fYWh8O6kDTt0AuJWyp0YIrb7W1UNNMPXI5wA4J59IVj
+Nmk5wocm9+Hqzbg7rORAN/mHPBhzLAjhnm1HODs36hW15DtbDkkH4wCM/Tsyv79m
+n0xq1V6peK3t9vi2D4p/IRjHkYR2jm+BeknopijhY0kHHfpGTHa2DnVirwIDAQAB
+MA0GCSqGSIb3DQEBBQUAA4GBAB0LgNo0oCcwIie5plgwwFybQ8x95q6e3wndM/Mp
+3gjcAFbGuchpo3dfFlTcRI0KyERb3q1MVxPM4sff9nT7EdHVyK9s8/ITkP2dcTKc
+flbcTEfJVIeM8L2P5F41Hvn9GuGcMW8EmsC06gdbp1LLnqsdrXdMNBsAUBXfgPrU
++UcZ
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/datatest.c b/libs/luci-lib-nixio/axTLS/ssl/test/datatest.c
new file mode 100644
index 0000000000..2a5e836e5b
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/datatest.c
@@ -0,0 +1,43 @@
+
+#include <string.h>
+#include <stdlib.h>
+#include "ssl.h"
+
+int main(int argc, char *argv[])
+{
+ bigint *m1, *m2, *d;
+ BI_CTX *ctx = bi_initialize();
+ char cmp1[1024], cmp2[1024];
+
+ const char *plaintext = /* 128 byte number */
+ "01aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee"
+ "01aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee";
+ d = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
+ memset(cmp1, 0, sizeof(cmp1));
+
+ while (1)
+ {
+ bi_set_mod(ctx, bi_clone(ctx, d), 0);
+ m1 = bi_square(ctx, bi_copy(d));
+ m2 = bi_residue(ctx, m1);
+ bi_free_mod(ctx, 0);
+
+ //bi_export(ctx, bi_copy(d), cmp1, sizeof(cmp1));
+ bi_export(ctx, m2, cmp2, sizeof(cmp2));
+
+ if (memcmp(cmp1, cmp2, sizeof(cmp1)) != 0)
+ {
+ printf("Error!\n"); TTY_FLUSH();
+ break;
+ }
+
+ d = bi_add(ctx, d, int_to_bi(ctx, 1));
+ }
+
+ bi_free(ctx, d);
+ bi_terminate(ctx);
+ printf("all good\n"); TTY_FLUSH();
+ return 0;
+
+}
+
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/datatest.c.old b/libs/luci-lib-nixio/axTLS/ssl/test/datatest.c.old
new file mode 100644
index 0000000000..a5703fb9ec
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/datatest.c.old
@@ -0,0 +1,280 @@
+#include "crypto.h"
+
+#include <string.h>
+#include <stdlib.h>
+//#define DEBUG_TEST
+
+typedef enum {
+ encrypt, decrypt
+} CryptoMode;
+
+void hex_dump(const char* header, const unsigned char* data, const unsigned int data_length)
+{
+ unsigned int byte_count;
+ printf("%s (%d bytes):\n", header, data_length);
+ for(byte_count = 0; byte_count < data_length; ++byte_count)
+ {
+ printf("%02X", data[byte_count]);
+ }
+ printf("\n");
+}
+
+void do_rsa(const CryptoMode crypto_mode,
+ const unsigned char* data, const unsigned int data_length,
+ const unsigned char* modulus, const unsigned int modulus_length,
+ const unsigned char* exponent, const unsigned int exponent_length,
+ unsigned char* result, const unsigned int result_length)
+{
+ RSA_CTX* rsa_context = NULL;
+ BI_CTX *bi_ctx;
+ bigint *plaintext_bi;
+ bigint *enc_data_bi, *dec_data_bi;
+
+#ifdef DEBUG_TEST
+ printf("do_rsa:\n");
+ hex_dump("data", data, data_length);
+ hex_dump("modulus", modulus, modulus_length);
+ hex_dump("exponent", exponent, exponent_length);
+#endif
+
+ RSA_priv_key_new(&rsa_context, modulus, modulus_length, exponent, exponent_length, exponent, exponent_length);
+ memset(result, 0, result_length);
+ bi_ctx = rsa_context->bi_ctx;
+
+ switch(crypto_mode)
+ {
+ case encrypt:
+#ifdef DEBUG_TEST
+ printf("encrypt\n");
+#endif
+ plaintext_bi = bi_import(bi_ctx, data, data_length);
+ enc_data_bi = RSA_public(rsa_context, plaintext_bi);
+ bi_export(bi_ctx, enc_data_bi, result, result_length);
+ break;
+
+ case decrypt:
+
+#ifdef DEBUG_TEST
+ printf("decrypt\n");
+#endif
+ plaintext_bi = bi_import(bi_ctx, data, data_length);
+ dec_data_bi = RSA_private(rsa_context, plaintext_bi);
+ bi_export(bi_ctx, dec_data_bi, result, result_length);
+ break;
+ }
+#ifdef DEBUG_TEST
+ hex_dump("result", result, result_length);
+#endif
+
+ RSA_free(rsa_context);
+}
+
+void test_matching(char* test_description,
+ const unsigned char* expected, const unsigned int expected_length,
+ const unsigned char* result, const unsigned int result_length)
+{
+ int test_result = memcmp(expected, result, expected_length);
+ printf("Testing %s ... ", test_description);
+ if(test_result == 0)
+ {
+ printf("ok.\n");
+ }
+ else
+ {
+ printf("failed!\n");
+ hex_dump("should be", expected, expected_length);
+ hex_dump("but is", result, result_length);
+ }
+}
+
+void encrypt_decrypt_should_yield_original(char* test_description,
+ const unsigned char* data, const unsigned int data_length,
+ const unsigned char* modulus, const unsigned int modulus_length,
+ const unsigned char* private_exponent, const unsigned int private_exponent_length,
+ const unsigned char* public_exponent, const unsigned int public_exponent_length,
+ const unsigned char* cryptogram, const unsigned int cryptogram_length)
+{
+ const unsigned int calculated_cryptogram_length = modulus_length;
+ unsigned char* calculated_cryptogram = malloc(calculated_cryptogram_length);
+ const unsigned int decrypted_data_length = modulus_length;
+ unsigned char* decrypted_data = malloc(decrypted_data_length);
+
+ printf("\nRunning \"%s\" ...\n", test_description);
+
+#ifdef DEBUG_TEST
+ printf("encrypt_decrypt_should_yield_original:\n");
+ hex_dump("data", data, data_length);
+ hex_dump("modulus", modulus, modulus_length);
+ hex_dump("private_exponent", private_exponent, private_exponent_length);
+ hex_dump("public_exponent", public_exponent, public_exponent_length);
+ hex_dump("cryptogram", cryptogram, cryptogram_length);
+#endif
+
+ do_rsa(encrypt, data, data_length,
+ modulus, modulus_length,
+ private_exponent, private_exponent_length,
+ calculated_cryptogram, calculated_cryptogram_length);
+
+#ifdef DEBUG_TEST
+ hex_dump("calculated_cryptogram", calculated_cryptogram, calculated_cryptogram_length);
+#endif
+
+ if(cryptogram != NULL)
+ {
+ test_matching("cryptogram", cryptogram, cryptogram_length,
+ calculated_cryptogram, calculated_cryptogram_length);
+ }
+
+ do_rsa(decrypt, calculated_cryptogram, calculated_cryptogram_length,
+ modulus, modulus_length,
+ public_exponent, public_exponent_length,
+ decrypted_data, decrypted_data_length);
+
+ test_matching("decrypted plaintext", data, data_length,
+ decrypted_data, decrypted_data_length);
+
+ free(calculated_cryptogram);
+ free(decrypted_data);
+}
+
+/* configure without CRT!
+
+ prepare data with:
+ > echo "<string>" |
+ ruby -ne '$_.gsub!(/ /, "").scan(/../).each_with_index \
+ { |b, i| print "\"\n\"" if i % 16 == 0; print "\\x" + b;}' */
+int main(int argc, char *argv[])
+{
+#if 0
+ unsigned char stuff[] = {
+ 0x22, 0x33, 0x44, 0x81,
+ 0xF1, 0xFF, 0xAA, 0xBB,
+ 0xCC, 0xDD, 0xEE , 0x01,
+ 0x45, 0x44, 0xfa, 0x8d,
+ 0xfa, 0x20, 0x99, 0xFF,
+ 0xab, 0xda, 0xac, 0x40 };
+ unsigned char resA[sizeof(stuff)*2], resB[sizeof(stuff)*2];
+
+ BI_CTX *bi_ctx = bi_initialize();
+ bigint *bi_data1, *bi_data2, *res1, *res2;
+ bi_data1 = bi_import(bi_ctx, stuff, sizeof(stuff));
+ bi_data2 = bi_import(bi_ctx, stuff, sizeof(stuff));
+
+ res1 = bi_multiply(bi_ctx, bi_copy(bi_data1), bi_copy(bi_data2));
+ res2 = bi_multiply(bi_ctx, bi_data1, bi_data2);
+ bi_print("MULTIPLY", res1);
+ bi_print("SQUARE", res2);
+ bi_export(bi_ctx, res1, resA, sizeof(resA));
+ bi_export(bi_ctx, res2, resB, sizeof(resB));
+ if (memcmp(resA, resB, sizeof(resA)))
+ printf("OUCH - difference!\n");
+ bi_terminate(bi_ctx);
+
+ exit(0);
+#endif
+ encrypt_decrypt_should_yield_original("Works only with Montgomery",
+ (const unsigned char*) /* data */
+ "\xBC\xD3\x12\x6C\x93\x13\x14\x4C\x00\x5D\xFD\xBF\xDE\xE4\xD3\x60"
+ "\x29\xB8\xAE\x47\xBE\x0B\xB6\x0A\x39\x88\xB7\x93\x19\x14\xE8\x88"
+ "\x4A\xDE\x00\x46\x89\x5A\x11\x1A\xC4\x8F\xE8\xF7\x27\xAC\x59\x80"
+ "\x03\xC1\x93\x14\x01\x00\x93\x15\x07\x00\x00\x00\x01\x01\x05\x20"
+ "\x93\x16\x0F\x42\x34\x33\x3A\x58\x30\x30\x30\x31\x30\x31\x30\x30"
+ "\x30\x31\x92\x6B\x10\x6C\x69\x62\x65\x6C\x6D\x65\x74\x72\x65\x65"
+ "\x2E\x73\x6F\x2E\x30\x93\x18\x02\xA5\x92\x92\x6C\x03\x96\xE3\x0C"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xB7\xBE", 128,
+ (const unsigned char*) /* modulus */
+ "\xc4\x5a\xcb\x35\x95\xad\x32\x4a\xcf\x9c\x82\x45\x13\xb7\x42\x35"
+ "\x22\x32\x6d\x2e\x6d\x26\x2e\x6d\x00\x9b\xae\x2d\x9e\x78\x1e\xdd"
+ "\x40\x23\x17\xa8\xbb\xa1\x07\x86\xb4\x3c\xbc\xe8\xd5\xfc\xd9\xeb"
+ "\x3c\xad\x63\x11\xf3\x1d\x64\x81\x96\xf2\xf5\xfe\xca\x5a\xf7\x8a"
+ "\x15\xcb\x90\x81\x68\xae\x59\xb4\xe1\xa4\x41\x99\xcd\xf3\x98\xbd"
+ "\x3c\x48\x37\xdb\xa1\xc3\x1c\x6f\x43\xd1\x89\x23\xe5\x3d\xa3\xa5"
+ "\x92\x7b\x19\x14\x1e\x7a\xf3\x88\x8a\x36\x21\x3e\x16\x40\x3c\xd7"
+ "\xd3\xdb\x13\xaf\xc9\x68\x45\x84\xb3\x39\x8f\x02\xed\x28\x02\x5f", 128,
+ (const unsigned char*) /* private exponent */
+ "\x5d\x19\xb7\xb4\x66\x8d\xc2\x84\xda\x3f\x99\x3c\xeb\x86\x3e\xec"
+ "\x36\x94\xb6\x54\x07\x08\xcd\x86\x7d\x7d\x53\x6e\xe9\xee\x86\xa3"
+ "\xdd\x5f\x46\x3e\x89\x08\x67\x2b\x25\x96\x8e\xf3\xcf\x52\x9e\x78"
+ "\xfd\x42\x30\xf1\x37\xd6\xbd\xea\xfc\x09\xa3\x3d\xf5\xf0\x7f\xe1"
+ "\xb1\xe0\x69\x13\x44\xf9\x8b\x95\x58\x2a\x81\xb3\xa8\x15\xce\x7e"
+ "\xd3\xea\x97\x0a\xa2\x14\xd4\xae\xc7\x75\xbb\x9f\x68\xa5\x53\x0e"
+ "\x85\x29\x88\x48\x6c\xc9\xcc\xde\x72\x40\x3a\x4c\x82\xde\x3c\xfb"
+ "\x08\xf8\x2c\x26\xb5\xd4\xea\xc4\xca\x98\x6e\x43\x3e\x67\x54\xc1", 128,
+ (const unsigned char*) /* public exponent */
+ "\x01\x00\x01", 3,
+ (const unsigned char*) /* precalculated encrypted data */
+ "\x93\xE8\x1F\xF9\x70\xFA\xAA\xED\x54\xFD\x48\x37\xC9\x71\x9A\x11"
+ "\x69\x80\xB4\x22\x0C\xAD\x5A\x95\x65\xCA\x7C\xF7\x70\x56\x92\xCB"
+ "\x45\x6D\x58\x84\x21\x80\x23\x76\x21\x4A\x61\x99\xC1\x11\x9C\x0F"
+ "\x40\xED\x80\x9C\x8F\x3A\x4F\x01\xB5\x72\xC3\x24\xAE\xF3\x6B\x98"
+ "\xA8\x60\xAC\xAF\x95\x98\x9A\xAA\xA4\x28\xF2\x02\x05\xFC\xF3\xDD"
+ "\xB0\x5A\x4E\xDE\x3C\x41\x4B\x1C\x5B\x1F\xF6\x3D\xAF\x93\x43\xCB"
+ "\xD8\xC7\x24\x97\x8F\x49\xE5\x5B\x10\x51\x3B\x1E\xA6\x39\xEA\x4E"
+ "\xA5\xE0\x71\x8C\xCA\x34\x8C\x2F\x6C\x5C\x78\x34\x86\x7C\x54\x6A", 128);
+
+ encrypt_decrypt_should_yield_original("Works only with Barrett",
+ (const unsigned char*) /* data */
+ "\x36\x42\x32\xe4\x1e\x78\x02\x8e\xfb\x64\x5f\x0c\xfc\x5a\xd7\x5c"
+ "\xe4\xb5\x91\x5c\x4b\x00\x87\x28\x87\x9b\xa0\x4b\x09\xc2\x6b\x64"
+ "\xac\x4b\xcf\xa5\xee\x8a\xb7\xc9\xc9\x90\x02\xc1\xa3\x47\x5c\x6b"
+ "\x71\x5d\x5d\x49\x27\xe1\x15\xc6\xcf\x37\x9e\xa7\x0f\xa1\xad\x96"
+ "\x83\xef\x4b\x53\x68\xcd\x77\xfc\x14\x5f\xf5\xb7\x78\xb0\x10\xeb"
+ "\x0d\x61\x94\x01\xf6\xaa\x1b\x19\x23\x39\xa7\xcc\x6c\x42\x4a\x87"
+ "\x79\x27\x04\xc6\xec\x8e\x50\xba\xb9\x26\x89\xd4\x00\x01\x25\xe5"
+ "\xf3\x9e\x98\x0c\x8d\x2e\x43\x1e\xe9\x29\x90\xd2\x75\x61\x85\xe7", 128,
+ (const unsigned char*) /* modulus */
+ "\x37\x0c\x32\xe4\x1e\x78\x02\x8e\xfb\x64\x5f\x0c\xfc\x5a\xd7\x5c"
+ "\xe4\xb5\x91\x5c\x4b\x00\x87\x28\x87\x9b\xa0\x4b\x09\xc2\x6b\x64"
+ "\xac\x4b\xcf\xa5\xee\x8a\xb7\xc9\xc9\x90\x02\xc1\xa3\x47\x5c\x6b"
+ "\x71\x5d\x5d\x49\x27\xe1\x15\xc6\xcf\x37\x9e\xa7\x0f\xa1\xad\x96"
+ "\x83\xef\x4b\x53\x68\xcd\x77\xfc\x14\x5f\xf5\xb7\x78\xb0\x10\xeb"
+ "\x0d\x61\x94\x01\xf6\xaa\x1b\x19\x23\x39\xa7\xcc\x6c\x42\x4a\x87"
+ "\x79\x27\x04\xc6\xec\x8e\x50\xba\xb9\x26\x89\xd4\x00\x01\x25\xe5"
+ "\xf3\x9e\x98\x0c\x8d\x2e\x43\x1e\xe9\x29\x90\xd2\x75\x61\x85\xe7", 128,
+ (const unsigned char*) /* private exponent */
+ "\x16\x3a\x76\xd2\x66\xfb\x4f\x0d\x2d\xb6\x7a\x2b\x64\x3b\xca\x7b"
+ "\x58\x5f\x79\x33\x2b\x96\x2a\xfd\xd2\xc4\xa5\x15\xa7\xfb\x3a\x22"
+ "\x8c\xf0\x90\x09\x11\x2a\x32\xcc\xe8\xf7\x9e\x25\x53\x29\x9d\xc8"
+ "\x45\x1e\xce\x6c\x9c\x0d\xe8\x1d\x3f\xcf\xd5\xe0\xe0\x0f\x09\x69"
+ "\x2d\xe7\xd5\xe6\xe5\x10\xd9\x4e\x20\xdb\xbd\xa1\x04\x6b\xe6\x1d"
+ "\x4c\x79\x28\x47\x30\x11\xde\x14\xb4\x6e\x35\x98\x38\x50\x44\x82"
+ "\xbd\xc4\xfb\x03\xb3\xf6\x5e\x5a\x29\xfa\x29\xaa\xde\xe4\xfd\x15"
+ "\xbe\xed\x4f\x93\x9d\x0d\x29\xe8\xd7\xa3\xf4\x18\xc8\x98\xb1\x01", 128,
+ (const unsigned char*) /* public exponent */
+ "\x01\x00\x01", 3,
+ NULL, 0);
+
+ encrypt_decrypt_should_yield_original("Works always",
+ (const unsigned char*) /* data */
+ "\xB9\x42\x32\xe4\x1e\x78\x02\x8e\xfb\x64\x5f\x0c\xfc\x5a\xd7\x5c"
+ "\xe4\xb5\x91\x5c\x4b\x00\x87\x28\x87\x9b\xa0\x4b\x09\xc2\x6b\x64"
+ "\xac\x4b\xcf\xa5\xee\x8a\xb7\xc9\xc9\x90\x02\xc1\xa3\x47\x5c\x6b"
+ "\x71\x5d\x5d\x49\x27\xe1\x15\xc6\xcf\x37\x9e\xa7\x0f\xa1\xad\x96"
+ "\x83\xef\x4b\x53\x68\xcd\x77\xfc\x14\x5f\xf5\xb7\x78\xb0\x10\xeb"
+ "\x0d\x61\x94\x01\xf6\xaa\x1b\x19\x23\x39\xa7\xcc\x6c\x42\x4a\x87"
+ "\x79\x27\x04\xc6\xec\x8e\x50\xba\xb9\x26\x89\xd4\x00\x01\x25\xe5"
+ "\xf3\x9e\x98\x0c\x8d\x2e\x43\x1e\xe9\x29\x90\xd2\x75\x61\x85\xe7", 128,
+ (const unsigned char*) /* modulus */
+ "\xB9\x77\xEC\x83\x95\xAF\xB1\xF8\x21\x21\xFF\x05\x5E\x0C\x91\x0C"
+ "\x2E\xD5\xD2\x94\x1C\x38\x5E\xED\x5A\xCF\x84\xD0\x12\x8B\xAA\x4B"
+ "\x3A\x63\x65\x78\x13\xED\x24\x4E\x83\xF2\xF5\x02\x66\x5D\xFC\xC1"
+ "\x80\x5B\x78\x78\xB4\x0B\x45\xE5\x22\xC6\xCD\xEB\xCC\x74\x0B\x0B"
+ "\xD8\x8B\x91\x99\x48\x8E\x74\xA9\xD0\x1A\x39\x94\xC2\xD4\x2E\x9A"
+ "\x8C\x0C\x35\x0D\x97\x8F\xC4\x62\x20\xE9\x78\x40\x97\x05\x98\xE6"
+ "\x22\x48\x3D\x3D\xCA\x6A\x3F\xEF\xB0\x23\x14\x30\xDA\x35\x46\x65"
+ "\x55\xEF\xEB\xA1\xA9\xCF\x83\xE7\xEF\xF2\x83\x6D\x38\xEA\x88\xED", 128,
+ (const unsigned char*) /* private exponent */
+ "\x52\x2A\x68\xE3\x9A\xAA\xED\xA3\x49\xBA\x6F\xEA\x86\xD1\xF6\x68"
+ "\x79\x4F\x4D\x2D\x44\x9B\x4C\xA2\xC6\xBA\x6C\xD2\x69\x84\xEA\x7A"
+ "\xCD\x71\x3F\x80\xC5\x03\x28\x34\x88\x8C\x58\x33\x29\xFA\xB5\x81"
+ "\x5C\x46\x29\xC6\xFF\xAC\x86\xD8\x8E\x61\x98\xD4\xC0\x0D\x20\xDE"
+ "\xEB\x61\x1C\x0C\x3C\x19\xA3\x75\x10\x7D\xDA\xA9\x55\xA7\x64\x5F"
+ "\xE0\xB6\x35\x62\x00\xD9\xD2\xF7\xA4\xDF\x85\xFF\xDF\x86\x75\x29"
+ "\x66\x16\x03\x8C\xC0\xB0\x3F\xAB\xBA\x41\xB3\x3C\x76\x58\xB6\xE2"
+ "\x1F\x36\x47\x5F\x1F\x0E\x4C\xB5\x29\x90\xDC\xA1\xF8\xFA\x58\x19", 128,
+ (const unsigned char*) /* public exponent */
+ "\x01\x00\x01", 3,
+ NULL, 0);
+
+ return 0;
+}
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/deutsche_telecom.x509_ca b/libs/luci-lib-nixio/axTLS/ssl/test/deutsche_telecom.x509_ca
new file mode 100644
index 0000000000..0f4b96a0d5
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/deutsche_telecom.x509_ca
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/equifax.x509_ca b/libs/luci-lib-nixio/axTLS/ssl/test/equifax.x509_ca
new file mode 100644
index 0000000000..79b0a3f987
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/equifax.x509_ca
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/gnutls.cer b/libs/luci-lib-nixio/axTLS/ssl/test/gnutls.cer
new file mode 100755
index 0000000000..312e365404
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/gnutls.cer
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/header_issue.dat b/libs/luci-lib-nixio/axTLS/ssl/test/header_issue.dat
new file mode 100755
index 0000000000..a48d23d2b9
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/header_issue.dat
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/killopenssl.sh b/libs/luci-lib-nixio/axTLS/ssl/test/killopenssl.sh
new file mode 100755
index 0000000000..17950fbaef
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/killopenssl.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+ps -ef|grep openssl | /usr/bin/awk '{print $2}' |xargs kill -9
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/make_certs.sh b/libs/luci-lib-nixio/axTLS/ssl/test/make_certs.sh
new file mode 100755
index 0000000000..dfc39d4f53
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/make_certs.sh
@@ -0,0 +1,174 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+#
+# Generate the certificates and keys for testing.
+#
+
+PROJECT_NAME="axTLS Project"
+
+# Generate the openssl configuration files.
+cat > ca_cert.conf << EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+ O = $PROJECT_NAME Dodgy Certificate Authority
+EOF
+
+cat > certs.conf << EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+ O = $PROJECT_NAME
+ CN = 127.0.0.1
+EOF
+
+cat > device_cert.conf << EOF
+[ req ]
+distinguished_name = req_distinguished_name
+prompt = no
+
+[ req_distinguished_name ]
+ O = $PROJECT_NAME Device Certificate
+EOF
+
+# private key generation
+openssl genrsa -out axTLS.ca_key.pem 1024
+openssl genrsa -out axTLS.key_512.pem 512
+openssl genrsa -out axTLS.key_1024.pem 1024
+openssl genrsa -out axTLS.key_2048.pem 2048
+openssl genrsa -out axTLS.key_4096.pem 4096
+openssl genrsa -out axTLS.device_key.pem 1024
+openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
+openssl genrsa -aes256 -passout pass:abcd -out axTLS.key_aes256.pem 512
+
+# convert private keys into DER format
+openssl rsa -in axTLS.key_512.pem -out axTLS.key_512 -outform DER
+openssl rsa -in axTLS.key_1024.pem -out axTLS.key_1024 -outform DER
+openssl rsa -in axTLS.key_2048.pem -out axTLS.key_2048 -outform DER
+openssl rsa -in axTLS.key_4096.pem -out axTLS.key_4096 -outform DER
+openssl rsa -in axTLS.device_key.pem -out axTLS.device_key -outform DER
+
+# cert requests
+openssl req -out axTLS.ca_x509.req -key axTLS.ca_key.pem -new \
+ -config ./ca_cert.conf
+openssl req -out axTLS.x509_512.req -key axTLS.key_512.pem -new \
+ -config ./certs.conf
+openssl req -out axTLS.x509_1024.req -key axTLS.key_1024.pem -new \
+ -config ./certs.conf
+openssl req -out axTLS.x509_2048.req -key axTLS.key_2048.pem -new \
+ -config ./certs.conf
+openssl req -out axTLS.x509_4096.req -key axTLS.key_4096.pem -new \
+ -config ./certs.conf
+openssl req -out axTLS.x509_device.req -key axTLS.device_key.pem -new \
+ -config ./device_cert.conf
+openssl req -out axTLS.x509_aes128.req -key axTLS.key_aes128.pem \
+ -new -config ./certs.conf -passin pass:abcd
+openssl req -out axTLS.x509_aes256.req -key axTLS.key_aes256.pem \
+ -new -config ./certs.conf -passin pass:abcd
+
+# generate the actual certs.
+openssl x509 -req -in axTLS.ca_x509.req -out axTLS.ca_x509.pem \
+ -sha1 -days 10000 -signkey axTLS.ca_key.pem
+openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_512.pem \
+ -sha1 -CAcreateserial -days 10000 \
+ -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
+openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_1024.pem \
+ -sha1 -CAcreateserial -days 10000 \
+ -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
+openssl x509 -req -in axTLS.x509_2048.req -out axTLS.x509_2048.pem \
+ -md5 -CAcreateserial -days 10000 \
+ -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
+openssl x509 -req -in axTLS.x509_4096.req -out axTLS.x509_4096.pem \
+ -md5 -CAcreateserial -days 10000 \
+ -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
+openssl x509 -req -in axTLS.x509_device.req -out axTLS.x509_device.pem \
+ -sha1 -CAcreateserial -days 10000 \
+ -CA axTLS.x509_512.pem -CAkey axTLS.key_512.pem
+openssl x509 -req -in axTLS.x509_aes128.req \
+ -out axTLS.x509_aes128.pem \
+ -sha1 -CAcreateserial -days 10000 \
+ -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
+openssl x509 -req -in axTLS.x509_aes256.req \
+ -out axTLS.x509_aes256.pem \
+ -sha1 -CAcreateserial -days 10000 \
+ -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
+
+# note: must be root to do this
+DATE_NOW=`date`
+if date -s "Jan 1 2025"; then
+openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_before.pem \
+ -sha1 -CAcreateserial -days 365 \
+ -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
+date -s "$DATE_NOW"
+touch axTLS.x509_bad_before.pem
+fi
+openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_after.pem \
+ -sha1 -CAcreateserial -days -365 \
+ -CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
+
+# some cleanup
+rm axTLS*.req
+rm axTLS.srl
+rm *.conf
+
+# need this for the client tests
+openssl x509 -in axTLS.ca_x509.pem -outform DER -out axTLS.ca_x509.cer
+openssl x509 -in axTLS.x509_512.pem -outform DER -out axTLS.x509_512.cer
+openssl x509 -in axTLS.x509_1024.pem -outform DER -out axTLS.x509_1024.cer
+openssl x509 -in axTLS.x509_2048.pem -outform DER -out axTLS.x509_2048.cer
+openssl x509 -in axTLS.x509_4096.pem -outform DER -out axTLS.x509_4096.cer
+openssl x509 -in axTLS.x509_device.pem -outform DER -out axTLS.x509_device.cer
+
+# generate pkcs8 files (use RC4-128 for encryption)
+openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8
+openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8
+openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -out axTLS.unencrypted_pem.p8
+openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -outform DER -out axTLS.unencrypted.p8
+
+# generate pkcs12 files (use RC4-128 for encryption)
+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_with_CA" -out axTLS.withCA.p12 -password pass:abcd
+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_without_CA" -out axTLS.withoutCA.p12 -password pass:abcd
+openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -out axTLS.noname.p12 -password pass:abcd
+
+# PEM certificate chain
+cat axTLS.ca_x509.pem >> axTLS.x509_device.pem
+
+# set default key/cert for use in the server
+xxd -i axTLS.x509_1024.cer | sed -e \
+ "s/axTLS_x509_1024_cer/default_certificate/" > ../../ssl/cert.h
+xxd -i axTLS.key_1024 | sed -e \
+ "s/axTLS_key_1024/default_private_key/" > ../../ssl/private_key.h
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/microsoft.x509_ca b/libs/luci-lib-nixio/axTLS/ssl/test/microsoft.x509_ca
new file mode 100644
index 0000000000..b90803452b
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/microsoft.x509_ca
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/microsoft.x509_ca.pem b/libs/luci-lib-nixio/axTLS/ssl/test/microsoft.x509_ca.pem
new file mode 100644
index 0000000000..478e60b070
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/microsoft.x509_ca.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEEjCCAvqgAwIBAgIPAMEAizw8iBHRPvZj7N9AMA0GCSqGSIb3DQEBBAUAMHAx
+KzApBgNVBAsTIkNvcHlyaWdodCAoYykgMTk5NyBNaWNyb3NvZnQgQ29ycC4xHjAc
+BgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEhMB8GA1UEAxMYTWljcm9zb2Z0
+IFJvb3QgQXV0aG9yaXR5MB4XDTk3MDExMDA3MDAwMFoXDTIwMTIzMTA3MDAwMFow
+cDErMCkGA1UECxMiQ29weXJpZ2h0IChjKSAxOTk3IE1pY3Jvc29mdCBDb3JwLjEe
+MBwGA1UECxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3Nv
+ZnQgUm9vdCBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCpAr3BcOY78k4bKJ+XeF4w6qKpjSVf+P6VTKO3/p2iID58UaKboo9gMmvRQmR5
+7qx2yVTa8uuchhyPn4Rms8VremIj1h083g8BkuiWxL8tZpqaaCaZ0Dosvwy1WCbB
+RucKPjiWLKkoOajsSYNC44QPu5psVWGsgnyhYC13TOmZtGQ7mlAcMQgkFJ+p55Er
+GOY9mGMUYFgFZZ8dN1KH96fvlALGG9O/VUWziYC/OuxUlE6u/ad6bXROrxjMlgko
+IQBXkGBpN7tLEgc8Vv9b+6RmCgim0oFWV++2O14WgXcE2va+roCV/rDNf9anGnJc
+PMq88AijIjCzBoXJsyB3E4XfAgMBAAGjgagwgaUwgaIGA1UdAQSBmjCBl4AQW9Bw
+72lyniNRfhSyTY7/y6FyMHAxKzApBgNVBAsTIkNvcHlyaWdodCAoYykgMTk5NyBN
+aWNyb3NvZnQgQ29ycC4xHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEh
+MB8GA1UEAxMYTWljcm9zb2Z0IFJvb3QgQXV0aG9yaXR5gg8AwQCLPDyIEdE+9mPs
+30AwDQYJKoZIhvcNAQEEBQADggEBAJXoC8CN85cYNe24ASTYdxHzXGAyn54Lyz4F
+kYiPyTrmIfLwV5MstaBHyGLv/NfMOztaqTZUaf4kbT/JzKreBXzdMY09nxBwarv+
+Ek8YacD80EPjEVogT+pie6+qGcgrNyUtvmWhEoolD2Oj91Qc+SHJ1hXzUqxuQzIH
+/YIX+OVnbA1R9r3xUse958Qw/CAxCYgdlSkaTdUdAqXxgOADtFv0sd3IV+5lScdS
+VLa0AygS/5DW8AiPfriXxas3LOR65Kh343agANBqP8HSNorgQRKoNWobats14dQc
+BOSoRQTIWjM4bk0cDWK3CqKM09VUP0bNHFWmcNsSOoeTdZ+n0qA=
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/ms_iis.cer b/libs/luci-lib-nixio/axTLS/ssl/test/ms_iis.cer
new file mode 100755
index 0000000000..250b926d68
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/ms_iis.cer
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB5jCCAVOgAwIBAgIQWPe7KyA+U7lLUohulwW2HDAJBgUrDgMCHQUAMCExHzAd
+BgNVBAMTFmF4dGxzLmNlcm9jY2x1Yi5jb20uYXUwHhcNMDgwMzE3MTAyMTA2WhcN
+MDkwMzE3MTAyMTA2WjAhMR8wHQYDVQQDExZheHRscy5jZXJvY2NsdWIuY29tLmF1
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9JqHlQjrQMt3JW8yxcGhFagDa
+D4QiIY8+KItTt13fIBt5g1AG4VXniaylSqKKYNPwVzqSWl7WhxMmoFU73veF8o4M
+G0Zc5qbVB6ukrSV4WaTgHrIO6pWkyiaQ4L/eYfCo/2pByhl0IUKkf/TMN346/rFg
+JgrElx01l6QHNQrzVQIDAQABoycwJTATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNV
+HQ8EBwMFALAAAAAwCQYFKw4DAh0FAAOBgQAbH94H1fryngROJ//Oa0D3vvTO8CJ3
+8VW+3gQEwrPBOWmN6RV8OM0dE6pf8wD3s7PTCcM5+/HI1Qk53nUGrNiOmKM1s0JB
+bvsO9RT+UF8mtdbo/n30M0MHMWPCC76baW3R+ANBp/V/z4l1ytpUTt+MHvz0VlUs
+J4uJA3s3uh23Tg==
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/perf_bigint.c b/libs/luci-lib-nixio/axTLS/ssl/test/perf_bigint.c
new file mode 100644
index 0000000000..a4ffab6a3a
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/perf_bigint.c
@@ -0,0 +1,228 @@
+/*
+ * 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 performance testing of bigint.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ssl.h"
+
+/**************************************************************************
+ * BIGINT tests
+ *
+ **************************************************************************/
+
+int main(int argc, char *argv[])
+{
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+ RSA_CTX *rsa_ctx;
+ BI_CTX *ctx;
+ bigint *bi_data, *bi_res;
+ int diff, res = 1;
+ struct timeval tv_old, tv_new;
+ const char *plaintext;
+ uint8_t compare[MAX_KEY_BYTE_SIZE];
+ int i, max_biggie = 10; /* really crank performance */
+ int len;
+ uint8_t *buf;
+
+ /**
+ * 512 bit key
+ */
+ plaintext = /* 64 byte number */
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^";
+
+ len = get_file("../ssl/test/axTLS.key_512", &buf);
+ asn1_get_private_key(buf, len, &rsa_ctx);
+ ctx = rsa_ctx->bi_ctx;
+ bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
+ bi_res = RSA_public(rsa_ctx, bi_data);
+ bi_data = bi_res; /* reuse again */
+
+ gettimeofday(&tv_old, NULL);
+ for (i = 0; i < max_biggie; i++)
+ {
+ bi_res = RSA_private(rsa_ctx, bi_copy(bi_data));
+ if (i < max_biggie-1)
+ {
+ bi_free(ctx, bi_res);
+ }
+ }
+
+ gettimeofday(&tv_new, NULL);
+ bi_free(ctx, bi_data);
+
+ diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
+ (tv_new.tv_usec-tv_old.tv_usec)/1000;
+ printf("512 bit decrypt time: %dms\n", diff/max_biggie);
+ TTY_FLUSH();
+ bi_export(ctx, bi_res, compare, 64);
+ RSA_free(rsa_ctx);
+ free(buf);
+ if (memcmp(plaintext, compare, 64) != 0)
+ goto end;
+
+ /**
+ * 1024 bit key
+ */
+ plaintext = /* 128 byte number */
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^";
+
+ len = get_file("../ssl/test/axTLS.key_1024", &buf);
+ asn1_get_private_key(buf, len, &rsa_ctx);
+ ctx = rsa_ctx->bi_ctx;
+ bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
+ bi_res = RSA_public(rsa_ctx, bi_data);
+ bi_data = bi_res; /* reuse again */
+
+ gettimeofday(&tv_old, NULL);
+ for (i = 0; i < max_biggie; i++)
+ {
+ bi_res = RSA_private(rsa_ctx, bi_copy(bi_data));
+ if (i < max_biggie-1)
+ {
+ bi_free(ctx, bi_res);
+ }
+ }
+
+ gettimeofday(&tv_new, NULL);
+ bi_free(ctx, bi_data);
+
+ diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
+ (tv_new.tv_usec-tv_old.tv_usec)/1000;
+ printf("1024 bit decrypt time: %dms\n", diff/max_biggie);
+ TTY_FLUSH();
+ bi_export(ctx, bi_res, compare, 128);
+ RSA_free(rsa_ctx);
+ free(buf);
+ if (memcmp(plaintext, compare, 128) != 0)
+ goto end;
+
+ /**
+ * 2048 bit key
+ */
+ plaintext = /* 256 byte number */
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^";
+
+ len = get_file("../ssl/test/axTLS.key_2048", &buf);
+ asn1_get_private_key(buf, len, &rsa_ctx);
+ ctx = rsa_ctx->bi_ctx;
+ bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
+ bi_res = RSA_public(rsa_ctx, bi_data);
+ bi_data = bi_res; /* reuse again */
+
+ gettimeofday(&tv_old, NULL);
+ for (i = 0; i < max_biggie; i++)
+ {
+ bi_res = RSA_private(rsa_ctx, bi_copy(bi_data));
+ if (i < max_biggie-1)
+ {
+ bi_free(ctx, bi_res);
+ }
+ }
+ gettimeofday(&tv_new, NULL);
+ bi_free(ctx, bi_data);
+
+ diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
+ (tv_new.tv_usec-tv_old.tv_usec)/1000;
+ printf("2048 bit decrypt time: %dms\n", diff/max_biggie);
+ TTY_FLUSH();
+ bi_export(ctx, bi_res, compare, 256);
+ RSA_free(rsa_ctx);
+ free(buf);
+ if (memcmp(plaintext, compare, 256) != 0)
+ goto end;
+
+ /**
+ * 4096 bit key
+ */
+ plaintext = /* 512 byte number */
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^"
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*^";
+
+ len = get_file("../ssl/test/axTLS.key_4096", &buf);
+ asn1_get_private_key(buf, len, &rsa_ctx);
+ ctx = rsa_ctx->bi_ctx;
+ bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
+ gettimeofday(&tv_old, NULL);
+ bi_res = RSA_public(rsa_ctx, bi_data);
+ gettimeofday(&tv_new, NULL);
+ diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
+ (tv_new.tv_usec-tv_old.tv_usec)/1000;
+ printf("4096 bit encrypt time: %dms\n", diff);
+ TTY_FLUSH();
+ bi_data = bi_res; /* reuse again */
+
+ gettimeofday(&tv_old, NULL);
+ for (i = 0; i < max_biggie; i++)
+ {
+ bi_res = RSA_private(rsa_ctx, bi_copy(bi_data));
+ if (i < max_biggie-1)
+ {
+ bi_free(ctx, bi_res);
+ }
+ }
+
+ gettimeofday(&tv_new, NULL);
+ bi_free(ctx, bi_data);
+
+ diff = (tv_new.tv_sec-tv_old.tv_sec)*1000 +
+ (tv_new.tv_usec-tv_old.tv_usec)/1000;
+ printf("4096 bit decrypt time: %dms\n", diff/max_biggie);
+ TTY_FLUSH();
+ bi_export(ctx, bi_res, compare, 512);
+ RSA_free(rsa_ctx);
+ free(buf);
+ if (memcmp(plaintext, compare, 512) != 0)
+ goto end;
+
+ /* done */
+ printf("Bigint performance testing complete\n");
+ res = 0;
+
+end:
+ return res;
+#else
+ return 0;
+#endif
+}
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/socgen.cer b/libs/luci-lib-nixio/axTLS/ssl/test/socgen.cer
new file mode 100755
index 0000000000..a4278705b7
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/socgen.cer
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c b/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c
new file mode 100644
index 0000000000..d525e1a686
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c
@@ -0,0 +1,1983 @@
+/*
+ * 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.
+ */
+
+/*
+ * The testing of the crypto and ssl stuff goes here. Keeps the individual code
+ * modules from being uncluttered with test code.
+ *
+ * This is test code - I make no apologies for the quality!
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifndef WIN32
+#include <pthread.h>
+#endif
+
+#include "ssl.h"
+
+#define DEFAULT_CERT "../ssl/test/axTLS.x509_512.cer"
+#define DEFAULT_KEY "../ssl/test/axTLS.key_512"
+//#define DEFAULT_SVR_OPTION SSL_DISPLAY_BYTES|SSL_DISPLAY_STATES
+#define DEFAULT_SVR_OPTION 0
+#define DEFAULT_CLNT_OPTION 0
+//#define DEFAULT_CLNT_OPTION SSL_DISPLAY_BYTES|SSL_DISPLAY_STATES
+
+static int g_port = 19001;
+
+/**************************************************************************
+ * AES tests
+ *
+ * Run through a couple of the RFC3602 tests to verify that AES is correct.
+ **************************************************************************/
+#define TEST1_SIZE 16
+#define TEST2_SIZE 32
+
+static int AES_test(BI_CTX *bi_ctx)
+{
+ AES_CTX aes_key;
+ int res = 1;
+ uint8_t key[TEST1_SIZE];
+ uint8_t iv[TEST1_SIZE];
+
+ {
+ /*
+ Case #1: Encrypting 16 bytes (1 block) using AES-CBC
+ Key : 0x06a9214036b8a15b512e03d534120006
+ IV : 0x3dafba429d9eb430b422da802c9fac41
+ Plaintext : "Single block msg"
+ Ciphertext: 0xe353779c1079aeb82708942dbe77181a
+
+ */
+ char *in_str = "Single block msg";
+ uint8_t ct[TEST1_SIZE];
+ uint8_t enc_data[TEST1_SIZE];
+ uint8_t dec_data[TEST1_SIZE];
+
+ bigint *key_bi = bi_str_import(
+ bi_ctx, "06A9214036B8A15B512E03D534120006");
+ bigint *iv_bi = bi_str_import(
+ bi_ctx, "3DAFBA429D9EB430B422DA802C9FAC41");
+ bigint *ct_bi = bi_str_import(
+ bi_ctx, "E353779C1079AEB82708942DBE77181A");
+ bi_export(bi_ctx, key_bi, key, TEST1_SIZE);
+ bi_export(bi_ctx, iv_bi, iv, TEST1_SIZE);
+ bi_export(bi_ctx, ct_bi, ct, TEST1_SIZE);
+
+ AES_set_key(&aes_key, key, iv, AES_MODE_128);
+ AES_cbc_encrypt(&aes_key, (const uint8_t *)in_str,
+ enc_data, sizeof(enc_data));
+ if (memcmp(enc_data, ct, sizeof(ct)))
+ {
+ printf("Error: AES ENCRYPT #1 failed\n");
+ goto end;
+ }
+
+ AES_set_key(&aes_key, key, iv, AES_MODE_128);
+ AES_convert_key(&aes_key);
+ AES_cbc_decrypt(&aes_key, enc_data, dec_data, sizeof(enc_data));
+
+ if (memcmp(dec_data, in_str, sizeof(dec_data)))
+ {
+ printf("Error: AES DECRYPT #1 failed\n");
+ goto end;
+ }
+ }
+
+ {
+ /*
+ Case #2: Encrypting 32 bytes (2 blocks) using AES-CBC
+ Key : 0xc286696d887c9aa0611bbb3e2025a45a
+ IV : 0x562e17996d093d28ddb3ba695a2e6f58
+ Plaintext : 0x000102030405060708090a0b0c0d0e0f
+ 101112131415161718191a1b1c1d1e1f
+ Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a
+ 7586602d253cfff91b8266bea6d61ab1
+ */
+ uint8_t in_data[TEST2_SIZE];
+ uint8_t ct[TEST2_SIZE];
+ uint8_t enc_data[TEST2_SIZE];
+ uint8_t dec_data[TEST2_SIZE];
+
+ bigint *in_bi = bi_str_import(bi_ctx,
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
+ bigint *key_bi = bi_str_import(
+ bi_ctx, "C286696D887C9AA0611BBB3E2025A45A");
+ bigint *iv_bi = bi_str_import(
+ bi_ctx, "562E17996D093D28DDB3BA695A2E6F58");
+ bigint *ct_bi = bi_str_import(bi_ctx,
+ "D296CD94C2CCCF8A3A863028B5E1DC0A7586602D253CFFF91B8266BEA6D61AB1");
+ bi_export(bi_ctx, in_bi, in_data, TEST2_SIZE);
+ bi_export(bi_ctx, key_bi, key, TEST1_SIZE);
+ bi_export(bi_ctx, iv_bi, iv, TEST1_SIZE);
+ bi_export(bi_ctx, ct_bi, ct, TEST2_SIZE);
+
+ AES_set_key(&aes_key, key, iv, AES_MODE_128);
+ AES_cbc_encrypt(&aes_key, (const uint8_t *)in_data,
+ enc_data, sizeof(enc_data));
+
+ if (memcmp(enc_data, ct, sizeof(ct)))
+ {
+ printf("Error: ENCRYPT #2 failed\n");
+ goto end;
+ }
+
+ AES_set_key(&aes_key, key, iv, AES_MODE_128);
+ AES_convert_key(&aes_key);
+ AES_cbc_decrypt(&aes_key, enc_data, dec_data, sizeof(enc_data));
+ if (memcmp(dec_data, in_data, sizeof(dec_data)))
+ {
+ printf("Error: DECRYPT #2 failed\n");
+ goto end;
+ }
+ }
+
+ res = 0;
+ printf("All AES tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * RC4 tests
+ *
+ * ARC4 tests vectors from OpenSSL (crypto/rc4/rc4test.c)
+ **************************************************************************/
+static const uint8_t keys[7][30]=
+{
+ {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
+ {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
+ {8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ {4,0xef,0x01,0x23,0x45},
+ {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
+ {4,0xef,0x01,0x23,0x45},
+};
+
+static const uint8_t data_len[7]={8,8,8,20,28,10};
+static uint8_t data[7][30]=
+{
+ {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xff},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff},
+ {0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
+ 0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
+ 0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
+ 0x12,0x34,0x56,0x78,0xff},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
+ {0},
+};
+
+static const uint8_t output[7][30]=
+{
+ {0x75,0xb7,0x87,0x80,0x99,0xe0,0xc5,0x96,0x00},
+ {0x74,0x94,0xc2,0xe7,0x10,0x4b,0x08,0x79,0x00},
+ {0xde,0x18,0x89,0x41,0xa3,0x37,0x5d,0x3a,0x00},
+ {0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,
+ 0xbd,0x61,0x5a,0x11,0x62,0xe1,0xc7,0xba,
+ 0x36,0xb6,0x78,0x58,0x00},
+ {0x66,0xa0,0x94,0x9f,0x8a,0xf7,0xd6,0x89,
+ 0x1f,0x7f,0x83,0x2b,0xa8,0x33,0xc0,0x0c,
+ 0x89,0x2e,0xbe,0x30,0x14,0x3c,0xe2,0x87,
+ 0x40,0x01,0x1e,0xcf,0x00},
+ {0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,0xbd,0x61,0x00},
+ {0},
+};
+
+static int RC4_test(BI_CTX *bi_ctx)
+{
+ int i, res = 1;
+ RC4_CTX s;
+
+ for (i = 0; i < 6; i++)
+ {
+ RC4_setup(&s, &keys[i][1], keys[i][0]);
+ RC4_crypt(&s, data[i], data[i], data_len[i]);
+
+ if (memcmp(data[i], output[i], data_len[i]))
+ {
+ printf("Error: RC4 CRYPT #%d failed\n", i);
+ goto end;
+ }
+ }
+
+ res = 0;
+ printf("All RC4 tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * SHA1 tests
+ *
+ * Run through a couple of the RFC3174 tests to verify that SHA1 is correct.
+ **************************************************************************/
+static int SHA1_test(BI_CTX *bi_ctx)
+{
+ SHA1_CTX ctx;
+ uint8_t ct[SHA1_SIZE];
+ uint8_t digest[SHA1_SIZE];
+ int res = 1;
+
+ {
+ const char *in_str = "abc";
+ bigint *ct_bi = bi_str_import(bi_ctx,
+ "A9993E364706816ABA3E25717850C26C9CD0D89D");
+ bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, (const uint8_t *)in_str, strlen(in_str));
+ SHA1_Final(digest, &ctx);
+
+ if (memcmp(digest, ct, sizeof(ct)))
+ {
+ printf("Error: SHA1 #1 failed\n");
+ goto end;
+ }
+ }
+
+ {
+ const char *in_str =
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+ bigint *ct_bi = bi_str_import(bi_ctx,
+ "84983E441C3BD26EBAAE4AA1F95129E5E54670F1");
+ bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, (const uint8_t *)in_str, strlen(in_str));
+ SHA1_Final(digest, &ctx);
+
+ if (memcmp(digest, ct, sizeof(ct)))
+ {
+ printf("Error: SHA1 #2 failed\n");
+ goto end;
+ }
+ }
+
+ res = 0;
+ printf("All SHA1 tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * MD5 tests
+ *
+ * Run through a couple of the RFC1321 tests to verify that MD5 is correct.
+ **************************************************************************/
+static int MD5_test(BI_CTX *bi_ctx)
+{
+ MD5_CTX ctx;
+ uint8_t ct[MD5_SIZE];
+ uint8_t digest[MD5_SIZE];
+ int res = 1;
+
+ {
+ const char *in_str = "abc";
+ bigint *ct_bi = bi_str_import(bi_ctx,
+ "900150983CD24FB0D6963F7D28E17F72");
+ bi_export(bi_ctx, ct_bi, ct, MD5_SIZE);
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, (const uint8_t *)in_str, strlen(in_str));
+ MD5_Final(digest, &ctx);
+
+ if (memcmp(digest, ct, sizeof(ct)))
+ {
+ printf("Error: MD5 #1 failed\n");
+ goto end;
+ }
+ }
+
+ {
+ const char *in_str =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ bigint *ct_bi = bi_str_import(
+ bi_ctx, "D174AB98D277D9F5A5611C2C9F419D9F");
+ bi_export(bi_ctx, ct_bi, ct, MD5_SIZE);
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, (const uint8_t *)in_str, strlen(in_str));
+ MD5_Final(digest, &ctx);
+
+ if (memcmp(digest, ct, sizeof(ct)))
+ {
+ printf("Error: MD5 #2 failed\n");
+ goto end;
+ }
+ }
+ res = 0;
+ printf("All MD5 tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * HMAC tests
+ *
+ * Run through a couple of the RFC2202 tests to verify that HMAC is correct.
+ **************************************************************************/
+static int HMAC_test(BI_CTX *bi_ctx)
+{
+ uint8_t key[SHA1_SIZE];
+ uint8_t ct[SHA1_SIZE];
+ uint8_t dgst[SHA1_SIZE];
+ int res = 1;
+ const char *key_str;
+
+ const char *data_str = "Hi There";
+ bigint *key_bi = bi_str_import(bi_ctx, "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
+ bigint *ct_bi = bi_str_import(bi_ctx, "9294727A3638BB1C13F48EF8158BFC9D");
+ bi_export(bi_ctx, key_bi, key, MD5_SIZE);
+ bi_export(bi_ctx, ct_bi, ct, MD5_SIZE);
+ hmac_md5((const uint8_t *)data_str, 8, key, MD5_SIZE, dgst);
+ if (memcmp(dgst, ct, MD5_SIZE))
+ {
+ printf("HMAC MD5 #1 failed\n");
+ goto end;
+ }
+
+ data_str = "what do ya want for nothing?";
+ key_str = "Jefe";
+ ct_bi = bi_str_import(bi_ctx, "750C783E6AB0B503EAA86E310A5DB738");
+ bi_export(bi_ctx, ct_bi, ct, MD5_SIZE);
+ hmac_md5((const uint8_t *)data_str, 28, (const uint8_t *)key_str, 4, dgst);
+ if (memcmp(dgst, ct, MD5_SIZE))
+ {
+ printf("HMAC MD5 #2 failed\n");
+ goto end;
+ }
+
+ data_str = "Hi There";
+ key_bi = bi_str_import(bi_ctx, "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
+ bi_export(bi_ctx, key_bi, key, SHA1_SIZE);
+ ct_bi = bi_str_import(bi_ctx, "B617318655057264E28BC0B6FB378C8EF146BE00");
+ bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
+
+ hmac_sha1((const uint8_t *)data_str, 8,
+ (const uint8_t *)key, SHA1_SIZE, dgst);
+ if (memcmp(dgst, ct, SHA1_SIZE))
+ {
+ printf("HMAC SHA1 #1 failed\n");
+ goto end;
+ }
+
+ data_str = "what do ya want for nothing?";
+ key_str = "Jefe";
+ ct_bi = bi_str_import(bi_ctx, "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79");
+ bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
+
+ hmac_sha1((const uint8_t *)data_str, 28, (const uint8_t *)key_str, 5, dgst);
+ if (memcmp(dgst, ct, SHA1_SIZE))
+ {
+ printf("HMAC SHA1 failed\n");
+ exit(1);
+ }
+
+ res = 0;
+ printf("All HMAC tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * BIGINT tests
+ *
+ **************************************************************************/
+static int BIGINT_test(BI_CTX *ctx)
+{
+ int res = 1;
+ bigint *bi_data, *bi_exp, *bi_res;
+ const char *expnt, *plaintext, *mod;
+ uint8_t compare[MAX_KEY_BYTE_SIZE];
+
+ /**
+ * 512 bit key
+ */
+ plaintext = /* 64 byte number */
+ "01aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee";
+
+ mod = "C30773C8ABE09FCC279EE0E5343370DE"
+ "8B2FFDB6059271E3005A7CEEF0D35E0A"
+ "1F9915D95E63560836CC2EB2C289270D"
+ "BCAE8CAF6F5E907FC2759EE220071E1B";
+
+ expnt = "A1E556CD1738E10DF539E35101334E97"
+ "BE8D391C57A5C89A7AD9A2EA2ACA1B3D"
+ "F3140F5091CC535CBAA47CEC4159EE1F"
+ "B6A3661AFF1AB758426EAB158452A9B9";
+
+ bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
+ bi_exp = int_to_bi(ctx, 0x10001);
+ bi_set_mod(ctx, bi_str_import(ctx, mod), 0);
+ bi_res = bi_mod_power(ctx, bi_data, bi_exp);
+
+ bi_data = bi_res; /* resuse again - see if we get the original */
+
+ bi_exp = bi_str_import(ctx, expnt);
+ bi_res = bi_mod_power(ctx, bi_data, bi_exp);
+ bi_free_mod(ctx, 0);
+
+ bi_export(ctx, bi_res, compare, 64);
+ if (memcmp(plaintext, compare, 64) != 0)
+ goto end;
+
+ printf("All BIGINT tests passed\n");
+ res = 0;
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * RSA tests
+ *
+ * Use the results from openssl to verify PKCS1 etc
+ **************************************************************************/
+static int RSA_test(void)
+{
+ int res = 1;
+ const char *plaintext = /* 128 byte hex number */
+ "1aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee2"
+ "1aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeee2\012";
+ uint8_t enc_data[128], dec_data[128];
+ RSA_CTX *rsa_ctx = NULL;
+ BI_CTX *bi_ctx;
+ bigint *plaintext_bi;
+ bigint *enc_data_bi, *dec_data_bi;
+ uint8_t enc_data2[128], dec_data2[128];
+ int size;
+ int len;
+ uint8_t *buf;
+
+ /* extract the private key elements */
+ len = get_file("../ssl/test/axTLS.key_1024", &buf);
+ if (asn1_get_private_key(buf, len, &rsa_ctx) < 0)
+ {
+ goto end;
+ }
+
+ free(buf);
+ bi_ctx = rsa_ctx->bi_ctx;
+ plaintext_bi = bi_import(bi_ctx,
+ (const uint8_t *)plaintext, strlen(plaintext));
+
+ /* basic rsa encrypt */
+ enc_data_bi = RSA_public(rsa_ctx, plaintext_bi);
+ bi_export(bi_ctx, bi_copy(enc_data_bi), enc_data, sizeof(enc_data));
+
+ /* basic rsa decrypt */
+ dec_data_bi = RSA_private(rsa_ctx, enc_data_bi);
+ bi_export(bi_ctx, dec_data_bi, dec_data, sizeof(dec_data));
+
+ if (memcmp(dec_data, plaintext, strlen(plaintext)))
+ {
+ printf("Error: DECRYPT #1 failed\n");
+ goto end;
+ }
+
+ RSA_encrypt(rsa_ctx, (const uint8_t *)"abc", 3, enc_data2, 0);
+ size = RSA_decrypt(rsa_ctx, enc_data2, dec_data2, 1);
+ if (memcmp("abc", dec_data2, 3))
+ {
+ printf("Error: ENCRYPT/DECRYPT #2 failed\n");
+ goto end;
+ }
+
+ RSA_free(rsa_ctx);
+ res = 0;
+ printf("All RSA tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * Cert Testing
+ *
+ **************************************************************************/
+static int cert_tests(void)
+{
+ int res = -1, len;
+ X509_CTX *x509_ctx;
+ SSL_CTX *ssl_ctx;
+ uint8_t *buf;
+
+ /* check a bunch of 3rd party certificates */
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/microsoft.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #1\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/thawte.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #2\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/deutsche_telecom.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #3\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/equifax.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #4\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/gnutls.cer", &buf);
+ if ((res = add_cert(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #5\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/socgen.cer", &buf);
+ if ((res = add_cert(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #6\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/verisign.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) <0)
+ {
+ printf("Cert #7\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ if (get_file("../ssl/test/verisign.x509_my_cert", &buf) < 0 ||
+ x509_new(buf, &len, &x509_ctx))
+ {
+ printf("Cert #8\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ x509_free(x509_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ if ((res = ssl_obj_load(ssl_ctx,
+ SSL_OBJ_X509_CERT, "../ssl/test/ms_iis.cer", NULL)) != SSL_OK)
+ {
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ res = 0; /* all ok */
+ printf("All Certificate tests passed\n");
+
+bad_cert:
+ if (res)
+ printf("Error: A certificate test failed\n");
+ return res;
+}
+
+/**
+ * init a server socket.
+ */
+static int server_socket_init(int *port)
+{
+ struct sockaddr_in serv_addr;
+ int server_fd;
+ char yes = 1;
+
+ /* Create socket for incoming connections */
+ if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ return -1;
+ }
+
+ setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
+
+go_again:
+ /* Construct local address structure */
+ memset(&serv_addr, 0, sizeof(serv_addr)); /* Zero out structure */
+ serv_addr.sin_family = AF_INET; /* Internet address family */
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
+ serv_addr.sin_port = htons(*port); /* Local port */
+
+ /* Bind to the local address */
+ if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
+ {
+ (*port)++;
+ goto go_again;
+ }
+ /* Mark the socket so it will listen for incoming connections */
+ if (listen(server_fd, 3000) < 0)
+ {
+ return -1;
+ }
+
+ return server_fd;
+}
+
+/**
+ * init a client socket.
+ */
+static int client_socket_init(uint16_t port)
+{
+ struct sockaddr_in address;
+ int client_fd;
+
+ address.sin_family = AF_INET;
+ address.sin_port = htons(port);
+ address.sin_addr.s_addr = inet_addr("127.0.0.1");
+ client_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (connect(client_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
+ {
+ perror("socket");
+ SOCKET_CLOSE(client_fd);
+ client_fd = -1;
+ }
+
+ return client_fd;
+}
+
+/**************************************************************************
+ * SSL Server Testing
+ *
+ **************************************************************************/
+typedef struct
+{
+ /* not used as yet */
+ int dummy;
+} SVR_CTX;
+
+typedef struct
+{
+ const char *testname;
+ const char *openssl_option;
+} client_t;
+
+static void do_client(client_t *clnt)
+{
+ char openssl_buf[2048];
+
+ /* make sure the main thread goes first */
+ sleep(0);
+
+ /* show the session ids in the reconnect test */
+ if (strcmp(clnt->testname, "Session Reuse") == 0)
+ {
+ sprintf(openssl_buf, "echo \"hello client\" | openssl s_client "
+ "-connect localhost:%d %s 2>&1 | grep \"Session-ID:\"",
+ g_port, clnt->openssl_option);
+ }
+ else
+ {
+ sprintf(openssl_buf, "echo \"hello client\" | openssl s_client "
+#ifdef WIN32
+ "-connect localhost:%d -quiet %s",
+#else
+ "-connect localhost:%d -quiet %s > /dev/null 2>&1",
+#endif
+ g_port, clnt->openssl_option);
+ }
+
+ system(openssl_buf);
+}
+
+static int SSL_server_test(
+ const char *testname,
+ const char *openssl_option,
+ const char *device_cert,
+ const char *product_cert,
+ const char *private_key,
+ const char *ca_cert,
+ const char *password,
+ int axtls_option)
+{
+ int server_fd, ret = 0;
+ SSL_CTX *ssl_ctx = NULL;
+ struct sockaddr_in client_addr;
+ uint8_t *read_buf;
+ socklen_t clnt_len = sizeof(client_addr);
+ client_t client_data;
+#ifndef WIN32
+ pthread_t thread;
+#endif
+ g_port++;
+
+ client_data.testname = testname;
+ client_data.openssl_option = openssl_option;
+
+ if ((server_fd = server_socket_init(&g_port)) < 0)
+ goto error;
+
+ if (private_key)
+ {
+ axtls_option |= SSL_NO_DEFAULT_KEY;
+ }
+
+ if ((ssl_ctx = ssl_ctx_new(axtls_option, SSL_DEFAULT_SVR_SESS)) == NULL)
+ {
+ ret = SSL_ERROR_INVALID_KEY;
+ goto error;
+ }
+
+ if (private_key)
+ {
+ int obj_type = SSL_OBJ_RSA_KEY;
+
+ if (strstr(private_key, ".p8"))
+ obj_type = SSL_OBJ_PKCS8;
+ else if (strstr(private_key, ".p12"))
+ obj_type = SSL_OBJ_PKCS12;
+
+ if (ssl_obj_load(ssl_ctx, obj_type, private_key, password))
+ {
+ ret = SSL_ERROR_INVALID_KEY;
+ goto error;
+ }
+ }
+
+ if (device_cert) /* test chaining */
+ {
+ if ((ret = ssl_obj_load(ssl_ctx,
+ SSL_OBJ_X509_CERT, device_cert, NULL)) != SSL_OK)
+ goto error;
+ }
+
+ if (product_cert) /* test chaining */
+ {
+ if ((ret = ssl_obj_load(ssl_ctx,
+ SSL_OBJ_X509_CERT, product_cert, NULL)) != SSL_OK)
+ goto error;
+ }
+
+ if (ca_cert) /* test adding certificate authorities */
+ {
+ if ((ret = ssl_obj_load(ssl_ctx,
+ SSL_OBJ_X509_CACERT, ca_cert, NULL)) != SSL_OK)
+ goto error;
+ }
+
+#ifndef WIN32
+ pthread_create(&thread, NULL,
+ (void *(*)(void *))do_client, (void *)&client_data);
+ pthread_detach(thread);
+#else
+ CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_client,
+ (LPVOID)&client_data, 0, NULL);
+#endif
+
+ for (;;)
+ {
+ int client_fd, size = 0;
+ SSL *ssl;
+
+ /* Wait for a client to connect */
+ if ((client_fd = accept(server_fd,
+ (struct sockaddr *)&client_addr, &clnt_len)) < 0)
+ {
+ ret = SSL_ERROR_SOCK_SETUP_FAILURE;
+ goto error;
+ }
+
+ /* we are ready to go */
+ ssl = ssl_server_new(ssl_ctx, client_fd);
+ while ((size = ssl_read(ssl, &read_buf)) == SSL_OK);
+ SOCKET_CLOSE(client_fd);
+
+ if (size < SSL_OK) /* got some alert or something nasty */
+ {
+ ret = size;
+
+ if (ret == SSL_ERROR_CONN_LOST)
+ {
+ ret = SSL_OK;
+ continue;
+ }
+
+ break; /* we've got a problem */
+ }
+ else /* looks more promising */
+ {
+ if (strstr("hello client", (char *)read_buf) == NULL)
+ {
+ printf("SSL server test \"%s\" passed\n", testname);
+ TTY_FLUSH();
+ ret = 0;
+ break;
+ }
+ }
+
+ ssl_free(ssl);
+ }
+
+ SOCKET_CLOSE(server_fd);
+
+error:
+ ssl_ctx_free(ssl_ctx);
+ return ret;
+}
+
+int SSL_server_tests(void)
+{
+ int ret = -1;
+ struct stat stat_buf;
+ SVR_CTX svr_test_ctx;
+ memset(&svr_test_ctx, 0, sizeof(SVR_CTX));
+
+ printf("### starting server tests\n"); TTY_FLUSH();
+
+ /* Go through the algorithms */
+
+ /*
+ * TLS1 client hello
+ */
+ if ((ret = SSL_server_test("TLSv1", "-cipher RC4-SHA -tls1",
+ NULL, NULL, NULL, NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES128-SHA
+ */
+ if ((ret = SSL_server_test("AES256-SHA", "-cipher AES128-SHA",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES256-SHA
+ */
+ if ((ret = SSL_server_test("AES256-SHA", "-cipher AES128-SHA",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * RC4-SHA
+ */
+ if ((ret = SSL_server_test("RC4-SHA", "-cipher RC4-SHA",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * RC4-MD5
+ */
+ if ((ret = SSL_server_test("RC4-MD5", "-cipher RC4-MD5",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * Session Reuse
+ * all the session id's should match for session resumption.
+ */
+ if ((ret = SSL_server_test("Session Reuse",
+ "-cipher RC4-SHA -reconnect",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * 512 bit RSA key
+ */
+ if ((ret = SSL_server_test("512 bit key", "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_512.cer", NULL,
+ "../ssl/test/axTLS.key_512",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * 1024 bit RSA key (check certificate chaining)
+ */
+ if ((ret = SSL_server_test("1024 bit key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_device.cer",
+ "../ssl/test/axTLS.x509_512.cer",
+ "../ssl/test/axTLS.device_key",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * 2048 bit RSA key
+ */
+ if ((ret = SSL_server_test("2048 bit key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_2048.cer", NULL,
+ "../ssl/test/axTLS.key_2048",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * 4096 bit RSA key
+ */
+ if ((ret = SSL_server_test("4096 bit key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_4096.cer", NULL,
+ "../ssl/test/axTLS.key_4096",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * Client Verification
+ */
+ if ((ret = SSL_server_test("Client Verification",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_2048.pem "
+ "-key ../ssl/test/axTLS.key_2048.pem ",
+ NULL, NULL, NULL,
+ "../ssl/test/axTLS.ca_x509.cer", NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)))
+ goto cleanup;
+
+ /* this test should fail */
+ if (stat("../ssl/test/axTLS.x509_bad_before.pem", &stat_buf) >= 0)
+ {
+ if ((ret = SSL_server_test("Error: Bad Before Cert",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_bad_before.pem "
+ "-key ../ssl/test/axTLS.key_512.pem ",
+ NULL, NULL, NULL,
+ "../ssl/test/axTLS.ca_x509.cer", NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) !=
+ SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID))
+ goto cleanup;
+
+ printf("SSL server test \"%s\" passed\n", "Bad Before Cert");
+ TTY_FLUSH();
+ ret = 0; /* is ok */
+ }
+
+ /* this test should fail */
+ if ((ret = SSL_server_test("Error: Bad After Cert",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_bad_after.pem "
+ "-key ../ssl/test/axTLS.key_512.pem ",
+ NULL, NULL, NULL,
+ "../ssl/test/axTLS.ca_x509.cer", NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) !=
+ SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED))
+ goto cleanup;
+
+ printf("SSL server test \"%s\" passed\n", "Bad After Cert");
+ TTY_FLUSH();
+
+ /*
+ * No trusted cert
+ */
+ if ((ret = SSL_server_test("Error: No trusted certificate",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_512.pem "
+ "-key ../ssl/test/axTLS.key_512.pem ",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) !=
+ SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT))
+ goto cleanup;
+
+ printf("SSL server test \"%s\" passed\n", "No trusted certificate");
+ TTY_FLUSH();
+
+ /*
+ * Self-signed (from the server)
+ */
+ if ((ret = SSL_server_test("Error: Self-signed certificate (from server)",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_512.pem "
+ "-key ../ssl/test/axTLS.key_512.pem "
+ "-CAfile ../ssl/test/axTLS.ca_x509.pem ",
+ NULL, NULL, NULL,
+ NULL, NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) !=
+ SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED))
+ goto cleanup;
+
+ printf("SSL server test \"%s\" passed\n",
+ "Self-signed certificate (from server)");
+ TTY_FLUSH();
+
+ /*
+ * Self-signed (from the client)
+ */
+ if ((ret = SSL_server_test("Self-signed certificate (from client)",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_512.pem "
+ "-key ../ssl/test/axTLS.key_512.pem ",
+ NULL, NULL, NULL,
+ "../ssl/test/axTLS.ca_x509.cer",
+ NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)))
+ goto cleanup;
+
+ /*
+ * Key in PEM format
+ */
+ if ((ret = SSL_server_test("Key in PEM format",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_512.cer", NULL,
+ "../ssl/test/axTLS.key_512.pem", NULL,
+ NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * Cert in PEM format
+ */
+ if ((ret = SSL_server_test("Cert in PEM format",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_512.pem", NULL,
+ "../ssl/test/axTLS.key_512.pem", NULL,
+ NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * Cert chain in PEM format
+ */
+ if ((ret = SSL_server_test("Cert chain in PEM format",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_device.pem",
+ NULL, "../ssl/test/axTLS.device_key.pem",
+ "../ssl/test/axTLS.ca_x509.pem", NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES128 Encrypted key
+ */
+ if ((ret = SSL_server_test("AES128 encrypted key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_aes128.pem", NULL,
+ "../ssl/test/axTLS.key_aes128.pem",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES256 Encrypted key
+ */
+ if ((ret = SSL_server_test("AES256 encrypted key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_aes256.pem", NULL,
+ "../ssl/test/axTLS.key_aes256.pem",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES128 Encrypted invalid key
+ */
+ if ((ret = SSL_server_test("AES128 encrypted invalid key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_aes128.pem", NULL,
+ "../ssl/test/axTLS.key_aes128.pem",
+ NULL, "xyz", DEFAULT_SVR_OPTION)) != SSL_ERROR_INVALID_KEY)
+ goto cleanup;
+
+ printf("SSL server test \"%s\" passed\n", "AES128 encrypted invalid key");
+ TTY_FLUSH();
+
+ /*
+ * PKCS#8 key (encrypted)
+ */
+ if ((ret = SSL_server_test("pkcs#8 encrypted", "-cipher RC4-SHA",
+ DEFAULT_CERT, NULL, "../ssl/test/axTLS.encrypted.p8",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * PKCS#8 key (unencrypted)
+ */
+ if ((ret = SSL_server_test("pkcs#8 unencrypted", "-cipher RC4-SHA",
+ DEFAULT_CERT, NULL, "../ssl/test/axTLS.unencrypted.p8",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * PKCS#12 key/certificate
+ */
+ if ((ret = SSL_server_test("pkcs#12 with CA", "-cipher RC4-SHA",
+ NULL, NULL, "../ssl/test/axTLS.withCA.p12",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ if ((ret = SSL_server_test("pkcs#12 no CA", "-cipher RC4-SHA",
+ DEFAULT_CERT, NULL, "../ssl/test/axTLS.withoutCA.p12",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ ret = 0;
+
+cleanup:
+ if (ret)
+ {
+ printf("Error: A server test failed\n");
+ ssl_display_error(ret);
+ exit(1);
+ }
+ else
+ {
+ printf("All server tests passed\n"); TTY_FLUSH();
+ }
+
+ return ret;
+}
+
+/**************************************************************************
+ * SSL Client Testing
+ *
+ **************************************************************************/
+typedef struct
+{
+ uint8_t session_id[SSL_SESSION_ID_SIZE];
+#ifndef WIN32
+ pthread_t server_thread;
+#endif
+ int start_server;
+ int stop_server;
+ int do_reneg;
+} CLNT_SESSION_RESUME_CTX;
+
+typedef struct
+{
+ const char *testname;
+ const char *openssl_option;
+} server_t;
+
+static void do_server(server_t *svr)
+{
+ char openssl_buf[2048];
+#ifndef WIN32
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#endif
+ sprintf(openssl_buf, "openssl s_server -tls1 "
+ "-accept %d -quiet %s ", g_port, svr->openssl_option);
+ system(openssl_buf);
+}
+
+static int SSL_client_test(
+ const char *test,
+ SSL_CTX **ssl_ctx,
+ const char *openssl_option,
+ CLNT_SESSION_RESUME_CTX *sess_resume,
+ uint32_t client_options,
+ const char *private_key,
+ const char *password,
+ const char *cert)
+{
+ server_t server_data;
+ SSL *ssl = NULL;
+ int client_fd = -1;
+ uint8_t *session_id = NULL;
+ int ret = 1;
+#ifndef WIN32
+ pthread_t thread;
+#endif
+
+ if (sess_resume == NULL || sess_resume->start_server)
+ {
+ g_port++;
+ server_data.openssl_option = openssl_option;
+
+#ifndef WIN32
+ pthread_create(&thread, NULL,
+ (void *(*)(void *))do_server, (void *)&server_data);
+ pthread_detach(thread);
+#else
+ CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_server,
+ (LPVOID)&server_data, 0, NULL);
+#endif
+ }
+
+ usleep(200000); /* allow server to start */
+
+ if (*ssl_ctx == NULL)
+ {
+ if (private_key)
+ {
+ client_options |= SSL_NO_DEFAULT_KEY;
+ }
+
+ if ((*ssl_ctx = ssl_ctx_new(
+ client_options, SSL_DEFAULT_CLNT_SESS)) == NULL)
+ {
+ ret = SSL_ERROR_INVALID_KEY;
+ goto client_test_exit;
+ }
+
+ if (private_key)
+ {
+ int obj_type = SSL_OBJ_RSA_KEY;
+
+ if (strstr(private_key, ".p8"))
+ obj_type = SSL_OBJ_PKCS8;
+ else if (strstr(private_key, ".p12"))
+ obj_type = SSL_OBJ_PKCS12;
+
+ if (ssl_obj_load(*ssl_ctx, obj_type, private_key, password))
+ {
+ ret = SSL_ERROR_INVALID_KEY;
+ goto client_test_exit;
+ }
+ }
+
+ if (cert)
+ {
+ if ((ret = ssl_obj_load(*ssl_ctx,
+ SSL_OBJ_X509_CERT, cert, NULL)) != SSL_OK)
+ {
+ printf("could not add cert %s (%d)\n", cert, ret);
+ TTY_FLUSH();
+ goto client_test_exit;
+ }
+ }
+
+ if (ssl_obj_load(*ssl_ctx, SSL_OBJ_X509_CACERT,
+ "../ssl/test/axTLS.ca_x509.cer", NULL))
+ {
+ printf("could not add cert auth\n"); TTY_FLUSH();
+ goto client_test_exit;
+ }
+ }
+
+ if (sess_resume && !sess_resume->start_server)
+ {
+ session_id = sess_resume->session_id;
+ }
+
+ if ((client_fd = client_socket_init(g_port)) < 0)
+ {
+ printf("could not start socket on %d\n", g_port); TTY_FLUSH();
+ goto client_test_exit;
+ }
+
+ ssl = ssl_client_new(*ssl_ctx, client_fd, session_id, sizeof(session_id));
+
+ /* check the return status */
+ if ((ret = ssl_handshake_status(ssl)))
+ goto client_test_exit;
+
+ /* renegotiate client */
+ if (sess_resume && sess_resume->do_reneg)
+ {
+ if (ssl_renegotiate(ssl) < 0)
+ goto client_test_exit;
+ }
+
+ if (sess_resume)
+ {
+ memcpy(sess_resume->session_id,
+ ssl_get_session_id(ssl), SSL_SESSION_ID_SIZE);
+ }
+
+ if (IS_SET_SSL_FLAG(SSL_SERVER_VERIFY_LATER) &&
+ (ret = ssl_verify_cert(ssl)))
+ {
+ goto client_test_exit;
+ }
+
+ ssl_write(ssl, (uint8_t *)"hello world\n", 13);
+ if (sess_resume)
+ {
+ const uint8_t *sess_id = ssl_get_session_id(ssl);
+ int i;
+
+ printf(" Session-ID: ");
+ for (i = 0; i < SSL_SESSION_ID_SIZE; i++)
+ {
+ printf("%02X", sess_id[i]);
+ }
+ printf("\n");
+ TTY_FLUSH();
+ }
+
+ ret = 0;
+
+client_test_exit:
+ ssl_free(ssl);
+ SOCKET_CLOSE(client_fd);
+ usleep(200000); /* allow openssl to say something */
+
+ if (sess_resume)
+ {
+ if (sess_resume->stop_server)
+ {
+ ssl_ctx_free(*ssl_ctx);
+ *ssl_ctx = NULL;
+#ifndef WIN32
+ pthread_cancel(sess_resume->server_thread);
+#endif
+ }
+ else if (sess_resume->start_server)
+ {
+#ifndef WIN32
+ sess_resume->server_thread = thread;
+#endif
+ }
+ }
+ else
+ {
+ ssl_ctx_free(*ssl_ctx);
+ *ssl_ctx = NULL;
+#ifndef WIN32
+ pthread_cancel(thread);
+#endif
+ }
+
+ if (ret == 0)
+ {
+ printf("SSL client test \"%s\" passed\n", test);
+ TTY_FLUSH();
+ }
+
+ return ret;
+}
+
+int SSL_client_tests(void)
+{
+ int ret = -1;
+ SSL_CTX *ssl_ctx = NULL;
+ CLNT_SESSION_RESUME_CTX sess_resume;
+ memset(&sess_resume, 0, sizeof(CLNT_SESSION_RESUME_CTX));
+
+ sess_resume.start_server = 1;
+ printf("### starting client tests\n");
+
+ if ((ret = SSL_client_test("512 bit key",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_512.pem "
+ "-key ../ssl/test/axTLS.key_512.pem", &sess_resume,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ /* all the session id's should match for session resumption */
+ sess_resume.start_server = 0;
+ if ((ret = SSL_client_test("Client session resumption #1",
+ &ssl_ctx, NULL, &sess_resume,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ sess_resume.do_reneg = 1;
+ if ((ret = SSL_client_test("Client renegotiation",
+ &ssl_ctx, NULL, &sess_resume,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+ sess_resume.do_reneg = 0;
+
+ sess_resume.stop_server = 1;
+ if ((ret = SSL_client_test("Client session resumption #2",
+ &ssl_ctx, NULL, &sess_resume,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ if ((ret = SSL_client_test("1024 bit key",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_1024.pem "
+ "-key ../ssl/test/axTLS.key_1024.pem", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ if ((ret = SSL_client_test("2048 bit key",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_2048.pem "
+ "-key ../ssl/test/axTLS.key_2048.pem", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ if ((ret = SSL_client_test("4096 bit key",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_4096.pem "
+ "-key ../ssl/test/axTLS.key_4096.pem", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ if ((ret = SSL_client_test("Server cert chaining",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_device.pem "
+ "-key ../ssl/test/axTLS.device_key.pem "
+ "-CAfile ../ssl/test/axTLS.x509_512.pem ", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ /* Check the server can verify the client */
+ if ((ret = SSL_client_test("Client peer authentication",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_2048.pem "
+ "-key ../ssl/test/axTLS.key_2048.pem "
+ "-CAfile ../ssl/test/axTLS.ca_x509.pem "
+ "-verify 1 ", NULL, DEFAULT_CLNT_OPTION,
+ "../ssl/test/axTLS.key_1024", NULL,
+ "../ssl/test/axTLS.x509_1024.cer")))
+ goto cleanup;
+
+ /* Should get an "ERROR" from openssl (as the handshake fails as soon as
+ * the certificate verification fails) */
+ if ((ret = SSL_client_test("Error: Expired cert (verify now)",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_bad_after.pem "
+ "-key ../ssl/test/axTLS.key_512.pem", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)) !=
+ SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED))
+ {
+ printf("*** Error: %d\n", ret);
+ goto cleanup;
+ }
+
+ printf("SSL client test \"Expired cert (verify now)\" passed\n");
+
+ /* There is no "ERROR" from openssl */
+ if ((ret = SSL_client_test("Error: Expired cert (verify later)",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_bad_after.pem "
+ "-key ../ssl/test/axTLS.key_512.pem", NULL,
+ DEFAULT_CLNT_OPTION|SSL_SERVER_VERIFY_LATER, NULL,
+ NULL, NULL)) != SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED))
+ {
+ printf("*** Error: %d\n", ret);
+ goto cleanup;
+ }
+
+ printf("SSL client test \"Expired cert (verify later)\" passed\n");
+ ret = 0;
+
+cleanup:
+ if (ret)
+ {
+ ssl_display_error(ret);
+ printf("Error: A client test failed\n");
+ exit(1);
+ }
+ else
+ {
+ printf("All client tests passed\n"); TTY_FLUSH();
+ }
+
+ return ret;
+}
+
+/**************************************************************************
+ * SSL Basic Testing (test a big packet handshake)
+ *
+ **************************************************************************/
+static uint8_t basic_buf[256*1024];
+
+static void do_basic(void)
+{
+ int client_fd;
+ SSL *ssl_clnt;
+ SSL_CTX *ssl_clnt_ctx = ssl_ctx_new(
+ DEFAULT_CLNT_OPTION, SSL_DEFAULT_CLNT_SESS);
+ usleep(200000); /* allow server to start */
+
+ if ((client_fd = client_socket_init(g_port)) < 0)
+ goto error;
+
+ if (ssl_obj_load(ssl_clnt_ctx, SSL_OBJ_X509_CACERT,
+ "../ssl/test/axTLS.ca_x509.cer", NULL))
+ goto error;
+
+ ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0);
+
+ /* check the return status */
+ if (ssl_handshake_status(ssl_clnt) < 0)
+ {
+ printf("YA YA\n");
+ ssl_display_error(ssl_handshake_status(ssl_clnt));
+ goto error;
+ }
+
+ ssl_write(ssl_clnt, basic_buf, sizeof(basic_buf));
+ ssl_free(ssl_clnt);
+
+error:
+ ssl_ctx_free(ssl_clnt_ctx);
+ SOCKET_CLOSE(client_fd);
+
+ /* exit this thread */
+}
+
+static int SSL_basic_test(void)
+{
+ int server_fd, client_fd, ret = 0, size = 0, offset = 0;
+ SSL_CTX *ssl_svr_ctx = NULL;
+ struct sockaddr_in client_addr;
+ uint8_t *read_buf;
+ socklen_t clnt_len = sizeof(client_addr);
+ SSL *ssl_svr;
+#ifndef WIN32
+ pthread_t thread;
+#endif
+ memset(basic_buf, 0xA5, sizeof(basic_buf)/2);
+ memset(&basic_buf[sizeof(basic_buf)/2], 0x5A, sizeof(basic_buf)/2);
+
+ if ((server_fd = server_socket_init(&g_port)) < 0)
+ goto error;
+
+ ssl_svr_ctx = ssl_ctx_new(DEFAULT_SVR_OPTION, SSL_DEFAULT_SVR_SESS);
+
+#ifndef WIN32
+ pthread_create(&thread, NULL,
+ (void *(*)(void *))do_basic, NULL);
+ pthread_detach(thread);
+#else
+ CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_basic, NULL, 0, NULL);
+#endif
+
+ /* Wait for a client to connect */
+ if ((client_fd = accept(server_fd,
+ (struct sockaddr *) &client_addr, &clnt_len)) < 0)
+ {
+ ret = SSL_ERROR_SOCK_SETUP_FAILURE;
+ goto error;
+ }
+
+ /* we are ready to go */
+ ssl_svr = ssl_server_new(ssl_svr_ctx, client_fd);
+
+ do
+ {
+ while ((size = ssl_read(ssl_svr, &read_buf)) == SSL_OK);
+
+ if (size < SSL_OK) /* got some alert or something nasty */
+ {
+ printf("Server ");
+ ssl_display_error(size);
+ ret = size;
+ break;
+ }
+ else /* looks more promising */
+ {
+ if (memcmp(read_buf, &basic_buf[offset], size) != 0)
+ {
+ ret = SSL_NOT_OK;
+ break;
+ }
+ }
+
+ offset += size;
+ } while (offset < sizeof(basic_buf));
+
+ printf(ret == SSL_OK && offset == sizeof(basic_buf) ?
+ "SSL basic test passed\n" :
+ "SSL basic test failed\n");
+ TTY_FLUSH();
+
+ ssl_free(ssl_svr);
+ SOCKET_CLOSE(server_fd);
+ SOCKET_CLOSE(client_fd);
+
+error:
+ ssl_ctx_free(ssl_svr_ctx);
+ return ret;
+}
+
+#if !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING)
+/**************************************************************************
+ * Multi-Threading Tests
+ *
+ **************************************************************************/
+#define NUM_THREADS 100
+
+typedef struct
+{
+ SSL_CTX *ssl_clnt_ctx;
+ int port;
+ int thread_id;
+} multi_t;
+
+void do_multi_clnt(multi_t *multi_data)
+{
+ int res = 1, client_fd, i;
+ SSL *ssl = NULL;
+ char tmp[5];
+
+ if ((client_fd = client_socket_init(multi_data->port)) < 0)
+ goto client_test_exit;
+
+ sleep(1);
+ ssl = ssl_client_new(multi_data->ssl_clnt_ctx, client_fd, NULL, 0);
+
+ if ((res = ssl_handshake_status(ssl)))
+ {
+ printf("Client ");
+ ssl_display_error(res);
+ goto client_test_exit;
+ }
+
+ sprintf(tmp, "%d\n", multi_data->thread_id);
+ for (i = 0; i < 10; i++)
+ ssl_write(ssl, (uint8_t *)tmp, strlen(tmp)+1);
+
+client_test_exit:
+ ssl_free(ssl);
+ SOCKET_CLOSE(client_fd);
+ free(multi_data);
+}
+
+void do_multi_svr(SSL *ssl)
+{
+ uint8_t *read_buf;
+ int *res_ptr = malloc(sizeof(int));
+ int res;
+
+ for (;;)
+ {
+ res = ssl_read(ssl, &read_buf);
+
+ /* kill the client */
+ if (res != SSL_OK)
+ {
+ if (res == SSL_ERROR_CONN_LOST)
+ {
+ SOCKET_CLOSE(ssl->client_fd);
+ ssl_free(ssl);
+ break;
+ }
+ else if (res > 0)
+ {
+ /* do nothing */
+ }
+ else /* some problem */
+ {
+ printf("Server ");
+ ssl_display_error(res);
+ goto error;
+ }
+ }
+ }
+
+ res = SSL_OK;
+error:
+ *res_ptr = res;
+ pthread_exit(res_ptr);
+}
+
+int multi_thread_test(void)
+{
+ int server_fd = -1;
+ SSL_CTX *ssl_server_ctx;
+ SSL_CTX *ssl_clnt_ctx;
+ pthread_t clnt_threads[NUM_THREADS];
+ pthread_t svr_threads[NUM_THREADS];
+ int i, res = 0;
+ struct sockaddr_in client_addr;
+ socklen_t clnt_len = sizeof(client_addr);
+
+ printf("Do multi-threading test (takes a minute)\n");
+
+ ssl_server_ctx = ssl_ctx_new(DEFAULT_SVR_OPTION, SSL_DEFAULT_SVR_SESS);
+ ssl_clnt_ctx = ssl_ctx_new(DEFAULT_CLNT_OPTION, SSL_DEFAULT_CLNT_SESS);
+
+ if (ssl_obj_load(ssl_clnt_ctx, SSL_OBJ_X509_CACERT,
+ "../ssl/test/axTLS.ca_x509.cer", NULL))
+ goto error;
+
+ if ((server_fd = server_socket_init(&g_port)) < 0)
+ goto error;
+
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ multi_t *multi_data = (multi_t *)malloc(sizeof(multi_t));
+ multi_data->ssl_clnt_ctx = ssl_clnt_ctx;
+ multi_data->port = g_port;
+ multi_data->thread_id = i+1;
+ pthread_create(&clnt_threads[i], NULL,
+ (void *(*)(void *))do_multi_clnt, (void *)multi_data);
+ pthread_detach(clnt_threads[i]);
+ }
+
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ SSL *ssl_svr;
+ int client_fd = accept(server_fd,
+ (struct sockaddr *)&client_addr, &clnt_len);
+
+ if (client_fd < 0)
+ goto error;
+
+ ssl_svr = ssl_server_new(ssl_server_ctx, client_fd);
+
+ pthread_create(&svr_threads[i], NULL,
+ (void *(*)(void *))do_multi_svr, (void *)ssl_svr);
+ }
+
+ /* make sure we've run all of the threads */
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ void *thread_res;
+ pthread_join(svr_threads[i], &thread_res);
+
+ if (*((int *)thread_res) != 0)
+ res = 1;
+
+ free(thread_res);
+ }
+
+ if (res)
+ goto error;
+
+ printf("Multi-thread test passed (%d)\n", NUM_THREADS);
+error:
+ ssl_ctx_free(ssl_server_ctx);
+ ssl_ctx_free(ssl_clnt_ctx);
+ SOCKET_CLOSE(server_fd);
+ return res;
+}
+#endif /* !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING) */
+
+/**************************************************************************
+ * Header issue
+ *
+ **************************************************************************/
+static void do_header_issue(void)
+{
+ char axtls_buf[2048];
+#ifndef WIN32
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#endif
+ sprintf(axtls_buf, "./axssl s_client -connect localhost:%d", g_port);
+ system(axtls_buf);
+}
+
+static int header_issue(void)
+{
+ FILE *f = fopen("../ssl/test/header_issue.dat", "r");
+ int server_fd = -1, client_fd = -1, ret = 1;
+ uint8_t buf[2048];
+ int size = 0;
+ struct sockaddr_in client_addr;
+ socklen_t clnt_len = sizeof(client_addr);
+#ifndef WIN32
+ pthread_t thread;
+#endif
+
+ if (f == NULL || (server_fd = server_socket_init(&g_port)) < 0)
+ goto error;
+
+#ifndef WIN32
+ pthread_create(&thread, NULL,
+ (void *(*)(void *))do_header_issue, NULL);
+ pthread_detach(thread);
+#else
+ CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_header_issue,
+ NULL, 0, NULL);
+#endif
+ if ((client_fd = accept(server_fd,
+ (struct sockaddr *) &client_addr, &clnt_len)) < 0)
+ {
+ ret = SSL_ERROR_SOCK_SETUP_FAILURE;
+ goto error;
+ }
+
+ size = fread(buf, 1, sizeof(buf), f);
+ SOCKET_WRITE(client_fd, buf, size);
+ usleep(200000);
+
+ ret = 0;
+error:
+ fclose(f);
+ SOCKET_CLOSE(client_fd);
+ SOCKET_CLOSE(server_fd);
+ TTY_FLUSH();
+ system("killall axssl");
+ return ret;
+}
+
+/**************************************************************************
+ * main()
+ *
+ **************************************************************************/
+int main(int argc, char *argv[])
+{
+ int ret = 1;
+ BI_CTX *bi_ctx;
+ int fd;
+
+#ifdef WIN32
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD(2, 2);
+ WSAStartup(wVersionRequested, &wsaData);
+ fd = _open("test_result.txt", O_WRONLY|O_TEMPORARY|O_CREAT, _S_IWRITE);
+ dup2(fd, 2); /* write stderr to this file */
+#else
+ fd = open("/dev/null", O_WRONLY); /* write stderr to /dev/null */
+ signal(SIGPIPE, SIG_IGN); /* ignore pipe errors */
+ dup2(fd, 2);
+#endif
+
+ /* can't do testing in this mode */
+#if defined CONFIG_SSL_GENERATE_X509_CERT
+ printf("Error: Must compile with default key/certificates\n");
+ exit(1);
+#endif
+
+ bi_ctx = bi_initialize();
+
+ if (AES_test(bi_ctx))
+ {
+ printf("AES tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (RC4_test(bi_ctx))
+ {
+ printf("RC4 tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (MD5_test(bi_ctx))
+ {
+ printf("MD5 tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (SHA1_test(bi_ctx))
+ {
+ printf("SHA1 tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (HMAC_test(bi_ctx))
+ {
+ printf("HMAC tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (BIGINT_test(bi_ctx))
+ {
+ printf("BigInt tests failed!\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ bi_terminate(bi_ctx);
+
+ if (RSA_test())
+ {
+ printf("RSA tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (cert_tests())
+ {
+ printf("CERT tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+#if !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING)
+ if (multi_thread_test())
+ goto cleanup;
+#endif
+
+ if (SSL_basic_test())
+ goto cleanup;
+
+ system("sh ../ssl/test/killopenssl.sh");
+
+ if (SSL_client_tests())
+ goto cleanup;
+
+ system("sh ../ssl/test/killopenssl.sh");
+
+ if (SSL_server_tests())
+ goto cleanup;
+
+ system("sh ../ssl/test/killopenssl.sh");
+
+ if (header_issue())
+ {
+ printf("Header tests failed\n"); TTY_FLUSH();
+ goto cleanup;
+ }
+
+ ret = 0; /* all ok */
+ printf("**** ALL TESTS PASSED ****\n"); TTY_FLUSH();
+cleanup:
+
+ if (ret)
+ printf("Error: Some tests failed!\n");
+
+ close(fd);
+ return ret;
+}
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c.bak b/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c.bak
new file mode 100644
index 0000000000..ca9637f9ac
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c.bak
@@ -0,0 +1,1940 @@
+/*
+ * 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.
+ */
+
+/*
+ * The testing of the crypto and ssl stuff goes here. Keeps the individual code
+ * modules from being uncluttered with test code.
+ *
+ * This is test code - I make no apologies for the quality!
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifndef WIN32
+#include <pthread.h>
+#endif
+
+#include "ssl.h"
+
+#define DEFAULT_CERT "../ssl/test/axTLS.x509_512.cer"
+#define DEFAULT_KEY "../ssl/test/axTLS.key_512"
+//#define DEFAULT_SVR_OPTION SSL_DISPLAY_BYTES|SSL_DISPLAY_STATES
+#define DEFAULT_SVR_OPTION 0
+#define DEFAULT_CLNT_OPTION 0
+//#define DEFAULT_CLNT_OPTION SSL_DISPLAY_BYTES|SSL_DISPLAY_STATES
+
+static int g_port = 19001;
+
+/**************************************************************************
+ * AES tests
+ *
+ * Run through a couple of the RFC3602 tests to verify that AES is correct.
+ **************************************************************************/
+#define TEST1_SIZE 16
+#define TEST2_SIZE 32
+
+static int AES_test(BI_CTX *bi_ctx)
+{
+ AES_CTX aes_key;
+ int res = 1;
+ uint8_t key[TEST1_SIZE];
+ uint8_t iv[TEST1_SIZE];
+
+ {
+ /*
+ Case #1: Encrypting 16 bytes (1 block) using AES-CBC
+ Key : 0x06a9214036b8a15b512e03d534120006
+ IV : 0x3dafba429d9eb430b422da802c9fac41
+ Plaintext : "Single block msg"
+ Ciphertext: 0xe353779c1079aeb82708942dbe77181a
+
+ */
+ char *in_str = "Single block msg";
+ uint8_t ct[TEST1_SIZE];
+ uint8_t enc_data[TEST1_SIZE];
+ uint8_t dec_data[TEST1_SIZE];
+
+ bigint *key_bi = bi_str_import(
+ bi_ctx, "06A9214036B8A15B512E03D534120006");
+ bigint *iv_bi = bi_str_import(
+ bi_ctx, "3DAFBA429D9EB430B422DA802C9FAC41");
+ bigint *ct_bi = bi_str_import(
+ bi_ctx, "E353779C1079AEB82708942DBE77181A");
+ bi_export(bi_ctx, key_bi, key, TEST1_SIZE);
+ bi_export(bi_ctx, iv_bi, iv, TEST1_SIZE);
+ bi_export(bi_ctx, ct_bi, ct, TEST1_SIZE);
+
+ AES_set_key(&aes_key, key, iv, AES_MODE_128);
+ AES_cbc_encrypt(&aes_key, (const uint8_t *)in_str,
+ enc_data, sizeof(enc_data));
+ if (memcmp(enc_data, ct, sizeof(ct)))
+ {
+ printf("Error: AES ENCRYPT #1 failed\n");
+ goto end;
+ }
+
+ AES_set_key(&aes_key, key, iv, AES_MODE_128);
+ AES_convert_key(&aes_key);
+ AES_cbc_decrypt(&aes_key, enc_data, dec_data, sizeof(enc_data));
+
+ if (memcmp(dec_data, in_str, sizeof(dec_data)))
+ {
+ printf("Error: AES DECRYPT #1 failed\n");
+ goto end;
+ }
+ }
+
+ {
+ /*
+ Case #2: Encrypting 32 bytes (2 blocks) using AES-CBC
+ Key : 0xc286696d887c9aa0611bbb3e2025a45a
+ IV : 0x562e17996d093d28ddb3ba695a2e6f58
+ Plaintext : 0x000102030405060708090a0b0c0d0e0f
+ 101112131415161718191a1b1c1d1e1f
+ Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a
+ 7586602d253cfff91b8266bea6d61ab1
+ */
+ uint8_t in_data[TEST2_SIZE];
+ uint8_t ct[TEST2_SIZE];
+ uint8_t enc_data[TEST2_SIZE];
+ uint8_t dec_data[TEST2_SIZE];
+
+ bigint *in_bi = bi_str_import(bi_ctx,
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
+ bigint *key_bi = bi_str_import(
+ bi_ctx, "C286696D887C9AA0611BBB3E2025A45A");
+ bigint *iv_bi = bi_str_import(
+ bi_ctx, "562E17996D093D28DDB3BA695A2E6F58");
+ bigint *ct_bi = bi_str_import(bi_ctx,
+ "D296CD94C2CCCF8A3A863028B5E1DC0A7586602D253CFFF91B8266BEA6D61AB1");
+ bi_export(bi_ctx, in_bi, in_data, TEST2_SIZE);
+ bi_export(bi_ctx, key_bi, key, TEST1_SIZE);
+ bi_export(bi_ctx, iv_bi, iv, TEST1_SIZE);
+ bi_export(bi_ctx, ct_bi, ct, TEST2_SIZE);
+
+ AES_set_key(&aes_key, key, iv, AES_MODE_128);
+ AES_cbc_encrypt(&aes_key, (const uint8_t *)in_data,
+ enc_data, sizeof(enc_data));
+
+ if (memcmp(enc_data, ct, sizeof(ct)))
+ {
+ printf("Error: ENCRYPT #2 failed\n");
+ goto end;
+ }
+
+ AES_set_key(&aes_key, key, iv, AES_MODE_128);
+ AES_convert_key(&aes_key);
+ AES_cbc_decrypt(&aes_key, enc_data, dec_data, sizeof(enc_data));
+ if (memcmp(dec_data, in_data, sizeof(dec_data)))
+ {
+ printf("Error: DECRYPT #2 failed\n");
+ goto end;
+ }
+ }
+
+ res = 0;
+ printf("All AES tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * RC4 tests
+ *
+ * ARC4 tests vectors from OpenSSL (crypto/rc4/rc4test.c)
+ **************************************************************************/
+static const uint8_t keys[7][30]=
+{
+ {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
+ {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
+ {8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+ {4,0xef,0x01,0x23,0x45},
+ {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
+ {4,0xef,0x01,0x23,0x45},
+};
+
+static const uint8_t data_len[7]={8,8,8,20,28,10};
+static uint8_t data[7][30]=
+{
+ {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xff},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff},
+ {0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
+ 0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
+ 0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0,
+ 0x12,0x34,0x56,0x78,0xff},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
+ {0},
+};
+
+static const uint8_t output[7][30]=
+{
+ {0x75,0xb7,0x87,0x80,0x99,0xe0,0xc5,0x96,0x00},
+ {0x74,0x94,0xc2,0xe7,0x10,0x4b,0x08,0x79,0x00},
+ {0xde,0x18,0x89,0x41,0xa3,0x37,0x5d,0x3a,0x00},
+ {0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,
+ 0xbd,0x61,0x5a,0x11,0x62,0xe1,0xc7,0xba,
+ 0x36,0xb6,0x78,0x58,0x00},
+ {0x66,0xa0,0x94,0x9f,0x8a,0xf7,0xd6,0x89,
+ 0x1f,0x7f,0x83,0x2b,0xa8,0x33,0xc0,0x0c,
+ 0x89,0x2e,0xbe,0x30,0x14,0x3c,0xe2,0x87,
+ 0x40,0x01,0x1e,0xcf,0x00},
+ {0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,0xbd,0x61,0x00},
+ {0},
+};
+
+static int RC4_test(BI_CTX *bi_ctx)
+{
+ int i, res = 1;
+ RC4_CTX s;
+
+ for (i = 0; i < 6; i++)
+ {
+ RC4_setup(&s, &keys[i][1], keys[i][0]);
+ RC4_crypt(&s, data[i], data[i], data_len[i]);
+
+ if (memcmp(data[i], output[i], data_len[i]))
+ {
+ printf("Error: RC4 CRYPT #%d failed\n", i);
+ goto end;
+ }
+ }
+
+ res = 0;
+ printf("All RC4 tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * SHA1 tests
+ *
+ * Run through a couple of the RFC3174 tests to verify that SHA1 is correct.
+ **************************************************************************/
+static int SHA1_test(BI_CTX *bi_ctx)
+{
+ SHA1_CTX ctx;
+ uint8_t ct[SHA1_SIZE];
+ uint8_t digest[SHA1_SIZE];
+ int res = 1;
+
+ {
+ const char *in_str = "abc";
+ bigint *ct_bi = bi_str_import(bi_ctx,
+ "A9993E364706816ABA3E25717850C26C9CD0D89D");
+ bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, (const uint8_t *)in_str, strlen(in_str));
+ SHA1_Final(digest, &ctx);
+
+ if (memcmp(digest, ct, sizeof(ct)))
+ {
+ printf("Error: SHA1 #1 failed\n");
+ goto end;
+ }
+ }
+
+ {
+ const char *in_str =
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+ bigint *ct_bi = bi_str_import(bi_ctx,
+ "84983E441C3BD26EBAAE4AA1F95129E5E54670F1");
+ bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
+
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, (const uint8_t *)in_str, strlen(in_str));
+ SHA1_Final(digest, &ctx);
+
+ if (memcmp(digest, ct, sizeof(ct)))
+ {
+ printf("Error: SHA1 #2 failed\n");
+ goto end;
+ }
+ }
+
+ res = 0;
+ printf("All SHA1 tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * MD5 tests
+ *
+ * Run through a couple of the RFC1321 tests to verify that MD5 is correct.
+ **************************************************************************/
+static int MD5_test(BI_CTX *bi_ctx)
+{
+ MD5_CTX ctx;
+ uint8_t ct[MD5_SIZE];
+ uint8_t digest[MD5_SIZE];
+ int res = 1;
+
+ {
+ const char *in_str = "abc";
+ bigint *ct_bi = bi_str_import(bi_ctx,
+ "900150983CD24FB0D6963F7D28E17F72");
+ bi_export(bi_ctx, ct_bi, ct, MD5_SIZE);
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, (const uint8_t *)in_str, strlen(in_str));
+ MD5_Final(digest, &ctx);
+
+ if (memcmp(digest, ct, sizeof(ct)))
+ {
+ printf("Error: MD5 #1 failed\n");
+ goto end;
+ }
+ }
+
+ {
+ const char *in_str =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ bigint *ct_bi = bi_str_import(
+ bi_ctx, "D174AB98D277D9F5A5611C2C9F419D9F");
+ bi_export(bi_ctx, ct_bi, ct, MD5_SIZE);
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, (const uint8_t *)in_str, strlen(in_str));
+ MD5_Final(digest, &ctx);
+
+ if (memcmp(digest, ct, sizeof(ct)))
+ {
+ printf("Error: MD5 #2 failed\n");
+ goto end;
+ }
+ }
+ res = 0;
+ printf("All MD5 tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * HMAC tests
+ *
+ * Run through a couple of the RFC2202 tests to verify that HMAC is correct.
+ **************************************************************************/
+static int HMAC_test(BI_CTX *bi_ctx)
+{
+ uint8_t key[SHA1_SIZE];
+ uint8_t ct[SHA1_SIZE];
+ uint8_t dgst[SHA1_SIZE];
+ int res = 1;
+ const char *key_str;
+
+ const char *data_str = "Hi There";
+ bigint *key_bi = bi_str_import(bi_ctx, "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
+ bigint *ct_bi = bi_str_import(bi_ctx, "9294727A3638BB1C13F48EF8158BFC9D");
+ bi_export(bi_ctx, key_bi, key, MD5_SIZE);
+ bi_export(bi_ctx, ct_bi, ct, MD5_SIZE);
+ hmac_md5((const uint8_t *)data_str, 8, key, MD5_SIZE, dgst);
+ if (memcmp(dgst, ct, MD5_SIZE))
+ {
+ printf("HMAC MD5 #1 failed\n");
+ goto end;
+ }
+
+ data_str = "what do ya want for nothing?";
+ key_str = "Jefe";
+ ct_bi = bi_str_import(bi_ctx, "750C783E6AB0B503EAA86E310A5DB738");
+ bi_export(bi_ctx, ct_bi, ct, MD5_SIZE);
+ hmac_md5((const uint8_t *)data_str, 28, (const uint8_t *)key_str, 4, dgst);
+ if (memcmp(dgst, ct, MD5_SIZE))
+ {
+ printf("HMAC MD5 #2 failed\n");
+ goto end;
+ }
+
+ data_str = "Hi There";
+ key_bi = bi_str_import(bi_ctx, "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B");
+ bi_export(bi_ctx, key_bi, key, SHA1_SIZE);
+ ct_bi = bi_str_import(bi_ctx, "B617318655057264E28BC0B6FB378C8EF146BE00");
+ bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
+
+ hmac_sha1((const uint8_t *)data_str, 8,
+ (const uint8_t *)key, SHA1_SIZE, dgst);
+ if (memcmp(dgst, ct, SHA1_SIZE))
+ {
+ printf("HMAC SHA1 #1 failed\n");
+ goto end;
+ }
+
+ data_str = "what do ya want for nothing?";
+ key_str = "Jefe";
+ ct_bi = bi_str_import(bi_ctx, "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79");
+ bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE);
+
+ hmac_sha1((const uint8_t *)data_str, 28, (const uint8_t *)key_str, 5, dgst);
+ if (memcmp(dgst, ct, SHA1_SIZE))
+ {
+ printf("HMAC SHA1 failed\n");
+ exit(1);
+ }
+
+ res = 0;
+ printf("All HMAC tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * BIGINT tests
+ *
+ **************************************************************************/
+static int BIGINT_test(BI_CTX *ctx)
+{
+ int res = 1;
+ bigint *bi_data, *bi_exp, *bi_res;
+ const char *expnt, *plaintext, *mod;
+ uint8_t compare[MAX_KEY_BYTE_SIZE];
+
+ /**
+ * 512 bit key
+ */
+ plaintext = /* 64 byte number */
+ "01aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee";
+
+ mod = "C30773C8ABE09FCC279EE0E5343370DE"
+ "8B2FFDB6059271E3005A7CEEF0D35E0A"
+ "1F9915D95E63560836CC2EB2C289270D"
+ "BCAE8CAF6F5E907FC2759EE220071E1B";
+
+ expnt = "A1E556CD1738E10DF539E35101334E97"
+ "BE8D391C57A5C89A7AD9A2EA2ACA1B3D"
+ "F3140F5091CC535CBAA47CEC4159EE1F"
+ "B6A3661AFF1AB758426EAB158452A9B9";
+
+ bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext));
+ bi_exp = int_to_bi(ctx, 0x10001);
+ bi_set_mod(ctx, bi_str_import(ctx, mod), 0);
+ bi_res = bi_mod_power(ctx, bi_data, bi_exp);
+
+ bi_data = bi_res; /* resuse again - see if we get the original */
+
+ bi_exp = bi_str_import(ctx, expnt);
+ bi_res = bi_mod_power(ctx, bi_data, bi_exp);
+ bi_free_mod(ctx, 0);
+
+ bi_export(ctx, bi_res, compare, 64);
+ if (memcmp(plaintext, compare, 64) != 0)
+ goto end;
+
+ printf("All BIGINT tests passed\n");
+ res = 0;
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * RSA tests
+ *
+ * Use the results from openssl to verify PKCS1 etc
+ **************************************************************************/
+static int RSA_test(void)
+{
+ int res = 1;
+ const char *plaintext = /* 128 byte hex number */
+ "1aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee2"
+ "1aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeee2\012";
+ uint8_t enc_data[128], dec_data[128];
+ RSA_CTX *rsa_ctx = NULL;
+ BI_CTX *bi_ctx;
+ bigint *plaintext_bi;
+ bigint *enc_data_bi, *dec_data_bi;
+ uint8_t enc_data2[128], dec_data2[128];
+ int size;
+ int len;
+ uint8_t *buf;
+
+ /* extract the private key elements */
+ len = get_file("../ssl/test/axTLS.key_1024", &buf);
+ if (asn1_get_private_key(buf, len, &rsa_ctx) < 0)
+ {
+ goto end;
+ }
+
+ free(buf);
+ bi_ctx = rsa_ctx->bi_ctx;
+ plaintext_bi = bi_import(bi_ctx,
+ (const uint8_t *)plaintext, strlen(plaintext));
+
+ /* basic rsa encrypt */
+ enc_data_bi = RSA_public(rsa_ctx, plaintext_bi);
+ bi_export(bi_ctx, bi_copy(enc_data_bi), enc_data, sizeof(enc_data));
+
+ /* basic rsa decrypt */
+ dec_data_bi = RSA_private(rsa_ctx, enc_data_bi);
+ bi_export(bi_ctx, dec_data_bi, dec_data, sizeof(dec_data));
+
+ if (memcmp(dec_data, plaintext, strlen(plaintext)))
+ {
+ printf("Error: DECRYPT #1 failed\n");
+ goto end;
+ }
+
+ RSA_encrypt(rsa_ctx, (const uint8_t *)"abc", 3, enc_data2, 0);
+ size = RSA_decrypt(rsa_ctx, enc_data2, dec_data2, 1);
+ if (memcmp("abc", dec_data2, 3))
+ {
+ printf("Error: ENCRYPT/DECRYPT #2 failed\n");
+ goto end;
+ }
+
+ RSA_free(rsa_ctx);
+ res = 0;
+ printf("All RSA tests passed\n");
+
+end:
+ return res;
+}
+
+/**************************************************************************
+ * Cert Testing
+ *
+ **************************************************************************/
+static int cert_tests(void)
+{
+ int res = -1, len;
+ X509_CTX *x509_ctx;
+ SSL_CTX *ssl_ctx;
+ uint8_t *buf;
+
+ /* check a bunch of 3rd party certificates */
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/microsoft.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #1\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/thawte.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #2\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/deutsche_telecom.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #3\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/equifax.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #4\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/gnutls.cer", &buf);
+ if ((res = add_cert(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #5\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/socgen.cer", &buf);
+ if ((res = add_cert(ssl_ctx, buf, len)) < 0)
+ {
+ printf("Cert #6\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ len = get_file("../ssl/test/verisign.x509_ca", &buf);
+ if ((res = add_cert_auth(ssl_ctx, buf, len)) <0)
+ {
+ printf("Cert #7\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ free(buf);
+
+ if (get_file("../ssl/test/verisign.x509_my_cert", &buf) < 0 ||
+ x509_new(buf, &len, &x509_ctx))
+ {
+ printf("Cert #8\n");
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ x509_free(x509_ctx);
+ free(buf);
+
+ ssl_ctx = ssl_ctx_new(0, 0);
+ if ((res = ssl_obj_load(ssl_ctx,
+ SSL_OBJ_X509_CERT, "../ssl/test/ms_iis.cer", NULL)) != SSL_OK)
+ {
+ ssl_display_error(res);
+ goto bad_cert;
+ }
+
+ ssl_ctx_free(ssl_ctx);
+ res = 0; /* all ok */
+ printf("All Certificate tests passed\n");
+
+bad_cert:
+ if (res)
+ printf("Error: A certificate test failed\n");
+ return res;
+}
+
+/**
+ * init a server socket.
+ */
+static int server_socket_init(int *port)
+{
+ struct sockaddr_in serv_addr;
+ int server_fd;
+ char yes = 1;
+
+ /* Create socket for incoming connections */
+ if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ return -1;
+ }
+
+ setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
+
+go_again:
+ /* Construct local address structure */
+ memset(&serv_addr, 0, sizeof(serv_addr)); /* Zero out structure */
+ serv_addr.sin_family = AF_INET; /* Internet address family */
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
+ serv_addr.sin_port = htons(*port); /* Local port */
+
+ /* Bind to the local address */
+ if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
+ {
+ (*port)++;
+ goto go_again;
+ }
+ /* Mark the socket so it will listen for incoming connections */
+ if (listen(server_fd, 3000) < 0)
+ {
+ return -1;
+ }
+
+ return server_fd;
+}
+
+/**
+ * init a client socket.
+ */
+static int client_socket_init(uint16_t port)
+{
+ struct sockaddr_in address;
+ int client_fd;
+
+ address.sin_family = AF_INET;
+ address.sin_port = htons(port);
+ address.sin_addr.s_addr = inet_addr("127.0.0.1");
+ client_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (connect(client_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
+ {
+ perror("socket");
+ SOCKET_CLOSE(client_fd);
+ client_fd = -1;
+ }
+
+ return client_fd;
+}
+
+/**************************************************************************
+ * SSL Server Testing
+ *
+ **************************************************************************/
+typedef struct
+{
+ /* not used as yet */
+ int dummy;
+} SVR_CTX;
+
+typedef struct
+{
+ const char *testname;
+ const char *openssl_option;
+} client_t;
+
+static void do_client(client_t *clnt)
+{
+ char openssl_buf[2048];
+
+ /* make sure the main thread goes first */
+ sleep(0);
+
+ /* show the session ids in the reconnect test */
+ if (strcmp(clnt->testname, "Session Reuse") == 0)
+ {
+ sprintf(openssl_buf, "echo \"hello client\" | openssl s_client "
+ "-connect localhost:%d %s 2>&1 | grep \"Session-ID:\"",
+ g_port, clnt->openssl_option);
+ }
+ else
+ {
+ sprintf(openssl_buf, "echo \"hello client\" | openssl s_client "
+#ifdef WIN32
+ "-connect localhost:%d -quiet %s",
+#else
+ "-connect localhost:%d -quiet %s > /dev/null 2>&1",
+#endif
+ g_port, clnt->openssl_option);
+ }
+
+ system(openssl_buf);
+}
+
+static int SSL_server_test(
+ const char *testname,
+ const char *openssl_option,
+ const char *device_cert,
+ const char *product_cert,
+ const char *private_key,
+ const char *ca_cert,
+ const char *password,
+ int axolotls_option)
+{
+ int server_fd, ret = 0;
+ SSL_CTX *ssl_ctx = NULL;
+ struct sockaddr_in client_addr;
+ uint8_t *read_buf;
+ socklen_t clnt_len = sizeof(client_addr);
+ client_t client_data;
+#ifndef WIN32
+ pthread_t thread;
+#endif
+ g_port++;
+
+ client_data.testname = testname;
+ client_data.openssl_option = openssl_option;
+
+ if ((server_fd = server_socket_init(&g_port)) < 0)
+ goto error;
+
+ if (private_key)
+ {
+ axolotls_option |= SSL_NO_DEFAULT_KEY;
+ }
+
+ if ((ssl_ctx = ssl_ctx_new(axolotls_option, SSL_DEFAULT_SVR_SESS)) == NULL)
+ {
+ ret = SSL_ERROR_INVALID_KEY;
+ goto error;
+ }
+
+ if (private_key)
+ {
+ int obj_type = SSL_OBJ_RSA_KEY;
+
+ if (strstr(private_key, ".p8"))
+ obj_type = SSL_OBJ_PKCS8;
+ else if (strstr(private_key, ".p12"))
+ obj_type = SSL_OBJ_PKCS12;
+
+ if (ssl_obj_load(ssl_ctx, obj_type, private_key, password))
+ {
+ ret = SSL_ERROR_INVALID_KEY;
+ goto error;
+ }
+ }
+
+ if (device_cert) /* test chaining */
+ {
+ if ((ret = ssl_obj_load(ssl_ctx,
+ SSL_OBJ_X509_CERT, device_cert, NULL)) != SSL_OK)
+ goto error;
+ }
+
+ if (product_cert) /* test chaining */
+ {
+ if ((ret = ssl_obj_load(ssl_ctx,
+ SSL_OBJ_X509_CERT, product_cert, NULL)) != SSL_OK)
+ goto error;
+ }
+
+ if (ca_cert) /* test adding certificate authorities */
+ {
+ if ((ret = ssl_obj_load(ssl_ctx,
+ SSL_OBJ_X509_CACERT, ca_cert, NULL)) != SSL_OK)
+ goto error;
+ }
+
+#ifndef WIN32
+ pthread_create(&thread, NULL,
+ (void *(*)(void *))do_client, (void *)&client_data);
+ pthread_detach(thread);
+#else
+ CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_client,
+ (LPVOID)&client_data, 0, NULL);
+#endif
+
+ for (;;)
+ {
+ int client_fd, size = 0;
+ SSL *ssl;
+
+ /* Wait for a client to connect */
+ if ((client_fd = accept(server_fd,
+ (struct sockaddr *)&client_addr, &clnt_len)) < 0)
+ {
+ ret = SSL_ERROR_SOCK_SETUP_FAILURE;
+ goto error;
+ }
+
+ /* we are ready to go */
+ ssl = ssl_server_new(ssl_ctx, client_fd);
+ while ((size = ssl_read(ssl, &read_buf)) == SSL_OK);
+ SOCKET_CLOSE(client_fd);
+
+ if (size < SSL_OK) /* got some alert or something nasty */
+ {
+ ret = size;
+
+ if (ret == SSL_ERROR_CONN_LOST)
+ {
+ ret = SSL_OK;
+ continue;
+ }
+
+ break; /* we've got a problem */
+ }
+ else /* looks more promising */
+ {
+ if (strstr("hello client", (char *)read_buf) == NULL)
+ {
+ printf("SSL server test \"%s\" passed\n", testname);
+ TTY_FLUSH();
+ ret = 0;
+ break;
+ }
+ }
+
+ ssl_free(ssl);
+ }
+
+ SOCKET_CLOSE(server_fd);
+
+error:
+ ssl_ctx_free(ssl_ctx);
+ return ret;
+}
+
+int SSL_server_tests(void)
+{
+ int ret = -1;
+ struct stat stat_buf;
+ SVR_CTX svr_test_ctx;
+ memset(&svr_test_ctx, 0, sizeof(SVR_CTX));
+
+ printf("### starting server tests\n"); TTY_FLUSH();
+
+ /* Go through the algorithms */
+
+ /*
+ * TLS1 client hello
+ */
+ if ((ret = SSL_server_test("TLSv1", "-cipher RC4-SHA -tls1",
+ NULL, NULL, NULL, NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES128-SHA
+ */
+ if ((ret = SSL_server_test("AES256-SHA", "-cipher AES128-SHA",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES256-SHA
+ */
+ if ((ret = SSL_server_test("AES256-SHA", "-cipher AES128-SHA",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * RC4-SHA
+ */
+ if ((ret = SSL_server_test("RC4-SHA", "-cipher RC4-SHA",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * RC4-MD5
+ */
+ if ((ret = SSL_server_test("RC4-MD5", "-cipher RC4-MD5",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * Session Reuse
+ * all the session id's should match for session resumption.
+ */
+ if ((ret = SSL_server_test("Session Reuse",
+ "-cipher RC4-SHA -reconnect",
+ DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL,
+ DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * 512 bit RSA key
+ */
+ if ((ret = SSL_server_test("512 bit key", "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_512.cer", NULL,
+ "../ssl/test/axTLS.key_512",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * 1024 bit RSA key (check certificate chaining)
+ */
+ if ((ret = SSL_server_test("1024 bit key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_device.cer",
+ "../ssl/test/axTLS.x509_512.cer",
+ "../ssl/test/axTLS.device_key",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * 2048 bit RSA key
+ */
+ if ((ret = SSL_server_test("2048 bit key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_2048.cer", NULL,
+ "../ssl/test/axTLS.key_2048",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * 4096 bit RSA key
+ */
+ if ((ret = SSL_server_test("4096 bit key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_4096.cer", NULL,
+ "../ssl/test/axTLS.key_4096",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * Client Verification
+ */
+ if ((ret = SSL_server_test("Client Verification",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_2048.pem "
+ "-key ../ssl/test/axTLS.key_2048.pem ",
+ NULL, NULL, NULL,
+ "../ssl/test/axTLS.ca_x509.cer", NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)))
+ goto cleanup;
+
+ /* this test should fail */
+ if (stat("../ssl/test/axTLS.x509_bad_before.pem", &stat_buf) >= 0)
+ {
+ if ((ret = SSL_server_test("Bad Before Cert",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_bad_before.pem "
+ "-key ../ssl/test/axTLS.key_512.pem ",
+ NULL, NULL, NULL,
+ "../ssl/test/axTLS.ca_x509.cer", NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) !=
+ SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID))
+ goto cleanup;
+
+ printf("SSL server test \"%s\" passed\n", "Bad Before Cert");
+ TTY_FLUSH();
+ ret = 0; /* is ok */
+ }
+
+ /* this test should fail */
+ if ((ret = SSL_server_test("Bad After Cert",
+ "-cipher RC4-SHA -tls1 "
+ "-cert ../ssl/test/axTLS.x509_bad_after.pem "
+ "-key ../ssl/test/axTLS.key_512.pem ",
+ NULL, NULL, NULL,
+ "../ssl/test/axTLS.ca_x509.cer", NULL,
+ DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) !=
+ SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED))
+ goto cleanup;
+
+ printf("SSL server test \"%s\" passed\n", "Bad After Cert");
+ TTY_FLUSH();
+
+ /*
+ * Key in PEM format
+ */
+ if ((ret = SSL_server_test("Key in PEM format",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_512.cer", NULL,
+ "../ssl/test/axTLS.key_512.pem", NULL,
+ NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * Cert in PEM format
+ */
+ if ((ret = SSL_server_test("Cert in PEM format",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_512.pem", NULL,
+ "../ssl/test/axTLS.key_512.pem", NULL,
+ NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * Cert chain in PEM format
+ */
+ if ((ret = SSL_server_test("Cert chain in PEM format",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_device.pem",
+ NULL, "../ssl/test/axTLS.device_key.pem",
+ "../ssl/test/axTLS.ca_x509.pem", NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES128 Encrypted key
+ */
+ if ((ret = SSL_server_test("AES128 encrypted key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_aes128.pem", NULL,
+ "../ssl/test/axTLS.key_aes128.pem",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES256 Encrypted key
+ */
+ if ((ret = SSL_server_test("AES256 encrypted key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_aes256.pem", NULL,
+ "../ssl/test/axTLS.key_aes256.pem",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * AES128 Encrypted invalid key
+ */
+ if ((ret = SSL_server_test("AES128 encrypted invalid key",
+ "-cipher RC4-SHA",
+ "../ssl/test/axTLS.x509_aes128.pem", NULL,
+ "../ssl/test/axTLS.key_aes128.pem",
+ NULL, "xyz", DEFAULT_SVR_OPTION)) != SSL_ERROR_INVALID_KEY)
+ goto cleanup;
+
+ printf("SSL server test \"%s\" passed\n", "AES128 encrypted invalid key");
+ TTY_FLUSH();
+
+ /*
+ * PKCS#8 key (encrypted)
+ */
+ if ((ret = SSL_server_test("pkcs#8 encrypted", "-cipher RC4-SHA",
+ DEFAULT_CERT, NULL, "../ssl/test/axTLS.encrypted.p8",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * PKCS#8 key (unencrypted)
+ */
+ if ((ret = SSL_server_test("pkcs#8 unencrypted", "-cipher RC4-SHA",
+ DEFAULT_CERT, NULL, "../ssl/test/axTLS.unencrypted.p8",
+ NULL, NULL, DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ * PKCS#12 key/certificate
+ */
+ if ((ret = SSL_server_test("pkcs#12 with CA", "-cipher RC4-SHA",
+ NULL, NULL, "../ssl/test/axTLS.withCA.p12",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ if ((ret = SSL_server_test("pkcs#12 no CA", "-cipher RC4-SHA",
+ DEFAULT_CERT, NULL, "../ssl/test/axTLS.withoutCA.p12",
+ NULL, "abcd", DEFAULT_SVR_OPTION)))
+ goto cleanup;
+
+ /*
+ *
+ */
+
+ ret = 0;
+
+cleanup:
+ if (ret)
+ {
+ printf("Error: A server test failed\n");
+ ssl_display_error(ret);
+ exit(1);
+ }
+ else
+ {
+ printf("All server tests passed\n"); TTY_FLUSH();
+ }
+
+ return ret;
+}
+
+/**************************************************************************
+ * SSL Client Testing
+ *
+ **************************************************************************/
+typedef struct
+{
+ uint8_t session_id[SSL_SESSION_ID_SIZE];
+#ifndef WIN32
+ pthread_t server_thread;
+#endif
+ int start_server;
+ int stop_server;
+ int do_reneg;
+} CLNT_SESSION_RESUME_CTX;
+
+typedef struct
+{
+ const char *testname;
+ const char *openssl_option;
+} server_t;
+
+static void do_server(server_t *svr)
+{
+ char openssl_buf[2048];
+#ifndef WIN32
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#endif
+ sprintf(openssl_buf, "openssl s_server -tls1 "
+ "-accept %d -quiet %s ", g_port, svr->openssl_option);
+ system(openssl_buf);
+}
+
+static int SSL_client_test(
+ const char *test,
+ SSL_CTX **ssl_ctx,
+ const char *openssl_option,
+ CLNT_SESSION_RESUME_CTX *sess_resume,
+ uint32_t client_options,
+ const char *private_key,
+ const char *password,
+ const char *cert)
+{
+ server_t server_data;
+ SSL *ssl = NULL;
+ int client_fd = -1;
+ uint8_t *session_id = NULL;
+ int ret = 1;
+#ifndef WIN32
+ pthread_t thread;
+#endif
+
+ if (sess_resume == NULL || sess_resume->start_server)
+ {
+ g_port++;
+ server_data.openssl_option = openssl_option;
+
+#ifndef WIN32
+ pthread_create(&thread, NULL,
+ (void *(*)(void *))do_server, (void *)&server_data);
+ pthread_detach(thread);
+#else
+ CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_server,
+ (LPVOID)&server_data, 0, NULL);
+#endif
+ }
+
+ usleep(200000); /* allow server to start */
+
+ if (*ssl_ctx == NULL)
+ {
+ if (private_key)
+ {
+ client_options |= SSL_NO_DEFAULT_KEY;
+ }
+
+ if ((*ssl_ctx = ssl_ctx_new(
+ client_options, SSL_DEFAULT_CLNT_SESS)) == NULL)
+ {
+ ret = SSL_ERROR_INVALID_KEY;
+ goto client_test_exit;
+ }
+
+ if (private_key)
+ {
+ int obj_type = SSL_OBJ_RSA_KEY;
+
+ if (strstr(private_key, ".p8"))
+ obj_type = SSL_OBJ_PKCS8;
+ else if (strstr(private_key, ".p12"))
+ obj_type = SSL_OBJ_PKCS12;
+
+ if (ssl_obj_load(*ssl_ctx, obj_type, private_key, password))
+ {
+ ret = SSL_ERROR_INVALID_KEY;
+ goto client_test_exit;
+ }
+ }
+
+ if (cert)
+ {
+ if ((ret = ssl_obj_load(*ssl_ctx,
+ SSL_OBJ_X509_CERT, cert, NULL)) != SSL_OK)
+ {
+ printf("could not add cert %s (%d)\n", cert, ret);
+ TTY_FLUSH();
+ goto client_test_exit;
+ }
+ }
+
+ if (ssl_obj_load(*ssl_ctx, SSL_OBJ_X509_CACERT,
+ "../ssl/test/axTLS.ca_x509.cer", NULL))
+ {
+ printf("could not add cert auth\n"); TTY_FLUSH();
+ goto client_test_exit;
+ }
+ }
+
+ if (sess_resume && !sess_resume->start_server)
+ {
+ session_id = sess_resume->session_id;
+ }
+
+ if ((client_fd = client_socket_init(g_port)) < 0)
+ {
+ printf("could not start socket on %d\n", g_port); TTY_FLUSH();
+ goto client_test_exit;
+ }
+
+ ssl = ssl_client_new(*ssl_ctx, client_fd, session_id, sizeof(session_id));
+
+ /* check the return status */
+ if ((ret = ssl_handshake_status(ssl)))
+ goto client_test_exit;
+
+ /* renegotiate client */
+ if (sess_resume && sess_resume->do_reneg)
+ {
+ if (ssl_renegotiate(ssl) < 0)
+ goto client_test_exit;
+ }
+
+ if (sess_resume)
+ {
+ memcpy(sess_resume->session_id,
+ ssl_get_session_id(ssl), SSL_SESSION_ID_SIZE);
+ }
+
+ if (IS_SET_SSL_FLAG(SSL_SERVER_VERIFY_LATER) &&
+ (ret = ssl_verify_cert(ssl)))
+ {
+ goto client_test_exit;
+ }
+
+ ssl_write(ssl, (uint8_t *)"hello world\n", 13);
+ if (sess_resume)
+ {
+ const uint8_t *sess_id = ssl_get_session_id(ssl);
+ int i;
+
+ printf(" Session-ID: ");
+ for (i = 0; i < SSL_SESSION_ID_SIZE; i++)
+ {
+ printf("%02X", sess_id[i]);
+ }
+ printf("\n");
+ TTY_FLUSH();
+ }
+
+ ret = 0;
+
+client_test_exit:
+ ssl_free(ssl);
+ SOCKET_CLOSE(client_fd);
+ usleep(200000); /* allow openssl to say something */
+
+ if (sess_resume)
+ {
+ if (sess_resume->stop_server)
+ {
+ ssl_ctx_free(*ssl_ctx);
+ *ssl_ctx = NULL;
+#ifndef WIN32
+ pthread_cancel(sess_resume->server_thread);
+#endif
+ }
+ else if (sess_resume->start_server)
+ {
+#ifndef WIN32
+ sess_resume->server_thread = thread;
+#endif
+ }
+ }
+ else
+ {
+ ssl_ctx_free(*ssl_ctx);
+ *ssl_ctx = NULL;
+#ifndef WIN32
+ pthread_cancel(thread);
+#endif
+ }
+
+ if (ret == 0)
+ {
+ printf("SSL client test \"%s\" passed\n", test);
+ TTY_FLUSH();
+ }
+
+ return ret;
+}
+
+int SSL_client_tests(void)
+{
+ int ret = -1;
+ SSL_CTX *ssl_ctx = NULL;
+ CLNT_SESSION_RESUME_CTX sess_resume;
+ memset(&sess_resume, 0, sizeof(CLNT_SESSION_RESUME_CTX));
+
+ sess_resume.start_server = 1;
+ printf("### starting client tests\n");
+
+ if ((ret = SSL_client_test("512 bit key",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_512.pem "
+ "-key ../ssl/test/axTLS.key_512.pem", &sess_resume,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ /* all the session id's should match for session resumption */
+ sess_resume.start_server = 0;
+ if ((ret = SSL_client_test("Client session resumption #1",
+ &ssl_ctx, NULL, &sess_resume,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ sess_resume.do_reneg = 1;
+ if ((ret = SSL_client_test("Client renegotiation",
+ &ssl_ctx, NULL, &sess_resume,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+ sess_resume.do_reneg = 0;
+
+ sess_resume.stop_server = 1;
+ if ((ret = SSL_client_test("Client session resumption #2",
+ &ssl_ctx, NULL, &sess_resume,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ if ((ret = SSL_client_test("1024 bit key",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_1024.pem "
+ "-key ../ssl/test/axTLS.key_1024.pem", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ if ((ret = SSL_client_test("2048 bit key",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_2048.pem "
+ "-key ../ssl/test/axTLS.key_2048.pem", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ if ((ret = SSL_client_test("4096 bit key",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_4096.pem "
+ "-key ../ssl/test/axTLS.key_4096.pem", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ if ((ret = SSL_client_test("Server cert chaining",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_device.pem "
+ "-key ../ssl/test/axTLS.device_key.pem "
+ "-CAfile ../ssl/test/axTLS.x509_512.pem ", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)))
+ goto cleanup;
+
+ /* Check the server can verify the client */
+ if ((ret = SSL_client_test("Client peer authentication",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_2048.pem "
+ "-key ../ssl/test/axTLS.key_2048.pem "
+ "-CAfile ../ssl/test/axTLS.ca_x509.pem "
+ "-verify 1 ", NULL, DEFAULT_CLNT_OPTION,
+ "../ssl/test/axTLS.key_1024", NULL,
+ "../ssl/test/axTLS.x509_1024.cer")))
+ goto cleanup;
+
+ /* Should get an "ERROR" from openssl (as the handshake fails as soon as
+ * the certificate verification fails) */
+ if ((ret = SSL_client_test("Error: Expired cert (verify now)",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_bad_after.pem "
+ "-key ../ssl/test/axTLS.key_512.pem", NULL,
+ DEFAULT_CLNT_OPTION, NULL, NULL, NULL)) !=
+ SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED))
+ {
+ printf("*** Error: %d\n", ret);
+ goto cleanup;
+ }
+
+ printf("SSL client test \"Expired cert (verify now)\" passed\n");
+
+ /* There is no "ERROR" from openssl */
+ if ((ret = SSL_client_test("Error: Expired cert (verify later)",
+ &ssl_ctx,
+ "-cert ../ssl/test/axTLS.x509_bad_after.pem "
+ "-key ../ssl/test/axTLS.key_512.pem", NULL,
+ DEFAULT_CLNT_OPTION|SSL_SERVER_VERIFY_LATER, NULL,
+ NULL, NULL)) != SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED))
+ {
+ printf("*** Error: %d\n", ret);
+ goto cleanup;
+ }
+
+ printf("SSL client test \"Expired cert (verify later)\" passed\n");
+ ret = 0;
+
+cleanup:
+ if (ret)
+ {
+ ssl_display_error(ret);
+ printf("Error: A client test failed\n");
+ exit(1);
+ }
+ else
+ {
+ printf("All client tests passed\n"); TTY_FLUSH();
+ }
+
+ return ret;
+}
+
+/**************************************************************************
+ * SSL Basic Testing (test a big packet handshake)
+ *
+ **************************************************************************/
+static uint8_t basic_buf[256*1024];
+
+static void do_basic(void)
+{
+ int client_fd;
+ SSL *ssl_clnt;
+ SSL_CTX *ssl_clnt_ctx = ssl_ctx_new(
+ DEFAULT_CLNT_OPTION, SSL_DEFAULT_CLNT_SESS);
+ usleep(200000); /* allow server to start */
+
+ if ((client_fd = client_socket_init(g_port)) < 0)
+ goto error;
+
+ if (ssl_obj_load(ssl_clnt_ctx, SSL_OBJ_X509_CACERT,
+ "../ssl/test/axTLS.ca_x509.cer", NULL))
+ goto error;
+
+ ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0);
+
+ /* check the return status */
+ if (ssl_handshake_status(ssl_clnt) < 0)
+ {
+ printf("YA YA\n");
+ ssl_display_error(ssl_handshake_status(ssl_clnt));
+ goto error;
+ }
+
+ ssl_write(ssl_clnt, basic_buf, sizeof(basic_buf));
+ ssl_free(ssl_clnt);
+
+error:
+ ssl_ctx_free(ssl_clnt_ctx);
+ SOCKET_CLOSE(client_fd);
+
+ /* exit this thread */
+}
+
+static int SSL_basic_test(void)
+{
+ int server_fd, client_fd, ret = 0, size = 0, offset = 0;
+ SSL_CTX *ssl_svr_ctx = NULL;
+ struct sockaddr_in client_addr;
+ uint8_t *read_buf;
+ socklen_t clnt_len = sizeof(client_addr);
+ SSL *ssl_svr;
+#ifndef WIN32
+ pthread_t thread;
+#endif
+ memset(basic_buf, 0xA5, sizeof(basic_buf)/2);
+ memset(&basic_buf[sizeof(basic_buf)/2], 0x5A, sizeof(basic_buf)/2);
+
+ if ((server_fd = server_socket_init(&g_port)) < 0)
+ goto error;
+
+ ssl_svr_ctx = ssl_ctx_new(DEFAULT_SVR_OPTION, SSL_DEFAULT_SVR_SESS);
+
+#ifndef WIN32
+ pthread_create(&thread, NULL,
+ (void *(*)(void *))do_basic, NULL);
+ pthread_detach(thread);
+#else
+ CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_basic, NULL, 0, NULL);
+#endif
+
+ /* Wait for a client to connect */
+ if ((client_fd = accept(server_fd,
+ (struct sockaddr *) &client_addr, &clnt_len)) < 0)
+ {
+ ret = SSL_ERROR_SOCK_SETUP_FAILURE;
+ goto error;
+ }
+
+ /* we are ready to go */
+ ssl_svr = ssl_server_new(ssl_svr_ctx, client_fd);
+
+ do
+ {
+ while ((size = ssl_read(ssl_svr, &read_buf)) == SSL_OK);
+
+ if (size < SSL_OK) /* got some alert or something nasty */
+ {
+ printf("Server ");
+ ssl_display_error(size);
+ ret = size;
+ break;
+ }
+ else /* looks more promising */
+ {
+ if (memcmp(read_buf, &basic_buf[offset], size) != 0)
+ {
+ ret = SSL_NOT_OK;
+ break;
+ }
+ }
+
+ offset += size;
+ } while (offset < sizeof(basic_buf));
+
+ printf(ret == SSL_OK && offset == sizeof(basic_buf) ?
+ "SSL basic test passed\n" :
+ "SSL basic test failed\n");
+ TTY_FLUSH();
+
+ ssl_free(ssl_svr);
+ SOCKET_CLOSE(server_fd);
+ SOCKET_CLOSE(client_fd);
+
+error:
+ ssl_ctx_free(ssl_svr_ctx);
+ return ret;
+}
+
+#if !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING)
+/**************************************************************************
+ * Multi-Threading Tests
+ *
+ **************************************************************************/
+#define NUM_THREADS 100
+
+typedef struct
+{
+ SSL_CTX *ssl_clnt_ctx;
+ int port;
+ int thread_id;
+} multi_t;
+
+void do_multi_clnt(multi_t *multi_data)
+{
+ int res = 1, client_fd, i;
+ SSL *ssl = NULL;
+ char tmp[5];
+
+ if ((client_fd = client_socket_init(multi_data->port)) < 0)
+ goto client_test_exit;
+
+ sleep(1);
+ ssl = ssl_client_new(multi_data->ssl_clnt_ctx, client_fd, NULL, 0);
+
+ if ((res = ssl_handshake_status(ssl)))
+ {
+ printf("Client ");
+ ssl_display_error(res);
+ goto client_test_exit;
+ }
+
+ sprintf(tmp, "%d\n", multi_data->thread_id);
+ for (i = 0; i < 10; i++)
+ ssl_write(ssl, (uint8_t *)tmp, strlen(tmp)+1);
+
+client_test_exit:
+ ssl_free(ssl);
+ SOCKET_CLOSE(client_fd);
+ free(multi_data);
+}
+
+void do_multi_svr(SSL *ssl)
+{
+ uint8_t *read_buf;
+ int *res_ptr = malloc(sizeof(int));
+ int res;
+
+ for (;;)
+ {
+ res = ssl_read(ssl, &read_buf);
+
+ /* kill the client */
+ if (res != SSL_OK)
+ {
+ if (res == SSL_ERROR_CONN_LOST)
+ {
+ SOCKET_CLOSE(ssl->client_fd);
+ ssl_free(ssl);
+ break;
+ }
+ else if (res > 0)
+ {
+ /* do nothing */
+ }
+ else /* some problem */
+ {
+ printf("Server ");
+ ssl_display_error(res);
+ goto error;
+ }
+ }
+ }
+
+ res = SSL_OK;
+error:
+ *res_ptr = res;
+ pthread_exit(res_ptr);
+}
+
+int multi_thread_test(void)
+{
+ int server_fd = -1;
+ SSL_CTX *ssl_server_ctx;
+ SSL_CTX *ssl_clnt_ctx;
+ pthread_t clnt_threads[NUM_THREADS];
+ pthread_t svr_threads[NUM_THREADS];
+ int i, res = 0;
+ struct sockaddr_in client_addr;
+ socklen_t clnt_len = sizeof(client_addr);
+
+ printf("Do multi-threading test (takes a minute)\n");
+
+ ssl_server_ctx = ssl_ctx_new(DEFAULT_SVR_OPTION, SSL_DEFAULT_SVR_SESS);
+ ssl_clnt_ctx = ssl_ctx_new(DEFAULT_CLNT_OPTION, SSL_DEFAULT_CLNT_SESS);
+
+ if (ssl_obj_load(ssl_clnt_ctx, SSL_OBJ_X509_CACERT,
+ "../ssl/test/axTLS.ca_x509.cer", NULL))
+ goto error;
+
+ if ((server_fd = server_socket_init(&g_port)) < 0)
+ goto error;
+
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ multi_t *multi_data = (multi_t *)malloc(sizeof(multi_t));
+ multi_data->ssl_clnt_ctx = ssl_clnt_ctx;
+ multi_data->port = g_port;
+ multi_data->thread_id = i+1;
+ pthread_create(&clnt_threads[i], NULL,
+ (void *(*)(void *))do_multi_clnt, (void *)multi_data);
+ pthread_detach(clnt_threads[i]);
+ }
+
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ SSL *ssl_svr;
+ int client_fd = accept(server_fd,
+ (struct sockaddr *)&client_addr, &clnt_len);
+
+ if (client_fd < 0)
+ goto error;
+
+ ssl_svr = ssl_server_new(ssl_server_ctx, client_fd);
+
+ pthread_create(&svr_threads[i], NULL,
+ (void *(*)(void *))do_multi_svr, (void *)ssl_svr);
+ }
+
+ /* make sure we've run all of the threads */
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ void *thread_res;
+ pthread_join(svr_threads[i], &thread_res);
+
+ if (*((int *)thread_res) != 0)
+ res = 1;
+
+ free(thread_res);
+ }
+
+ if (res)
+ goto error;
+
+ printf("Multi-thread test passed (%d)\n", NUM_THREADS);
+error:
+ ssl_ctx_free(ssl_server_ctx);
+ ssl_ctx_free(ssl_clnt_ctx);
+ SOCKET_CLOSE(server_fd);
+ return res;
+}
+#endif /* !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING) */
+
+/**************************************************************************
+ * Header issue
+ *
+ **************************************************************************/
+static void do_header_issue(void)
+{
+ char axtls_buf[2048];
+#ifndef WIN32
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#endif
+ sprintf(axtls_buf, "./axssl s_client -connect localhost:%d", g_port);
+ system(axtls_buf);
+}
+
+static int header_issue(void)
+{
+ FILE *f = fopen("../ssl/test/header_issue.dat", "r");
+ int server_fd = -1, client_fd = -1, ret = 1;
+ uint8_t buf[2048];
+ int size = 0;
+ struct sockaddr_in client_addr;
+ socklen_t clnt_len = sizeof(client_addr);
+#ifndef WIN32
+ pthread_t thread;
+#endif
+
+ if (f == NULL || (server_fd = server_socket_init(&g_port)) < 0)
+ goto error;
+
+#ifndef WIN32
+ pthread_create(&thread, NULL,
+ (void *(*)(void *))do_header_issue, NULL);
+ pthread_detach(thread);
+#else
+ CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_header_issue,
+ NULL, 0, NULL);
+#endif
+ if ((client_fd = accept(server_fd,
+ (struct sockaddr *) &client_addr, &clnt_len)) < 0)
+ {
+ ret = SSL_ERROR_SOCK_SETUP_FAILURE;
+ goto error;
+ }
+
+ size = fread(buf, 1, sizeof(buf), f);
+ SOCKET_WRITE(client_fd, buf, size);
+ usleep(200000);
+
+ ret = 0;
+error:
+ fclose(f);
+ SOCKET_CLOSE(client_fd);
+ SOCKET_CLOSE(server_fd);
+ TTY_FLUSH();
+ system("killall axssl");
+ return ret;
+}
+
+/**************************************************************************
+ * main()
+ *
+ **************************************************************************/
+int main(int argc, char *argv[])
+{
+ int ret = 1;
+ BI_CTX *bi_ctx;
+ int fd;
+
+#ifdef WIN32
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD(2, 2);
+ WSAStartup(wVersionRequested, &wsaData);
+ fd = _open("test_result.txt", O_WRONLY|O_TEMPORARY|O_CREAT, _S_IWRITE);
+ dup2(fd, 2); /* write stderr to this file */
+#else
+ fd = open("/dev/null", O_WRONLY); /* write stderr to /dev/null */
+ signal(SIGPIPE, SIG_IGN); /* ignore pipe errors */
+ dup2(fd, 2);
+#endif
+
+ /* can't do testing in this mode */
+#if defined CONFIG_SSL_GENERATE_X509_CERT
+ printf("Error: Must compile with default key/certificates\n");
+ exit(1);
+#endif
+
+ bi_ctx = bi_initialize();
+
+ if (AES_test(bi_ctx))
+ {
+ printf("AES tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (RC4_test(bi_ctx))
+ {
+ printf("RC4 tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (MD5_test(bi_ctx))
+ {
+ printf("MD5 tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (SHA1_test(bi_ctx))
+ {
+ printf("SHA1 tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (HMAC_test(bi_ctx))
+ {
+ printf("HMAC tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (BIGINT_test(bi_ctx))
+ {
+ printf("BigInt tests failed!\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ bi_terminate(bi_ctx);
+
+ if (RSA_test())
+ {
+ printf("RSA tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+ if (cert_tests())
+ {
+ printf("CERT tests failed\n");
+ goto cleanup;
+ }
+ TTY_FLUSH();
+
+#if !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING)
+ if (multi_thread_test())
+ goto cleanup;
+#endif
+
+ if (SSL_basic_test())
+ goto cleanup;
+
+ system("sh ../ssl/test/killopenssl.sh");
+
+ if (SSL_client_tests())
+ goto cleanup;
+
+ system("sh ../ssl/test/killopenssl.sh");
+
+ if (SSL_server_tests())
+ goto cleanup;
+
+ system("sh ../ssl/test/killopenssl.sh");
+
+ if (header_issue())
+ {
+ printf("Header tests failed\n"); TTY_FLUSH();
+ goto cleanup;
+ }
+
+ ret = 0; /* all ok */
+ printf("**** ALL TESTS PASSED ****\n"); TTY_FLUSH();
+cleanup:
+
+ if (ret)
+ printf("Error: Some tests failed!\n");
+
+ close(fd);
+ return ret;
+}
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/test_axssl.sh b/libs/luci-lib-nixio/axTLS/ssl/test/test_axssl.sh
new file mode 100755
index 0000000000..acf11a630c
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/test_axssl.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+#
+# Test the various axssl bindings. To run it, got to the _install directory
+# and run this script from there.
+#
+
+if grep "CONFIG_PLATFORM_WIN32=y" "../config/.config" > /dev/null; then
+ JAVA_EXE="$JAVA_HOME/bin/java.exe"
+ PERL_BIN="/cygdrive/c/Perl/bin/perl"
+ KILL_AXSSL="kill %1"
+ KILL_CSHARP="kill %1"
+ KILL_PERL="kill %1"
+ KILL_JAVA="kill %1"
+ KILL_LUA="kill %1"
+else
+ if grep "CONFIG_PLATFORM_CYGWIN=y" "../config/.config" > /dev/null; then
+ # no .net or java on cygwin
+ PERL_BIN=/usr/bin/perl
+ KILL_AXSSL="killall axssl"
+ KILL_PERL="killall /usr/bin/perl"
+ KILL_LUA="killall /usr/local/bin/lua"
+ else # Linux
+ JAVA_EXE=/usr/java/default/bin/java
+ PERL_BIN=/usr/bin/perl
+ KILL_AXSSL="killall axssl"
+ KILL_CSHARP="killall mono"
+ KILL_PERL="killall /usr/bin/perl"
+ RUN_CSHARP="mono"
+ KILL_JAVA="killall $JAVA_EXE"
+ KILL_LUA="killall /usr/local/bin/lua"
+ fi
+fi
+
+BASE=..
+SERVER_ARGS="s_server -accept 15001 -verify -CAfile $BASE/ssl/test/axTLS.ca_x509.cer"
+CLIENT_ARGS="s_client -reconnect -connect localhost:15001 -verify -CAfile $BASE/ssl/test/axTLS.ca_x509.cer -key $BASE/ssl/test/axTLS.key_1024 -cert $BASE/ssl/test/axTLS.x509_1024.cer"
+
+# check pem arguments
+SERVER_PEM_ARGS="s_server -accept 15001 -pass abcd -key $BASE/ssl/test/axTLS.key_aes128.pem -cert $BASE/ssl/test/axTLS.x509_aes128.pem"
+CLIENT_PEM_ARGS="s_client -connect localhost:15001 -CAfile $BASE/ssl/test/axTLS.ca_x509.pem -key $BASE/ssl/test/axTLS.key_1024.pem -cert $BASE/ssl/test/axTLS.x509_1024.pem"
+
+export LD_LIBRARY_PATH=.:`perl -e 'use Config; print $Config{archlib};'`/CORE
+
+if [ -x ./axssl ]; then
+echo "############################# C SAMPLE ###########################"
+./axssl $SERVER_ARGS &
+echo "C Test passed" | ./axssl $CLIENT_ARGS
+$KILL_AXSSL
+sleep 1
+
+./axssl $SERVER_PEM_ARGS &
+echo "C Test passed" | ./axssl $CLIENT_PEM_ARGS
+$KILL_AXSSL
+sleep 1
+echo "### C tests complete"
+fi
+
+if [ -f ./axtls.jar ]; then
+echo "########################## JAVA SAMPLE ###########################"
+"$JAVA_EXE" -jar ./axtls.jar $SERVER_ARGS &
+echo "Java Test passed" | "$JAVA_EXE" -jar ./axtls.jar $CLIENT_ARGS
+$KILL_JAVA
+sleep 1
+
+"$JAVA_EXE" -jar ./axtls.jar $SERVER_PEM_ARGS &
+echo "Java Test passed" | "$JAVA_EXE" -jar ./axtls.jar $CLIENT_PEM_ARGS
+$KILL_JAVA
+sleep 1
+
+echo "### Java tests complete"
+fi
+
+if [ -x ./axssl.csharp.exe ]; then
+echo "############################ C# SAMPLE ###########################"
+$RUN_CSHARP ./axssl.csharp.exe $SERVER_ARGS &
+echo "C# Test passed" | $RUN_CSHARP ./axssl.csharp.exe $CLIENT_ARGS
+$KILL_CSHARP
+sleep 1
+
+$RUN_CSHARP ./axssl.csharp.exe $SERVER_PEM_ARGS &
+echo "C# Test passed" | $RUN_CSHARP ./axssl.csharp.exe $CLIENT_PEM_ARGS
+$KILL_CSHARP
+sleep 1
+
+echo "### C# tests complete"
+fi
+
+if [ -x ./axssl.vbnet.exe ]; then
+echo "######################## VB.NET SAMPLE ###########################"
+echo $SERVER_ARGS
+echo $CLIENT_ARGS
+./axssl.vbnet $SERVER_ARGS &
+echo "VB.NET Test passed" | ./axssl.vbnet.exe $CLIENT_ARGS
+kill %1
+sleep 1
+
+./axssl.vbnet $SERVER_PEM_ARGS &
+echo "VB.NET Test passed" | ./axssl.vbnet.exe $CLIENT_PEM_ARGS
+kill %1
+sleep 1
+echo "### VB.NET tests complete"
+fi
+
+if [ -f ./axssl.pl ]; then
+echo "########################## PERL SAMPLE ###########################"
+"$PERL_BIN" ./axssl.pl $SERVER_ARGS &
+echo "Perl Test passed" | "$PERL_BIN" ./axssl.pl $CLIENT_ARGS
+$KILL_PERL
+sleep 1
+
+"$PERL_BIN" ./axssl.pl $SERVER_PEM_ARGS &
+echo "Perl Test passed" | "$PERL_BIN" ./axssl.pl $CLIENT_PEM_ARGS
+$KILL_PERL
+sleep 1
+echo "### Perl tests complete"
+fi
+
+if [ -f ./axssl.lua ]; then
+echo "########################## LUA SAMPLE ###########################"
+./axssl.lua $SERVER_ARGS &
+echo "Lua Test passed" | ./axssl.lua $CLIENT_ARGS
+$KILL_LUA
+sleep 1
+
+./axssl.lua $SERVER_PEM_ARGS &
+echo "Lua Test passed" | ./axssl.lua $CLIENT_PEM_ARGS
+$KILL_LUA
+sleep 1
+echo "### Lua tests complete"
+fi
+
+echo "########################## ALL TESTS COMPLETE ###########################"
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/thawte.x509_ca b/libs/luci-lib-nixio/axTLS/ssl/test/thawte.x509_ca
new file mode 100644
index 0000000000..59b1059f84
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/thawte.x509_ca
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_ca b/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_ca
new file mode 100644
index 0000000000..d2ea1289d6
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_ca
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_ca.pem b/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_ca.pem
new file mode 100644
index 0000000000..d5ef5d241b
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_ca.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICmDCCAgECECCol67bggLewTagTia9h3MwDQYJKoZIhvcNAQECBQAwgYwxCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEwMC4GA1UECxMnRm9y
+IFRlc3QgUHVycG9zZXMgT25seS4gIE5vIGFzc3VyYW5jZXMuMTIwMAYDVQQDEylW
+ZXJpU2lnbiBUcmlhbCBTZWN1cmUgU2VydmVyIFRlc3QgUm9vdCBDQTAeFw0wNTAy
+MDkwMDAwMDBaFw0yNTAyMDgyMzU5NTlaMIGMMQswCQYDVQQGEwJVUzEXMBUGA1UE
+ChMOVmVyaVNpZ24sIEluYy4xMDAuBgNVBAsTJ0ZvciBUZXN0IFB1cnBvc2VzIE9u
+bHkuICBObyBhc3N1cmFuY2VzLjEyMDAGA1UEAxMpVmVyaVNpZ24gVHJpYWwgU2Vj
+dXJlIFNlcnZlciBUZXN0IFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAJ8h98U7klaZH5cEn6CSEKmGWVBsTwHIaMAAVqGqCUn7Q9C10sEOIHBznyLy
+eSDjMs5M1nC/iAA7KCASf/yHz0AdlU+1IRSijwHTF/2dYSoTTxP2GCmtL1Ga4i7+
+zDDo086V7+NiFAGJj+CYey47ue4Xa33o/4YOA9PGL87oqFe7AgMBAAEwDQYJKoZI
+hvcNAQECBQADgYEAOq447rP5EDqFEl3vhLhgTbnyaskNYwPvxk+0grnQyDA4sF/q
+gK8nFlnvLmAOF3DmfuqW6WSr4zqTYzpwmJlsn48Om/yWirL8GuWRftit2POxTfHS
+B8VmR+PZx2k24UgWUZyojDGxJtiHd3tjCdqFgTit4NK429cWOcZrh47xeOI=
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_my_cert b/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_my_cert
new file mode 100644
index 0000000000..426c9ff7f1
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_my_cert
Binary files differ
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_my_cert.pem b/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_my_cert.pem
new file mode 100644
index 0000000000..5b6c1ffedd
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/test/verisign.x509_my_cert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEQzCCA6ygAwIBAgIQR/dXCzC/x5Ta5RvL6hKEojANBgkqhkiG9w0BAQUFADCB
+jDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTAwLgYDVQQL
+EydGb3IgVGVzdCBQdXJwb3NlcyBPbmx5LiAgTm8gYXNzdXJhbmNlcy4xMjAwBgNV
+BAMTKVZlcmlTaWduIFRyaWFsIFNlY3VyZSBTZXJ2ZXIgVGVzdCBSb290IENBMB4X
+DTA2MDExNjAwMDAwMFoXDTA2MDEzMDIzNTk1OVowgbkxCzAJBgNVBAYTAkFVMQww
+CgYDVQQIEwNRbGQxETAPBgNVBAcUCEJyaXNiYW5lMRkwFwYDVQQKFBBheG9sb1RM
+UyBQcm9qZWN0MRUwEwYDVQQLFAwxMDI0IGJpdCBrZXkxOjA4BgNVBAsUMVRlcm1z
+IG9mIHVzZSBhdCB3d3cudmVyaXNpZ24uY29tL2Nwcy90ZXN0Y2EgKGMpMDUxGzAZ
+BgNVBAMUEnd3dy5heG9sb3Rscy5jby5ucjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAttzj5S7qfOZIrh9xg8bgjTOKbSIbLBuMnxAwfGRcUrQO2EQOHd6kMjXR
+hqY/cG2IG4G8AeqdV3nHlKbrbHbRa1lFgP6b0BQCE8TyxmP+tIAqn5L6/HTm+EEi
+Ad1Pxjeok6e7F6UXHxJltSGHmOhAf3C5kPq/FQ6QZeG4yD/uzPkCAwEAAaOCAXUw
+ggFxMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMEcGA1UdHwRAMD4wPKA6oDiGNmh0
+dHA6Ly9TVlJTZWN1cmUtY3JsLnZlcmlzaWduLmNvbS9TVlJUcmlhbFJvb3QyMDA1
+LmNybDBKBgNVHSAEQzBBMD8GCmCGSAGG+EUBBxUwMTAvBggrBgEFBQcCARYjaHR0
+cHM6Ly93d3cudmVyaXNpZ24uY29tL2Nwcy90ZXN0Y2EwHQYDVR0lBBYwFAYIKwYB
+BQUHAwEGCCsGAQUFBwMCMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0
+cDovL29jc3AudmVyaXNpZ24uY29tMG0GCCsGAQUFBwEMBGEwX6FdoFswWTBXMFUW
+CWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgsexkuMCUW
+I2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMA0GCSqGSIb3DQEB
+BQUAA4GBACtlCTJFENCcHCQLHJfiotqr2XR+oWu0MstNm8dG6WB+zYprrT+kOPDn
+1rMO7YLx76f67fC+lIXz720kQHk6LsZ8hPBQvIXnfIsKjng73DeFzBmTMFz6Qxjd
++E0FUCKplqrdwUkmR4kH6O4pdGE4AlXJNiUI2903yYdSRVMOuLuR
+-----END CERTIFICATE-----
diff --git a/libs/luci-lib-nixio/axTLS/ssl/tls1.c b/libs/luci-lib-nixio/axTLS/ssl/tls1.c
new file mode 100755
index 0000000000..658c2c15d4
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/tls1.c
@@ -0,0 +1,2057 @@
+/*
+ * 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 "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 void 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;
+
+ /* spec says we must notify when we are dying */
+ 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);
+}
+
+/*
+ * 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)
+ {
+ 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 - change of "
+ "compile-time configuration required\n");
+#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_ERROR_NO_CERT_DEFINED;
+ int i = 0;
+ int offset;
+ 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++;
+
+ if (i > CONFIG_X509_MAX_CA_CERTS)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("Error: maximum number of CA certs added - change of "
+ "compile-time configuration required\n");
+#endif
+ goto error;
+ }
+
+ if ((ret = x509_new(buf, &offset, &ca_cert_ctx->cert[i])))
+ goto error;
+
+ len -= offset;
+ ret = SSL_OK; /* ok so far */
+
+ /* recurse? */
+ if (len > 0)
+ ret = add_cert_auth(ssl_ctx, &buf[offset], len);
+
+error:
+ 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;
+ }
+}
+
+#endif
+
+/*
+ * 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)
+ {
+ hmac_offset = read_len-buf[read_len-1]-ssl->cipher_info->digest_size-1;
+ }
+ else
+ {
+ hmac_offset = read_len - ssl->cipher_info->digest_size;
+ }
+
+ /* sanity check the offset */
+ if (hmac_offset < 0)
+ {
+ return SSL_ERROR_INVALID_HMAC;
+ }
+
+ 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;
+ }
+ break;
+
+ 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;
+ }
+ break;
+ }
+
+ 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 (TLS) */
+ rec_buf[2] = 0x01;
+ 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)
+ {
+ if ((ret = SOCKET_WRITE(ssl->client_fd,
+ &ssl->bm_all_data[sent], pkt_size)) < 0)
+ {
+ ret = SSL_ERROR_CONN_LOST;
+ break;
+ }
+
+ sent += ret;
+
+ /* 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);
+
+ if (select(ssl->client_fd + 1, NULL, &wfds, NULL, NULL) < 0)
+ {
+ ret = SSL_ERROR_CONN_LOST;
+ break;
+ }
+ }
+ }
+
+ 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 msg_length = length;
+ int ret, pad_bytes = 0;
+ ssl->bm_index = msg_length;
+
+ /* 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);
+ }
+
+ 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];
+
+ hmac_header[0] = protocol;
+ hmac_header[1] = 0x03;
+ hmac_header[2] = 0x01;
+ hmac_header[3] = length >> 8;
+ hmac_header[4] = 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, ssl->bm_index);
+ }
+ }
+
+ /* add the packet digest */
+ msg_length += ssl->cipher_info->digest_size;
+ ssl->bm_index = msg_length;
+ add_hmac_digest(ssl, mode, hmac_header, ssl->bm_data, length,
+ &ssl->bm_data[length]);
+
+ /* add padding? */
+ if (ssl->cipher_info->padding_size)
+ {
+ int last_blk_size = msg_length%ssl->cipher_info->padding_size;
+ 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;
+ ssl->bm_index = msg_length;
+ }
+
+ DISPLAY_BYTES(ssl, "unencrypted write", ssl->bm_data, msg_length);
+ increment_write_sequence(ssl);
+
+ /* 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, ssl->bm_index);
+ }
+ }
+
+ 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 void 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);
+
+ /* 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;
+}
+
+/**
+ * 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);
+
+ /* 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 && buf[3] == 0x03)
+ {
+#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
+ DISPLAY_BYTES(ssl, "ssl2 record", buf, 5);
+ 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);
+ 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:
+ ssl->dc->bm_proc_index = 0;
+ ret = do_handshake(ssl, buf, read_len);
+ 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);
+ set_key_block(ssl, 0);
+ memset(ssl->read_sequence, 0, 8);
+ break;
+
+ case PT_APP_PROTOCOL_DATA:
+ if (in_data)
+ {
+ *in_data = ssl->bm_data; /* 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 */
+ 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);
+ set_key_block(ssl, 1);
+ memset(ssl->write_sequence, 0, 8);
+ return ret;
+}
+
+/**
+ * Send a "finished" message
+ */
+int send_finished(SSL *ssl)
+{
+ uint8_t *buf = ssl->bm_data;
+
+ buf[0] = HS_FINISHED;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 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,
+ NULL, 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;
+
+ 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, int hs_len)
+{
+ uint8_t *buf = ssl->bm_data;
+ 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 */
+ 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;
+ }
+
+ /* DISPLAY_CERT(ssl, *chain); */
+ 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 X509 certificates.
+ */
+void DISPLAY_CERT(SSL *ssl, const X509_CTX *x509_ctx)
+{
+ if (!IS_SET_SSL_FLAG(SSL_DISPLAY_CERTS))
+ return;
+
+ x509_print(x509_ctx, ssl->ssl_ctx->ca_cert_ctx);
+ 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_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;
+
+ 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;
+}
+
+#endif /* CONFIG_SSL_CERT_VERIFICATION */
+
+#endif /* CONFIG_BINDINGS */
+
diff --git a/libs/luci-lib-nixio/axTLS/ssl/tls1.h b/libs/luci-lib-nixio/axTLS/ssl/tls1.h
new file mode 100755
index 0000000000..b64b4fda62
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/tls1.h
@@ -0,0 +1,289 @@
+/*
+ * 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 "os_port.h"
+#include "crypto_misc.h"
+
+#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
+
+/* 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;
+ 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, 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/libs/luci-lib-nixio/axTLS/ssl/tls1_clnt.c b/libs/luci-lib-nixio/axTLS/ssl/tls1_clnt.c
new file mode 100644
index 0000000000..91314333c0
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/tls1_clnt.c
@@ -0,0 +1,386 @@
+/*
+ * 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 "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;
+ int ret;
+
+ SOCKET_BLOCK(client_fd); /* ensure blocking mode */
+ ssl = ssl_new(ssl_ctx, client_fd);
+
+ 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);
+ ret = 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 = SSL_OK;
+
+ /* 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, hs_len);
+ disposable_free(ssl); /* free up some memory */
+ break;
+
+ case HS_HELLO_REQUEST:
+ disposable_new(ssl);
+ ret = do_client_connect(ssl);
+ 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 */
+ x509_free(ssl->x509_ctx);
+
+ /* sit in a loop until it all looks good */
+ while (ssl->hs_status != SSL_OK)
+ {
+ ret = basic_read(ssl, NULL);
+
+ if (ret < SSL_OK)
+ {
+ if (ret != SSL_ERROR_CONN_LOST)
+ {
+ /* let the server know we are dying and why */
+ if (send_alert(ssl, ret))
+ {
+ /* something nasty happened, so get rid of it */
+ kill_ssl_session(ssl->ssl_ctx->ssl_sessions, ssl);
+ }
+ }
+
+ 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] = 0x01;
+
+ /* 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 version = (buf[4] << 4) + buf[5];
+ 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 */
+ if (version != 0x31)
+ return SSL_ERROR_INVALID_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 (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] = 0x01;
+ 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/libs/luci-lib-nixio/axTLS/ssl/tls1_svr.c b/libs/luci-lib-nixio/axTLS/ssl/tls1_svr.c
new file mode 100644
index 0000000000..45b9bec6a6
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/tls1_svr.c
@@ -0,0 +1,476 @@
+/*
+ * 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 "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, 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 version = (record_buf[1] << 4) + record_buf[2];
+ int ret = SSL_OK;
+
+ /* should be v3.1 (TLSv1) or better - we'll send in v3.1 mode anyway */
+ if (version < 0x31)
+ {
+ 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 */
+ for (j = 0; j < NUM_PROTOCOLS; j++)
+ {
+ for (i = 0; i < cs_len; i += 2)
+ {
+ 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 version = (buf[3] << 4) + buf[4];
+ 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);
+
+ /* should be v3.1 (TLSv1) or better - we'll send in v3.1 mode anyway */
+ if (version < 0x31)
+ {
+ return SSL_ERROR_INVALID_VERSION;
+ }
+
+ 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] = 0x01;
+
+ /* 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 || /* check version is 3.1 (TLS) */
+ premaster_secret[1] != 0x01)
+ {
+ /* guard against a Bleichenbacher attack */
+ memset(premaster_secret, 0, SSL_SECRET_SIZE);
+ /* 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
+error:
+ ssl->dc->bm_proc_index += rsa_ctx->num_octets+offset;
+ 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/libs/luci-lib-nixio/axTLS/ssl/version.h b/libs/luci-lib-nixio/axTLS/ssl/version.h
new file mode 100644
index 0000000000..72260bf19e
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/version.h
@@ -0,0 +1 @@
+#define AXTLS_VERSION "1.2.1"
diff --git a/libs/luci-lib-nixio/axTLS/ssl/x509.c b/libs/luci-lib-nixio/axTLS/ssl/x509.c
new file mode 100644
index 0000000000..37db7f4e81
--- /dev/null
+++ b/libs/luci-lib-nixio/axTLS/ssl/x509.c
@@ -0,0 +1,502 @@
+/*
+ * 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;
+
+ *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;
+
+#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);
+ }
+
+ offset = end_tbs; /* skip the v3 data */
+ if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
+ asn1_signature(cert, &offset, x509_ctx))
+ goto end_cert;
+#endif
+
+ if (len)
+ {
+ *len = cert_size;
+ }
+
+ ret = X509_OK;
+end_cert:
+
+#ifdef CONFIG_SSL_FULL_MODE
+ if (ret)
+ {
+ printf("Error: Invalid X509 ASN.1 file\n");
+ }
+#endif
+
+ 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);
+ }
+#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 */
+