]> granicus.if.org Git - pdns/commitdiff
Upgrade to polarssl 1.3.8
authorRuben Kerkhof <ruben@rubenkerkhof.com>
Sat, 11 Oct 2014 12:24:13 +0000 (14:24 +0200)
committermind04 <mind04@monshouwer.org>
Mon, 22 Dec 2014 19:33:45 +0000 (20:33 +0100)
Upstream commit 1910aa78a367

133 files changed:
pdns/dist-recursor
pdns/ext/polarssl/CMakeLists.txt
pdns/ext/polarssl/ChangeLog
pdns/ext/polarssl/README.rst
pdns/ext/polarssl/include/polarssl/aes.h
pdns/ext/polarssl/include/polarssl/aesni.h [new file with mode: 0644]
pdns/ext/polarssl/include/polarssl/arc4.h
pdns/ext/polarssl/include/polarssl/asn1.h
pdns/ext/polarssl/include/polarssl/asn1write.h
pdns/ext/polarssl/include/polarssl/bignum.h
pdns/ext/polarssl/include/polarssl/blowfish.h
pdns/ext/polarssl/include/polarssl/bn_mul.h
pdns/ext/polarssl/include/polarssl/camellia.h
pdns/ext/polarssl/include/polarssl/ccm.h [new file with mode: 0644]
pdns/ext/polarssl/include/polarssl/check_config.h [new file with mode: 0644]
pdns/ext/polarssl/include/polarssl/cipher.h
pdns/ext/polarssl/include/polarssl/cipher_wrap.h
pdns/ext/polarssl/include/polarssl/compat-1.2.h
pdns/ext/polarssl/include/polarssl/config.h
pdns/ext/polarssl/include/polarssl/ctr_drbg.h
pdns/ext/polarssl/include/polarssl/debug.h
pdns/ext/polarssl/include/polarssl/des.h
pdns/ext/polarssl/include/polarssl/dhm.h
pdns/ext/polarssl/include/polarssl/ecdh.h
pdns/ext/polarssl/include/polarssl/ecdsa.h
pdns/ext/polarssl/include/polarssl/ecp.h
pdns/ext/polarssl/include/polarssl/entropy.h
pdns/ext/polarssl/include/polarssl/entropy_poll.h
pdns/ext/polarssl/include/polarssl/error.h
pdns/ext/polarssl/include/polarssl/gcm.h
pdns/ext/polarssl/include/polarssl/havege.h
pdns/ext/polarssl/include/polarssl/hmac_drbg.h [new file with mode: 0644]
pdns/ext/polarssl/include/polarssl/md.h
pdns/ext/polarssl/include/polarssl/md2.h
pdns/ext/polarssl/include/polarssl/md4.h
pdns/ext/polarssl/include/polarssl/md5.h
pdns/ext/polarssl/include/polarssl/md_wrap.h
pdns/ext/polarssl/include/polarssl/memory.h
pdns/ext/polarssl/include/polarssl/memory_buffer_alloc.h [new file with mode: 0644]
pdns/ext/polarssl/include/polarssl/net.h
pdns/ext/polarssl/include/polarssl/oid.h
pdns/ext/polarssl/include/polarssl/openssl.h
pdns/ext/polarssl/include/polarssl/padlock.h
pdns/ext/polarssl/include/polarssl/pk.h
pdns/ext/polarssl/include/polarssl/pk_wrap.h
pdns/ext/polarssl/include/polarssl/pkcs11.h
pdns/ext/polarssl/include/polarssl/pkcs12.h
pdns/ext/polarssl/include/polarssl/platform.h [new file with mode: 0644]
pdns/ext/polarssl/include/polarssl/ripemd160.h [new file with mode: 0644]
pdns/ext/polarssl/include/polarssl/rsa.h
pdns/ext/polarssl/include/polarssl/sha1.h
pdns/ext/polarssl/include/polarssl/sha256.h
pdns/ext/polarssl/include/polarssl/sha512.h
pdns/ext/polarssl/include/polarssl/ssl.h
pdns/ext/polarssl/include/polarssl/ssl_cache.h
pdns/ext/polarssl/include/polarssl/ssl_ciphersuites.h
pdns/ext/polarssl/include/polarssl/threading.h
pdns/ext/polarssl/include/polarssl/timing.h
pdns/ext/polarssl/include/polarssl/version.h
pdns/ext/polarssl/include/polarssl/x509.h
pdns/ext/polarssl/include/polarssl/x509_crl.h
pdns/ext/polarssl/include/polarssl/x509_crt.h
pdns/ext/polarssl/include/polarssl/x509_csr.h
pdns/ext/polarssl/include/polarssl/xtea.h
pdns/ext/polarssl/library/Makefile.am
pdns/ext/polarssl/library/aes.c
pdns/ext/polarssl/library/aesni.c [new file with mode: 0644]
pdns/ext/polarssl/library/arc4.c
pdns/ext/polarssl/library/asn1parse.c
pdns/ext/polarssl/library/asn1write.c
pdns/ext/polarssl/library/base64.c
pdns/ext/polarssl/library/bignum.c
pdns/ext/polarssl/library/blowfish.c
pdns/ext/polarssl/library/camellia.c
pdns/ext/polarssl/library/ccm.c [new file with mode: 0644]
pdns/ext/polarssl/library/certs.c
pdns/ext/polarssl/library/cipher.c
pdns/ext/polarssl/library/cipher_wrap.c
pdns/ext/polarssl/library/ctr_drbg.c
pdns/ext/polarssl/library/debug.c
pdns/ext/polarssl/library/des.c
pdns/ext/polarssl/library/dhm.c
pdns/ext/polarssl/library/ecdh.c
pdns/ext/polarssl/library/ecdsa.c
pdns/ext/polarssl/library/ecp.c
pdns/ext/polarssl/library/ecp_curves.c [new file with mode: 0644]
pdns/ext/polarssl/library/entropy.c
pdns/ext/polarssl/library/entropy_poll.c
pdns/ext/polarssl/library/error.c
pdns/ext/polarssl/library/gcm.c
pdns/ext/polarssl/library/havege.c
pdns/ext/polarssl/library/hmac_drbg.c [new file with mode: 0644]
pdns/ext/polarssl/library/md.c
pdns/ext/polarssl/library/md2.c
pdns/ext/polarssl/library/md4.c
pdns/ext/polarssl/library/md5.c
pdns/ext/polarssl/library/md_wrap.c
pdns/ext/polarssl/library/memory_buffer_alloc.c
pdns/ext/polarssl/library/net.c
pdns/ext/polarssl/library/oid.c
pdns/ext/polarssl/library/padlock.c
pdns/ext/polarssl/library/pbkdf2.c
pdns/ext/polarssl/library/pem.c
pdns/ext/polarssl/library/pk.c
pdns/ext/polarssl/library/pk_wrap.c
pdns/ext/polarssl/library/pkcs11.c
pdns/ext/polarssl/library/pkcs12.c
pdns/ext/polarssl/library/pkcs5.c
pdns/ext/polarssl/library/pkparse.c
pdns/ext/polarssl/library/pkwrite.c
pdns/ext/polarssl/library/platform.c [new file with mode: 0644]
pdns/ext/polarssl/library/ripemd160.c [new file with mode: 0644]
pdns/ext/polarssl/library/rsa.c
pdns/ext/polarssl/library/sha1.c
pdns/ext/polarssl/library/sha256.c
pdns/ext/polarssl/library/sha512.c
pdns/ext/polarssl/library/ssl_cache.c
pdns/ext/polarssl/library/ssl_ciphersuites.c
pdns/ext/polarssl/library/ssl_cli.c
pdns/ext/polarssl/library/ssl_srv.c
pdns/ext/polarssl/library/ssl_tls.c
pdns/ext/polarssl/library/threading.c
pdns/ext/polarssl/library/timing.c
pdns/ext/polarssl/library/version.c
pdns/ext/polarssl/library/version_features.c [new file with mode: 0644]
pdns/ext/polarssl/library/x509.c
pdns/ext/polarssl/library/x509_create.c
pdns/ext/polarssl/library/x509_crl.c
pdns/ext/polarssl/library/x509_crt.c
pdns/ext/polarssl/library/x509_csr.c
pdns/ext/polarssl/library/x509write_crt.c
pdns/ext/polarssl/library/x509write_csr.c
pdns/ext/polarssl/library/xtea.c

index e3b81d91557313a91c6bf9a0bc59193189a8729e..b9a61413692a605dca60628179ae2fcdb00826c4 100755 (executable)
@@ -60,7 +60,7 @@ mkdir -p $DIRNAME/ext/rapidjson/include/rapidjson/internal
 cp -a ext/rapidjson/include/rapidjson/*.h $DIRNAME/ext/rapidjson/include/rapidjson/
 cp -a ext/rapidjson/include/rapidjson/internal/*.h $DIRNAME/ext/rapidjson/include/rapidjson/internal
 mkdir -p $DIRNAME/ext/polarssl/include/polarssl
-cp -a ext/polarssl/include/polarssl/config.h ext/polarssl/include/polarssl/aes.h ext/polarssl/include/polarssl/padlock.h $DIRNAME/ext/polarssl/include/polarssl
+cp -a ext/polarssl/include/polarssl/config.h ext/polarssl/include/polarssl/check_config.h ext/polarssl/include/polarssl/aes.h ext/polarssl/include/polarssl/padlock.h $DIRNAME/ext/polarssl/include/polarssl
 mkdir -p $DIRNAME/ext/polarssl/library
 cp -a ext/polarssl/library/aes.c ext/polarssl/library/padlock.c $DIRNAME/ext/polarssl/library
 cp -a ext/yahttp/ $DIRNAME/ext/yahttp
index 08cb9b51cd0c00420df0d77315e58e7d9e3cb127..86439ada42a22163ddb1fcb9f8fb97d56caf9443 100644 (file)
@@ -1,23 +1,49 @@
 cmake_minimum_required(VERSION 2.6)
 project(POLARSSL C)
 
-enable_testing()
+string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
 
 if(CMAKE_COMPILER_IS_GNUCC)
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -Wall -Wextra -W -Wdeclaration-after-statement")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement")
+  set(CMAKE_C_FLAGS_RELEASE "-O2")
   set(CMAKE_C_FLAGS_DEBUG "-g3 -O0")
-  set(CMAKE_C_FLAGS_COVERAGE "-g3 -O0 -fprofile-arcs -ftest-coverage -lgcov")
+  set(CMAKE_C_FLAGS_COVERAGE "-g3 -O0 --coverage")
+  set(CMAKE_C_FLAGS_ASAN "-fsanitize=address -fno-omit-frame-pointer -g3 -O1")
+  set(CMAKE_C_FLAGS_CHECK "${CMAKE_C_FLAGS} -Werror -O1 -Wlogical-op -Wwrite-strings")
+  set(CMAKE_C_FLAGS_CHECKFULL "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
 endif(CMAKE_COMPILER_IS_GNUCC)
+
+if(CMAKE_COMPILER_IS_CLANG)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement")
+  set(CMAKE_C_FLAGS_RELEASE "-O2")
+  set(CMAKE_C_FLAGS_DEBUG "-g3 -O0")
+  set(CMAKE_C_FLAGS_COVERAGE "-g3 -O0 --coverage")
+  set(CMAKE_C_FLAGS_ASAN "-fsanitize=address -fno-omit-frame-pointer -g3 -O1")
+  set(CMAKE_C_FLAGS_CHECK "${CMAKE_C_FLAGS} -Werror -O1 -Wpointer-arith -Wwrite-strings -Wdocumentation -Wunreachable-code")
+endif(CMAKE_COMPILER_IS_CLANG)
+
+set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
+    CACHE STRING "Choose the type of build: None Debug Release Coverage ASan Check CheckFull"
+    FORCE)
+
 if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
   if(CMAKE_COMPILER_IS_GNUCC)
-    set(CMAKE_SHARED_LINKER_FLAGS "-fprofile-arcs -ftest-coverage")
+    set(CMAKE_SHARED_LINKER_FLAGS "--coverage")
   endif(CMAKE_COMPILER_IS_GNUCC)
+  if(CMAKE_COMPILER_IS_CLANG)
+    set(CMAKE_SHARED_LINKER_FLAGS "--coverage")
+  endif(CMAKE_COMPILER_IS_CLANG)
 endif(CMAKE_BUILD_TYPE STREQUAL "Coverage")
 
 option(USE_PKCS11_HELPER_LIBRARY "Build PolarSSL with the pkcs11-helper library." OFF)
 
 option(ENABLE_ZLIB_SUPPORT "Build PolarSSL with zlib library." OFF)
+option(ENABLE_PROGRAMS "Build PolarSSL programs." ON)
+option(ENABLE_TESTING "Build PolarSSL tests." ON)
+
+if(ENABLE_TESTING)
+  enable_testing()
+endif()
 
 if(LIB_INSTALL_DIR)
 else()
@@ -30,25 +56,56 @@ if(ENABLE_ZLIB_SUPPORT)
   find_package(ZLIB)
 
   if(ZLIB_FOUND)
-    include_directories(ZLIB_INCLUDE_DIR)
+    include_directories(${ZLIB_INCLUDE_DIR})
   endif(ZLIB_FOUND)
 endif(ENABLE_ZLIB_SUPPORT)
 
 add_subdirectory(library)
 add_subdirectory(include)
 
-if(CMAKE_COMPILER_IS_GNUCC)
-  add_subdirectory(tests)
-endif(CMAKE_COMPILER_IS_GNUCC)
+if(ENABLE_TESTING)
+  if(CMAKE_COMPILER_IS_GNUCC)
+    add_subdirectory(tests)
+  endif(CMAKE_COMPILER_IS_GNUCC)
+  if(CMAKE_COMPILER_IS_CLANG)
+    add_subdirectory(tests)
+  endif(CMAKE_COMPILER_IS_CLANG)
+endif()
 
-add_subdirectory(programs)
+if(ENABLE_PROGRAMS)
+  add_subdirectory(programs)
+endif()
 
 ADD_CUSTOM_TARGET(apidoc
                   COMMAND doxygen doxygen/polarssl.doxyfile
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 
-ADD_CUSTOM_TARGET(memcheck
+if(ENABLE_TESTING)
+  ADD_CUSTOM_TARGET(test-ref-config
+    COMMAND tests/scripts/test-ref-configs.pl
+    )
+
+  ADD_CUSTOM_TARGET(covtest
+    COMMAND make test
+    COMMAND programs/test/selftest
+    COMMAND cd tests && ./compat.sh
+    COMMAND cd tests && ./ssl-opt.sh
+    )
+
+  ADD_CUSTOM_TARGET(lcov
+    COMMAND rm -rf Coverage
+    COMMAND lcov --capture --initial --directory library/CMakeFiles/polarssl.dir -o files.info
+    COMMAND lcov --capture --directory library/CMakeFiles/polarssl.dir -o tests.info
+    COMMAND lcov --add-tracefile files.info --add-tracefile tests.info -o all.info
+    COMMAND lcov --remove all.info -o final.info '*.h'
+    COMMAND gendesc tests/Descriptions.txt -o descriptions
+    COMMAND genhtml --title PolarSSL --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage final.info
+    COMMAND rm -f files.info tests.info all.info final.info descriptions
+    )
+
+  ADD_CUSTOM_TARGET(memcheck
     COMMAND ctest -O memcheck.log -D ExperimentalMemCheck
     COMMAND tail -n1 memcheck.log | grep 'Memory checking results:' > /dev/null
     COMMAND rm -f memcheck.log
     )
+endif()
index 334d147fa6b4cedd71928f2fd401a3e9dae7d0e1..163bdb796eeb6c7f273634a49b9266668385eee1 100644 (file)
@@ -1,5 +1,278 @@
 PolarSSL ChangeLog (Sorted per branch, date)
 
+= PolarSSL 1.3.8 released 2014-07-11
+Security
+   * Fix length checking for AEAD ciphersuites (found by Codenomicon).
+     It was possible to crash the server (and client) using crafted messages
+     when a GCM suite was chosen.
+
+Features
+   * Add CCM module and cipher mode to Cipher Layer
+   * Support for CCM and CCM_8 ciphersuites
+   * Support for parsing and verifying RSASSA-PSS signatures in the X.509
+     modules (certificates, CRLs and CSRs).
+   * Blowfish in the cipher layer now supports variable length keys.
+   * Add example config.h for PSK with CCM, optimized for low RAM usage.
+   * Optimize for RAM usage in example config.h for NSA Suite B profile.
+   * Add POLARSSL_REMOVE_ARC4_CIPHERSUITES to allow removing RC4 ciphersuites
+     from the default list (inactive by default).
+   * Add server-side enforcement of sent renegotiation requests
+     (ssl_set_renegotiation_enforced())
+   * Add SSL_CIPHERSUITES config.h flag to allow specifying a list of
+     ciphersuites to use and save some memory if the list is small.
+
+Changes
+   * Add LINK_WITH_PTHREAD option in CMake for explicit linking that is
+     required on some platforms (e.g. OpenBSD)
+   * Migrate zeroizing of data to polarssl_zeroize() instead of memset()
+     against unwanted compiler optimizations
+   * md_list() now returns hashes strongest first
+   * Selection of hash for signing ServerKeyExchange in TLS 1.2 now picks
+     strongest offered by client.
+   * All public contexts have _init() and _free() functions now for simpler
+     usage pattern
+
+Bugfix
+   * Fix in debug_print_msg()
+   * Enforce alignment in the buffer allocator even if buffer is not aligned
+   * Remove less-than-zero checks on unsigned numbers
+   * Stricter check on SSL ClientHello internal sizes compared to actual packet
+     size (found by TrustInSoft)
+   * Fix WSAStartup() return value check (found by Peter Vaskovic)
+   * Other minor issues (found by Peter Vaskovic)
+   * Fix symlink command for cross compiling with CMake (found by Andre
+     Heinecke)
+   * Fix DER output of gen_key app (found by Gergely Budai)
+   * Very small records were incorrectly rejected when truncated HMAC was in
+     use with some ciphersuites and versions (RC4 in all versions, CBC with
+     versions < TLS 1.1).
+   * Very large records using more than 224 bytes of padding were incorrectly
+     rejected with CBC-based ciphersuites and TLS >= 1.1
+   * Very large records using less padding could cause a buffer overread of up
+     to 32 bytes with CBC-based ciphersuites and TLS >= 1.1
+   * Restore ability to use a v1 cert as a CA if trusted locally. (This had
+     been removed in 1.3.6.)
+   * Restore ability to locally trust a self-signed cert that is not a proper
+     CA for use as an end entity certificate. (This had been removed in
+     1.3.6.)
+   * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan).
+   * Use \n\t rather than semicolons for bn_mul asm, since some assemblers
+     interpret semicolons as comment delimiters (found by Barry K. Nathan).
+   * Fix off-by-one error in parsing Supported Point Format extension that
+     caused some handshakes to fail.
+   * Fix possible miscomputation of the premaster secret with DHE-PSK key
+     exchange that caused some handshakes to fail with other implementations.
+     (Failure rate <= 1/255 with common DHM moduli.)
+   * Disable broken Sparc64 bn_mul assembly (found by Florian Obser).
+   * Fix base64_decode() to return and check length correctly (in case of
+     tight buffers)
+   * Fix mpi_write_string() to write "00" as hex output for empty MPI (found
+     by Hui Dong)
+
+= PolarSSL 1.3.7 released on 2014-05-02
+Features
+   * debug_set_log_mode() added to determine raw or full logging
+   * debug_set_threshold() added to ignore messages over threshold level
+   * version_check_feature() added to check for compile-time options at
+     run-time
+
+Changes
+   * POLARSSL_CONFIG_OPTIONS has been removed. All values are individually
+     checked and filled in the relevant module headers
+   * Debug module only outputs full lines instead of parts
+   * Better support for the different Attribute Types from IETF PKIX (RFC 5280)
+   * AES-NI now compiles with "old" assemblers too
+   * Ciphersuites based on RC4 now have the lowest priority by default
+
+Bugfix
+   * Only iterate over actual certificates in ssl_write_certificate_request()
+     (found by Matthew Page)
+   * Typos in platform.c and pkcs11.c (found by Daniel Phillips and Steffan
+     Karger)
+   * cert_write app should use subject of issuer certificate as issuer of cert
+   * Fix false reject in padding check in ssl_decrypt_buf() for CBC
+     ciphersuites, for full SSL frames of data.
+   * Improve interoperability by not writing extension length in ClientHello /
+     ServerHello when no extensions are present (found by Matthew Page)
+   * rsa_check_pubkey() now allows an E up to N
+   * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings
+   * mpi_fill_random() was creating numbers larger than requested on
+     big-endian platform when size was not an integer number of limbs
+   * Fix dependencies issues in X.509 test suite.
+   * Some parts of ssl_tls.c were compiled even when the module was disabled.
+   * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer)
+   * Fix detection of Clang on some Apple platforms with CMake
+     (found by Barry K. Nathan)
+
+= PolarSSL 1.3.6 released on 2014-04-11
+
+Features
+   * Support for the ALPN SSL extension
+   * Add option 'use_dev_random' to gen_key application
+   * Enable verification of the keyUsage extension for CA and leaf
+     certificates (POLARSSL_X509_CHECK_KEY_USAGE)
+   * Enable verification of the extendedKeyUsage extension
+     (POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+
+Changes
+   * x509_crt_info() now prints information about parsed extensions as well
+   * pk_verify() now returns a specific error code when the signature is valid
+     but shorter than the supplied length.
+   * Use UTC time to check certificate validity.
+   * Reject certificates with times not in UTC, per RFC 5280.
+
+Security
+   * Avoid potential timing leak in ecdsa_sign() by blinding modular division.
+     (Found by Watson Ladd.)
+   * The notAfter date of some certificates was no longer checked since 1.3.5.
+     This affects certificates in the user-supplied chain except the top
+     certificate. If the user-supplied chain contains only one certificates,
+     it is not affected (ie, its notAfter date is properly checked).
+   * Prevent potential NULL pointer dereference in ssl_read_record() (found by
+     TrustInSoft)
+
+Bugfix
+   * The length of various ClientKeyExchange messages was not properly checked.
+   * Some example server programs were not sending the close_notify alert.
+   * Potential memory leak in mpi_exp_mod() when error occurs during
+     calculation of RR.
+   * Fixed malloc/free default #define in platform.c (found by Gergely Budai).
+   * Fixed type which made POLARSSL_ENTROPY_FORCE_SHA256 uneffective (found by
+     Gergely Budai).
+   * Fix #include path in ecdsa.h which wasn't accepted by some compilers.
+     (found by Gergely Budai)
+   * Fix compile errors when POLARSSL_ERROR_STRERROR_BC is undefined (found by
+     Shuo Chen).
+   * oid_get_numeric_string() used to truncate the output without returning an
+     error if the output buffer was just 1 byte too small.
+   * dhm_parse_dhm() (hence dhm_parse_dhmfile()) did not set dhm->len.
+   * Calling pk_debug() on an RSA-alt key would segfault.
+   * pk_get_size() and pk_get_len() were off by a factor 8 for RSA-alt keys.
+   * Potential buffer overwrite in pem_write_buffer() because of low length
+     indication (found by Thijs Alkemade)
+   * EC curves constants, which should be only in ROM since 1.3.3, were also
+     stored in RAM due to missing 'const's (found by Gergely Budai).
+
+= PolarSSL 1.3.5 released on 2014-03-26
+Features
+   * HMAC-DRBG as a separate module
+   * Option to set the Curve preference order (disabled by default)
+   * Single Platform compatilibity layer (for memory / printf / fprintf)
+   * Ability to provide alternate timing implementation
+   * Ability to force the entropy module to use SHA-256 as its basis
+     (POLARSSL_ENTROPY_FORCE_SHA256)
+   * Testing script ssl-opt.sh added for testing 'live' ssl option
+     interoperability against OpenSSL and PolarSSL
+   * Support for reading EC keys that use SpecifiedECDomain in some cases.
+   * Entropy module now supports seed writing and reading
+
+Changes
+   * Deprecated the Memory layer
+   * entropy_add_source(), entropy_update_manual() and entropy_gather()
+     now thread-safe if POLARSSL_THREADING_C defined
+   * Improvements to the CMake build system, contributed by Julian Ospald.
+   * Work around a bug of the version of Clang shipped by Apple with Mavericks
+     that prevented bignum.c from compiling. (Reported by Rafael Baptista.)
+   * Revamped the compat.sh interoperatibility script to include support for
+     testing against GnuTLS
+   * Deprecated ssl_set_own_cert_rsa() and ssl_set_own_cert_rsa_alt()
+   * Improvements to tests/Makefile, contributed by Oden Eriksson.
+
+Security
+   * Forbid change of server certificate during renegotiation to prevent
+     "triple handshake" attack when authentication mode is 'optional' (the
+     attack was already impossible when authentication is required).
+   * Check notBefore timestamp of certificates and CRLs from the future.
+   * Forbid sequence number wrapping
+   * Fixed possible buffer overflow with overlong PSK
+   * Possible remotely-triggered out-of-bounds memory access fixed (found by
+     TrustInSoft)
+
+Bugfix
+   * ecp_gen_keypair() does more tries to prevent failure because of
+     statistics
+   * Fixed bug in RSA PKCS#1 v1.5 "reversed" operations
+   * Fixed testing with out-of-source builds using cmake
+   * Fixed version-major intolerance in server
+   * Fixed CMake symlinking on out-of-source builds
+   * Fixed dependency issues in test suite
+   * Programs rsa_sign_pss and rsa_verify_pss were not using PSS since 1.3.0
+   * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by
+     Alex Wilson.)
+   * ssl_cache was creating entries when max_entries=0 if TIMING_C was enabled.
+   * m_sleep() was sleeping twice too long on most Unix platforms.
+   * Fixed bug with session tickets and non-blocking I/O in the unlikely case
+     send() would return an EAGAIN error when sending the ticket.
+   * ssl_cache was leaking memory when reusing a timed out entry containing a
+     client certificate.
+   * ssl_srv was leaking memory when client presented a timed out ticket
+     containing a client certificate
+   * ssl_init() was leaving a dirty pointer in ssl_context if malloc of
+     out_ctr failed
+   * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc
+     of one of them failed
+   * Fix typo in rsa_copy() that impacted PKCS#1 v2 contexts
+   * x509_get_current_time() uses localtime_r() to prevent thread issues
+
+= PolarSSL 1.3.4 released on 2014-01-27
+Features
+   * Support for the Koblitz curves: secp192k1, secp224k1, secp256k1
+   * Support for RIPEMD-160
+   * Support for AES CFB8 mode
+   * Support for deterministic ECDSA (RFC 6979)
+
+Bugfix
+   * Potential memory leak in bignum_selftest()
+   * Replaced expired test certificate
+   * ssl_mail_client now terminates lines with CRLF, instead of LF
+   * net module handles timeouts on blocking sockets better (found by Tilman
+     Sauerbeck)
+   * Assembly format fixes in bn_mul.h
+
+Security
+   * Missing MPI_CHK calls added around unguarded mpi calls (found by
+     TrustInSoft)
+
+= PolarSSL 1.3.3 released on 2013-12-31
+Features
+   * EC key generation support in gen_key app
+   * Support for adhering to client ciphersuite order preference
+     (POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
+   * Support for Curve25519
+   * Support for ECDH-RSA and ECDH-ECDSA key exchanges and ciphersuites
+   * Support for IPv6 in the NET module
+   * AES-NI support for AES, AES-GCM and AES key scheduling
+   * SSL Pthread-based server example added (ssl_pthread_server)
+
+Changes
+   * gen_prime() speedup
+   * Speedup of ECP multiplication operation
+   * Relaxed some SHA2 ciphersuite's version requirements
+   * Dropped use of readdir_r() instead of readdir() with threading support
+   * More constant-time checks in the RSA module
+   * Split off curves from ecp.c into ecp_curves.c
+   * Curves are now stored fully in ROM
+   * Memory usage optimizations in ECP module
+   * Removed POLARSSL_THREADING_DUMMY
+
+Bugfix
+   * Fixed bug in mpi_set_bit() on platforms where t_uint is wider than int
+   * Fixed X.509 hostname comparison (with non-regular characters)
+   * SSL now gracefully handles missing RNG
+   * Missing defines / cases for RSA_PSK key exchange
+   * crypt_and_hash app checks MAC before final decryption
+   * Potential memory leak in ssl_ticket_keys_init()
+   * Memory leak in benchmark application
+   * Fixed x509_crt_parse_path() bug on Windows platforms
+   * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by
+     TrustInSoft)
+   * Fixed potential overflow in certificate size verification in
+     ssl_write_certificate() (found by TrustInSoft)
+
+Security
+   * Possible remotely-triggered out-of-bounds memory access fixed (found by
+     TrustInSoft)
+
 = PolarSSL 1.3.2 released on 2013-11-04
 Features
    * PK tests added to test framework
@@ -107,6 +380,76 @@ Security
    * RSA blinding on CRT operations to counter timing attacks
      (found by Cyril Arnaud and Pierre-Alain Fouque)
 
+= Version 1.2.11 released 2014-07-11
+Features
+   * Entropy module now supports seed writing and reading
+
+Changes
+   * Introduced POLARSSL_HAVE_READDIR_R for systems without it
+   * Improvements to the CMake build system, contributed by Julian Ospald.
+   * Work around a bug of the version of Clang shipped by Apple with Mavericks
+     that prevented bignum.c from compiling. (Reported by Rafael Baptista.)
+   * Improvements to tests/Makefile, contributed by Oden Eriksson.
+   * Use UTC time to check certificate validity.
+   * Reject certificates with times not in UTC, per RFC 5280.
+   * Migrate zeroizing of data to polarssl_zeroize() instead of memset()
+     against unwanted compiler optimizations
+
+Security
+   * Forbid change of server certificate during renegotiation to prevent
+     "triple handshake" attack when authentication mode is optional (the
+     attack was already impossible when authentication is required).
+   * Check notBefore timestamp of certificates and CRLs from the future.
+   * Forbid sequence number wrapping
+   * Prevent potential NULL pointer dereference in ssl_read_record() (found by
+     TrustInSoft)
+   * Fix length checking for AEAD ciphersuites (found by Codenomicon).
+     It was possible to crash the server (and client) using crafted messages
+     when a GCM suite was chosen.
+
+Bugfix
+   * Fixed X.509 hostname comparison (with non-regular characters)
+   * SSL now gracefully handles missing RNG
+   * crypt_and_hash app checks MAC before final decryption
+   * Fixed x509_crt_parse_path() bug on Windows platforms
+   * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by
+     TrustInSoft)
+   * Fixed potential overflow in certificate size verification in
+     ssl_write_certificate() (found by TrustInSoft)
+   * Fix ASM format in bn_mul.h
+   * Potential memory leak in bignum_selftest()
+   * Replaced expired test certificate
+   * ssl_mail_client now terminates lines with CRLF, instead of LF
+   * Fix bug in RSA PKCS#1 v1.5 "reversed" operations
+   * Fixed testing with out-of-source builds using cmake
+   * Fixed version-major intolerance in server
+   * Fixed CMake symlinking on out-of-source builds
+   * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by
+     Alex Wilson.)
+   * ssl_init() was leaving a dirty pointer in ssl_context if malloc of
+     out_ctr failed
+   * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc
+     of one of them failed
+   * x509_get_current_time() uses localtime_r() to prevent thread issues
+   * Some example server programs were not sending the close_notify alert.
+   * Potential memory leak in mpi_exp_mod() when error occurs during
+     calculation of RR.
+   * Improve interoperability by not writing extension length in ClientHello
+     when no extensions are present (found by Matthew Page)
+   * rsa_check_pubkey() now allows an E up to N
+   * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings
+   * mpi_fill_random() was creating numbers larger than requested on
+     big-endian platform when size was not an integer number of limbs
+   * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer)
+   * Stricter check on SSL ClientHello internal sizes compared to actual packet
+     size (found by TrustInSoft)
+   * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan).
+   * Use \n\t rather than semicolons for bn_mul asm, since some assemblers
+     interpret semicolons as comment delimiters (found by Barry K. Nathan).
+   * Disable broken Sparc64 bn_mul assembly (found by Florian Obser).
+   * Fix base64_decode() to return and check length correctly (in case of
+     tight buffers)
+
 = Version 1.2.10 released 2013-10-07
 Changes
    * Changed RSA blinding to a slower but thread-safe version
index 52286157e163e76875d9aeaaac9ea2c9e1d5ba65..8dd823c9c2f1c19b63b732f02786088ae1da9311 100644 (file)
@@ -9,7 +9,7 @@ There are currently three active build systems within the PolarSSL releases:
 
 - Make
 - CMake
-- Microsoft Visual Studio
+- Microsoft Visual Studio (Visual Studio 6 and Visual Studio 2010)
 
 The main system used for development is CMake. That system is always the most up-to-date. The others should reflect all changes present in the CMake build system, but some features are not ported there by default.
 
@@ -18,11 +18,11 @@ Make
 
 We intentionally only use the absolute minimum of **Make** functionality, as we have discovered that a lot of **Make** features are not supported on all different implementations of Make on different platforms. As such, the Makefiles sometimes require some handwork or `export` statements in order to work for your platform.
 
-In order to build the source using Make, just enter at the command line:
+In order to build the source using Make, just enter at the command line::
 
     make
 
-In order to run the tests, enter:
+In order to run the tests, enter::
 
     make check
 
@@ -33,13 +33,13 @@ In case you find that you need to do something else as well, please let us know
 CMake
 -----
 
-In order to build the source using CMake, just enter at the command line:
+In order to build the source using CMake, just enter at the command line::
 
     cmake .
 
     make
 
-There are 3 different active build modes specified within the CMake buildsystem:
+There are 5 different active build modes specified within the CMake buildsystem:
 
 - Release.
   This generates the default code without any unnecessary information in the binary files.
@@ -47,19 +47,23 @@ There are 3 different active build modes specified within the CMake buildsystem:
   This generates debug information and disables optimization of the code.
 - Coverage.
   This generates code coverage information in addition to debug information.
+- ASan.
+  This instruments the code with AddressSanitizer to check for memory errors.
+- Check.
+  This activates more compiler warnings and treats them as errors.
 
 Switching build modes in CMake is simple. For debug mode, enter at the command line:
 
     cmake -D CMAKE_BUILD_TYPE:String="Debug" .
 
-In order to run the tests, enter:
+In order to run the tests, enter::
 
     make test
 
 Microsoft Visual Studio
 -----------------------
 
-The build files for Microsoft Visual Studio are generated for Visual Studio 6.0 all future Visual Studio's should be able to open and use this older version of the build files.
+The build files for Microsoft Visual Studio are generated for Visual Studio 6.0 and Visual Studio 2010.
 
 The workspace 'polarssl.dsw' contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need a perl environment as well.
 
@@ -71,11 +75,24 @@ We've included example programs for a lot of different features and uses in *pro
 Tests
 =====
 
-PolarSSL includes a elaborate test suite in *tests/* that initially requires Perl to generate the tests files (e.g. *test_suite_mpi.c*). These files are generates from a **function file** (e.g. *suites/test_suite_mpi.function*) and a **data file** (e.g. *suites/test_suite_mpi.data*). The **function file** contains the template for each test function. The **data file** contains the test cases, specified as parameters that should be pushed into a template function.
+PolarSSL includes an elaborate test suite in *tests/* that initially requires Perl to generate the tests files (e.g. *test_suite_mpi.c*). These files are generates from a **function file** (e.g. *suites/test_suite_mpi.function*) and a **data file** (e.g. *suites/test_suite_mpi.data*). The **function file** contains the template for each test function. The **data file** contains the test cases, specified as parameters that should be pushed into a template function.
+
+Configurations
+==============
+
+We provide some non-standard configurations focused on specific use cases in the configs/ directory. You can read more about those in configs/README.txt
 
 Contributing
 ============
 
+We graciously accept bugs and contributions from the community. There are some requirements we need to fulfil in order to be able to integrate contributions in the main code.
+
+Simple bug fixes to existing code do not contain copyright themselves and we can integrate those without any issue. The same goes for trivial contributions.
+
+For larger contributions, e.g. a new feature, the code possible falls under copyright law. We then need your consent to share in the ownership of the copyright. We have a form for that, which we will mail to you in case you submit a contribution or pull request that we deem this necessary for.
+
+Process
+-------
 #. `Check for open issues <https://github.com/polarssl/polarssl/issues>`_ or
    `start a discussion <https://polarssl.org/discussions>`_ around a feature
    idea or a bug.
index 1b93e2a3dbc83f889dff608ff3885cc64efb3821..2e9092f95ce63ba41acafc64c81533f77ed37c1a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief AES block cipher
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_AES_H
 #define POLARSSL_AES_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -38,6 +42,7 @@ typedef UINT32 uint32_t;
 #include <inttypes.h>
 #endif
 
+/* padlock.c and aesni.c rely on these values! */
 #define AES_ENCRYPT     1
 #define AES_DECRYPT     0
 
@@ -54,6 +59,11 @@ extern "C" {
 
 /**
  * \brief          AES context structure
+ *
+ * \note           buf is able to hold 32 extra bytes, which can be used:
+ *                 - for alignment purposes if VIA padlock is used, and/or
+ *                 - to simplify key expansion in the 256-bit case by
+ *                 generating an extra round key
  */
 typedef struct
 {
@@ -63,6 +73,20 @@ typedef struct
 }
 aes_context;
 
+/**
+ * \brief          Initialize AES context
+ *
+ * \param ctx      AES context to be initialized
+ */
+void aes_init( aes_context *ctx );
+
+/**
+ * \brief          Clear AES context
+ *
+ * \param ctx      AES context to be cleared
+ */
+void aes_free( aes_context *ctx );
+
 /**
  * \brief          AES key schedule (encryption)
  *
@@ -72,7 +96,8 @@ aes_context;
  *
  * \return         0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
  */
-int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize );
 
 /**
  * \brief          AES key schedule (decryption)
@@ -83,7 +108,8 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
  *
  * \return         0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
  */
-int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize );
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize );
 
 /**
  * \brief          AES-ECB block encryption/decryption
@@ -123,6 +149,7 @@ int aes_crypt_cbc( aes_context *ctx,
                     unsigned char *output );
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 
+#if defined(POLARSSL_CIPHER_MODE_CFB)
 /**
  * \brief          AES-CFB128 buffer encryption/decryption.
  *
@@ -148,6 +175,31 @@ int aes_crypt_cfb128( aes_context *ctx,
                        const unsigned char *input,
                        unsigned char *output );
 
+/**
+ * \brief          AES-CFB8 buffer encryption/decryption.
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful
+ */
+int aes_crypt_cfb8( aes_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[16],
+                    const unsigned char *input,
+                    unsigned char *output );
+#endif /*POLARSSL_CIPHER_MODE_CFB */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
 /**
  * \brief               AES-CTR buffer encryption/decryption
  *
@@ -177,6 +229,7 @@ int aes_crypt_ctr( aes_context *ctx,
                        unsigned char stream_block[16],
                        const unsigned char *input,
                        unsigned char *output );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
 
 #ifdef __cplusplus
 }
diff --git a/pdns/ext/polarssl/include/polarssl/aesni.h b/pdns/ext/polarssl/include/polarssl/aesni.h
new file mode 100644 (file)
index 0000000..92b23cd
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * \file aesni.h
+ *
+ * \brief AES-NI for hardware AES acceleration on some Intel processors
+ *
+ *  Copyright (C) 2013, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_AESNI_H
+#define POLARSSL_AESNI_H
+
+#include "aes.h"
+
+#define POLARSSL_AESNI_AES      0x02000000u
+#define POLARSSL_AESNI_CLMUL    0x00000002u
+
+#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) &&  \
+    ( defined(__amd64__) || defined(__x86_64__) )   &&  \
+    ! defined(POLARSSL_HAVE_X86_64)
+#define POLARSSL_HAVE_X86_64
+#endif
+
+#if defined(POLARSSL_HAVE_X86_64)
+
+/**
+ * \brief          AES-NI features detection routine
+ *
+ * \param what     The feature to detect
+ *                 (POLARSSL_AESNI_AES or POLARSSL_AESNI_CLMUL)
+ *
+ * \return         1 if CPU has support for the feature, 0 otherwise
+ */
+int aesni_supports( unsigned int what );
+
+/**
+ * \brief          AES-NI AES-ECB block en(de)cryption
+ *
+ * \param ctx      AES context
+ * \param mode     AES_ENCRYPT or AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 on success (cannot fail)
+ */
+int aesni_crypt_ecb( aes_context *ctx,
+                     int mode,
+                     const unsigned char input[16],
+                     unsigned char output[16] );
+
+/**
+ * \brief          GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \param c        Result
+ * \param a        First operand
+ * \param b        Second operand
+ *
+ * \note           Both operands and result are bit strings interpreted as
+ *                 elements of GF(2^128) as per the GCM spec.
+ */
+void aesni_gcm_mult( unsigned char c[16],
+                     const unsigned char a[16],
+                     const unsigned char b[16] );
+
+/**
+ * \brief           Compute decryption round keys from encryption round keys
+ *
+ * \param invkey    Round keys for the equivalent inverse cipher
+ * \param fwdkey    Original round keys (for encryption)
+ * \param nr        Number of rounds (that is, number of round keys minus one)
+ */
+void aesni_inverse_key( unsigned char *invkey,
+                        const unsigned char *fwdkey, int nr );
+
+/**
+ * \brief           Perform key expansion (for encryption)
+ *
+ * \param rk        Destination buffer where the round keys are written
+ * \param key       Encryption key
+ * \param bits      Key size in bits (must be 128, 192 or 256)
+ *
+ * \return          0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ */
+int aesni_setkey_enc( unsigned char *rk,
+                      const unsigned char *key,
+                      size_t bits );
+
+#endif /* POLARSSL_HAVE_X86_64 */
+
+#endif /* POLARSSL_AESNI_H */
index 9333265d383ffe6ad3bf1854d4548dc2fff53620..555f54fab3ebe075fae06fe5189450ef24ccc9ae 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief The ARCFOUR stream cipher
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_ARC4_H
 #define POLARSSL_ARC4_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -51,13 +55,28 @@ typedef struct
 arc4_context;
 
 /**
- * \brief          ARC4 key schedule
+ * \brief          Initialize ARC4 context
  *
  * \param ctx      ARC4 context to be initialized
+ */
+void arc4_init( arc4_context *ctx );
+
+/**
+ * \brief          Clear ARC4 context
+ *
+ * \param ctx      ARC4 context to be cleared
+ */
+void arc4_free( arc4_context *ctx );
+
+/**
+ * \brief          ARC4 key schedule
+ *
+ * \param ctx      ARC4 context to be setup
  * \param key      the secret key
  * \param keylen   length of the key, in bytes
  */
-void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen );
+void arc4_setup( arc4_context *ctx, const unsigned char *key,
+                 unsigned int keylen );
 
 /**
  * \brief          ARC4 cipher function
index 45fd6cd87755fc7186bc5f6ae4f28518ebd5e247..eacdd082bde59ffe1f376caac1cb1c3d9820d5b5 100644 (file)
 #ifndef POLARSSL_ASN1_H
 #define POLARSSL_ASN1_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_BIGNUM_C)
 #include "bignum.h"
 
 #include <string.h>
 
-/** 
+/**
  * \addtogroup asn1_module
- * \{ 
+ * \{
  */
+
 /**
  * \name ASN1 Error codes
  * These error codes are OR'ed to X509 error codes for
- * higher error granularity. 
+ * higher error granularity.
  * ASN1 is a standard to specify data structures.
  * \{
  */
 /** Returns the size of the binary string, without the trailing \\0 */
 #define OID_SIZE(x) (sizeof(x) - 1)
 
-/** Compares two asn1_buf structures for the same OID. Only works for
- *  'defined' oid_str values (OID_HMAC_SHA1), you cannot use a 'unsigned
- *  char *oid' here!
+/**
+ * Compares an asn1_buf structure to a reference OID.
+ *
+ * Only works for 'defined' oid_str values (OID_HMAC_SHA1), you cannot use a
+ * 'unsigned char *oid' here!
+ *
+ * Warning: returns true when the OIDs are equal (unlike memcmp)!
  */
 #define OID_CMP(oid_str, oid_buf)                                   \
         ( ( OID_SIZE(oid_str) == (oid_buf)->len ) &&                \
@@ -270,7 +278,7 @@ int asn1_get_sequence_of( unsigned char **p,
 int asn1_get_mpi( unsigned char **p,
                   const unsigned char *end,
                   mpi *X );
-#endif
+#endif /* POLARSSL_BIGNUM_C */
 
 /**
  * \brief       Retrieve an AlgorithmIdentifier ASN.1 sequence.
index d7f7b521a2606ff218ddd311d5608222561db666..7a7fbf7b3f24122b69381c15617e5141dd2cf977 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief ASN.1 buffer writing functionality
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -29,7 +29,8 @@
 
 #include "asn1.h"
 
-#define ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else g += ret; } while( 0 )
+#define ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else   \
+                                g += ret; } while( 0 )
 
 #ifdef __cplusplus
 extern "C" {
@@ -57,7 +58,8 @@ int asn1_write_len( unsigned char **p, unsigned char *start, size_t len );
  *
  * \return          the length written or a negative error code
  */
-int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag );
+int asn1_write_tag( unsigned char **p, unsigned char *start,
+                    unsigned char tag );
 
 /**
  * \brief           Write raw buffer data
@@ -85,7 +87,7 @@ int asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
  * \return          the length written or a negative error code
  */
 int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X );
-#endif
+#endif /* POLARSSL_BIGNUM_C */
 
 /**
  * \brief           Write a NULL tag (ASN1_NULL) with zero data in ASN.1 format
index 9bed027d92c8b65e6ddd52d25d2e4ab04061327d..cd7592c4fbb079e3a4e3aba1a9eab76cccdcd69f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief  Multi-precision integer library
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #include <stdio.h>
 #include <string.h>
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
 #include <basetsd.h>
@@ -47,7 +51,7 @@ typedef UINT32 uint32_t;
 typedef UINT64 uint64_t;
 #else
 #include <inttypes.h>
-#endif
+#endif /* _MSC_VER && !EFIX64 && !EFI32 */
 
 #define POLARSSL_ERR_MPI_FILE_IO_ERROR                     -0x0002  /**< An error occurred while reading from or writing to a file. */
 #define POLARSSL_ERR_MPI_BAD_INPUT_DATA                    -0x0004  /**< Bad input parameters to function. */
@@ -58,14 +62,14 @@ typedef UINT64 uint64_t;
 #define POLARSSL_ERR_MPI_NOT_ACCEPTABLE                    -0x000E  /**< The input arguments are not acceptable. */
 #define POLARSSL_ERR_MPI_MALLOC_FAILED                     -0x0010  /**< Memory allocation failed. */
 
-#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
+#define MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 )
 
 /*
  * Maximum size MPIs are allowed to grow to in number of limbs.
  */
 #define POLARSSL_MPI_MAX_LIMBS                             10000
 
-#if !defined(POLARSSL_CONFIG_OPTIONS)
+#if !defined(POLARSSL_MPI_WINDOW_SIZE)
 /*
  * Maximum window size used for modular exponentiation. Default: 6
  * Minimum value: 1. Maximum value: 6.
@@ -76,7 +80,9 @@ typedef UINT64 uint64_t;
  * Reduction in size, reduces speed.
  */
 #define POLARSSL_MPI_WINDOW_SIZE                           6        /**< Maximum windows size used. */
+#endif /* !POLARSSL_MPI_WINDOW_SIZE */
 
+#if !defined(POLARSSL_MPI_MAX_SIZE)
 /*
  * Maximum size of MPIs allowed in bits and bytes for user-MPIs.
  * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
@@ -85,8 +91,7 @@ typedef UINT64 uint64_t;
  * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher.
  */
 #define POLARSSL_MPI_MAX_SIZE                              512      /**< Maximum number of bytes for usable MPIs. */
-
-#endif /* !POLARSSL_CONFIG_OPTIONS */
+#endif /* !POLARSSL_MPI_MAX_SIZE */
 
 #define POLARSSL_MPI_MAX_BITS                              ( 8 * POLARSSL_MPI_MAX_SIZE )    /**< Maximum number of bits for usable MPIs. */
 
@@ -127,12 +132,18 @@ typedef uint16_t t_uint;
 typedef uint32_t t_udbl;
 #define POLARSSL_HAVE_UDBL
 #else
-  #if ( defined(_MSC_VER) && defined(_M_AMD64) )
+  /*
+   * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes)
+   * by defining POLARSSL_HAVE_INT32 and undefining POLARSSL_HAVE_ASM
+   */
+  #if ( ! defined(POLARSSL_HAVE_INT32) && \
+          defined(_MSC_VER) && defined(_M_AMD64) )
     #define POLARSSL_HAVE_INT64
     typedef  int64_t t_sint;
     typedef uint64_t t_uint;
   #else
-    #if ( defined(__GNUC__) && (                          \
+    #if ( ! defined(POLARSSL_HAVE_INT32) &&               \
+          defined(__GNUC__) && (                          \
           defined(__amd64__) || defined(__x86_64__)    || \
           defined(__ppc64__) || defined(__powerpc64__) || \
           defined(__ia64__)  || defined(__alpha__)     || \
@@ -156,8 +167,8 @@ typedef uint32_t t_udbl;
            #define POLARSSL_HAVE_UDBL
          #endif
        #endif
-    #endif
-  #endif
+    #endif /* !POLARSSL_HAVE_INT32 && __GNUC__ && 64-bit platform */
+  #endif /* !POLARSSL_HAVE_INT32 && _MSC_VER && _M_AMD64 */
 #endif /* POLARSSL_HAVE_INT16 */
 #endif /* POLARSSL_HAVE_INT8  */
 
@@ -201,6 +212,17 @@ void mpi_free( mpi *X );
  */
 int mpi_grow( mpi *X, size_t nblimbs );
 
+/**
+ * \brief          Resize down, keeping at least the specified number of limbs
+ *
+ * \param X        MPI to shrink
+ * \param nblimbs  The minimum number of limbs to keep
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ */
+int mpi_shrink( mpi *X, size_t nblimbs );
+
 /**
  * \brief          Copy the contents of Y into X
  *
@@ -220,6 +242,44 @@ int mpi_copy( mpi *X, const mpi *Y );
  */
 void mpi_swap( mpi *X, mpi *Y );
 
+/**
+ * \brief          Safe conditional assignement X = Y if assign is 1
+ *
+ * \param X        MPI to conditionally assign to
+ * \param Y        Value to be assigned
+ * \param assign   1: perform the assignment, 0: keep X's original value
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *
+ * \note           This function is equivalent to
+ *                      if( assign ) mpi_copy( X, Y );
+ *                 except that it avoids leaking any information about whether
+ *                 the assignment was done or not (the above code may leak
+ *                 information through branch prediction and/or memory access
+ *                 patterns analysis).
+ */
+int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign );
+
+/**
+ * \brief          Safe conditional swap X <-> Y if swap is 1
+ *
+ * \param X        First mpi value
+ * \param Y        Second mpi value
+ * \param assign   1: perform the swap, 0: keep X and Y's original values
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *
+ * \note           This function is equivalent to
+ *                      if( assign ) mpi_swap( X, Y );
+ *                 except that it avoids leaking any information about whether
+ *                 the assignment was done or not (the above code may leak
+ *                 information through branch prediction and/or memory access
+ *                 patterns analysis).
+ */
+int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char assign );
+
 /**
  * \brief          Set value from integer
  *
@@ -354,7 +414,9 @@ int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
 int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen );
 
 /**
- * \brief          Export X into unsigned binary data, big endian
+ * \brief          Export X into unsigned binary data, big endian.
+ *                 Always fills the whole buffer, which will start with zeros
+ *                 if the number is smaller.
  *
  * \param X        Source MPI
  * \param buf      Output buffer
@@ -509,8 +571,9 @@ int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
 
 /**
  * \brief          Baseline multiplication: X = A * b
- *                 Note: b is an unsigned integer type, thus
- *                 Negative values of b are ignored.
+ *                 Note: despite the functon signature, b is treated as a
+ *                 t_uint.  Negative values of b are treated as large positive
+ *                 values.
  *
  * \param X        Destination MPI
  * \param A        Left-hand MPI
@@ -584,7 +647,7 @@ int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
 /**
  * \brief          Sliding-window exponentiation: X = A^E mod N
  *
- * \param X        Destination MPI 
+ * \param X        Destination MPI
  * \param A        Left-hand MPI
  * \param E        Exponent MPI
  * \param N        Modular MPI
@@ -592,8 +655,8 @@ int mpi_mod_int( t_uint *r, const mpi *A, t_sint b );
  *
  * \return         0 if successful,
  *                 POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
- *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or if
- *                 E is negative
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or
+ *                 if E is negative
  *
  * \note           _RR is used to avoid re-computing R*R mod N across
  *                 multiple calls, which speeds up things a bit. It can
@@ -661,7 +724,8 @@ int mpi_is_prime( mpi *X,
  * \brief          Prime number generation
  *
  * \param X        Destination MPI
- * \param nbits    Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS )
+ * \param nbits    Required size of X in bits
+ *                 ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS )
  * \param dh_flag  If 1, then (X-1)/2 will be prime too
  * \param f_rng    RNG function
  * \param p_rng    RNG parameter
index 45b138764a1d8947a3b376dd2e81edde02457e8d..c652b463d1d81bc320dc04b7a696ce3728946e5b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief Blowfish block cipher
  *
- *  Copyright (C) 2012-2013, Brainspark B.V.
+ *  Copyright (C) 2012-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_BLOWFISH_H
 #define POLARSSL_BLOWFISH_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -42,7 +46,7 @@ typedef UINT32 uint32_t;
 #define BLOWFISH_DECRYPT     0
 #define BLOWFISH_MAX_KEY     448
 #define BLOWFISH_MIN_KEY     32
-#define BLOWFISH_ROUNDS      16         /* when increasing this value, make sure to extend the initialisation vectors */
+#define BLOWFISH_ROUNDS      16         /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */
 #define BLOWFISH_BLOCKSIZE   8          /* Blowfish uses 64 bit blocks */
 
 #define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH                -0x0016  /**< Invalid key length. */
@@ -66,6 +70,20 @@ typedef struct
 }
 blowfish_context;
 
+/**
+ * \brief          Initialize Blowfish context
+ *
+ * \param ctx      Blowfish context to be initialized
+ */
+void blowfish_init( blowfish_context *ctx );
+
+/**
+ * \brief          Clear Blowfish context
+ *
+ * \param ctx      Blowfish context to be cleared
+ */
+void blowfish_free( blowfish_context *ctx );
+
 /**
  * \brief          Blowfish key schedule
  *
@@ -75,7 +93,8 @@ blowfish_context;
  *
  * \return         0 if successful, or POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH
  */
-int blowfish_setkey( blowfish_context *ctx, const unsigned char *key, unsigned int keysize );
+int blowfish_setkey( blowfish_context *ctx, const unsigned char *key,
+                     unsigned int keysize );
 
 /**
  * \brief          Blowfish-ECB block encryption/decryption
@@ -105,7 +124,8 @@ int blowfish_crypt_ecb( blowfish_context *ctx,
  * \param input    buffer holding the input data
  * \param output   buffer holding the output data
  *
- * \return         0 if successful, or POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH
+ * \return         0 if successful, or
+ *                 POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH
  */
 int blowfish_crypt_cbc( blowfish_context *ctx,
                         int mode,
index 1c2da136ab1df3e60cdac5d4dc4c366e95a54538..64b59ff1e35f8437b5ab107d5a242604608e8dbe 100644 (file)
 #if defined(__GNUC__)
 #if defined(__i386__)
 
-#define MULADDC_INIT                \
-    asm( "                          \
-        movl   %%ebx, %0;           \
-        movl   %5, %%esi;           \
-        movl   %6, %%edi;           \
-        movl   %7, %%ecx;           \
-        movl   %8, %%ebx;           \
-        "
-
-#define MULADDC_CORE                \
-        "                           \
-        lodsl;                      \
-        mull   %%ebx;               \
-        addl   %%ecx,   %%eax;      \
-        adcl   $0,      %%edx;      \
-        addl   (%%edi), %%eax;      \
-        adcl   $0,      %%edx;      \
-        movl   %%edx,   %%ecx;      \
-        stosl;                      \
-        "
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "movl   %%ebx, %0           \n\t"   \
+        "movl   %5, %%esi           \n\t"   \
+        "movl   %6, %%edi           \n\t"   \
+        "movl   %7, %%ecx           \n\t"   \
+        "movl   %8, %%ebx           \n\t"
+
+#define MULADDC_CORE                        \
+        "lodsl                      \n\t"   \
+        "mull   %%ebx               \n\t"   \
+        "addl   %%ecx,   %%eax      \n\t"   \
+        "adcl   $0,      %%edx      \n\t"   \
+        "addl   (%%edi), %%eax      \n\t"   \
+        "adcl   $0,      %%edx      \n\t"   \
+        "movl   %%edx,   %%ecx      \n\t"   \
+        "stosl                      \n\t"
 
 #if defined(POLARSSL_HAVE_SSE2)
 
-#define MULADDC_HUIT                    \
-        "                               \
-        movd     %%ecx,     %%mm1;      \
-        movd     %%ebx,     %%mm0;      \
-        movd     (%%edi),   %%mm3;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     (%%esi),   %%mm2;      \
-        pmuludq  %%mm0,     %%mm2;      \
-        movd     4(%%esi),  %%mm4;      \
-        pmuludq  %%mm0,     %%mm4;      \
-        movd     8(%%esi),  %%mm6;      \
-        pmuludq  %%mm0,     %%mm6;      \
-        movd     12(%%esi), %%mm7;      \
-        pmuludq  %%mm0,     %%mm7;      \
-        paddq    %%mm2,     %%mm1;      \
-        movd     4(%%edi),  %%mm3;      \
-        paddq    %%mm4,     %%mm3;      \
-        movd     8(%%edi),  %%mm5;      \
-        paddq    %%mm6,     %%mm5;      \
-        movd     12(%%edi), %%mm4;      \
-        paddq    %%mm4,     %%mm7;      \
-        movd     %%mm1,     (%%edi);    \
-        movd     16(%%esi), %%mm2;      \
-        pmuludq  %%mm0,     %%mm2;      \
-        psrlq    $32,       %%mm1;      \
-        movd     20(%%esi), %%mm4;      \
-        pmuludq  %%mm0,     %%mm4;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     24(%%esi), %%mm6;      \
-        pmuludq  %%mm0,     %%mm6;      \
-        movd     %%mm1,     4(%%edi);   \
-        psrlq    $32,       %%mm1;      \
-        movd     28(%%esi), %%mm3;      \
-        pmuludq  %%mm0,     %%mm3;      \
-        paddq    %%mm5,     %%mm1;      \
-        movd     16(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm2;      \
-        movd     %%mm1,     8(%%edi);   \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm7,     %%mm1;      \
-        movd     20(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm4;      \
-        movd     %%mm1,     12(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm2,     %%mm1;      \
-        movd     24(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm6;      \
-        movd     %%mm1,     16(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm4,     %%mm1;      \
-        movd     28(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm3;      \
-        movd     %%mm1,     20(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm6,     %%mm1;      \
-        movd     %%mm1,     24(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     %%mm1,     28(%%edi);  \
-        addl     $32,       %%edi;      \
-        addl     $32,       %%esi;      \
-        psrlq    $32,       %%mm1;      \
-        movd     %%mm1,     %%ecx;      \
-        "
-
-#define MULADDC_STOP            \
-        "                       \
-        emms;                   \
-        movl   %4, %%ebx;       \
-        movl   %%ecx, %1;       \
-        movl   %%edi, %2;       \
-        movl   %%esi, %3;       \
-        "                       \
+#define MULADDC_HUIT                            \
+        "movd     %%ecx,     %%mm1      \n\t"   \
+        "movd     %%ebx,     %%mm0      \n\t"   \
+        "movd     (%%edi),   %%mm3      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     (%%esi),   %%mm2      \n\t"   \
+        "pmuludq  %%mm0,     %%mm2      \n\t"   \
+        "movd     4(%%esi),  %%mm4      \n\t"   \
+        "pmuludq  %%mm0,     %%mm4      \n\t"   \
+        "movd     8(%%esi),  %%mm6      \n\t"   \
+        "pmuludq  %%mm0,     %%mm6      \n\t"   \
+        "movd     12(%%esi), %%mm7      \n\t"   \
+        "pmuludq  %%mm0,     %%mm7      \n\t"   \
+        "paddq    %%mm2,     %%mm1      \n\t"   \
+        "movd     4(%%edi),  %%mm3      \n\t"   \
+        "paddq    %%mm4,     %%mm3      \n\t"   \
+        "movd     8(%%edi),  %%mm5      \n\t"   \
+        "paddq    %%mm6,     %%mm5      \n\t"   \
+        "movd     12(%%edi), %%mm4      \n\t"   \
+        "paddq    %%mm4,     %%mm7      \n\t"   \
+        "movd     %%mm1,     (%%edi)    \n\t"   \
+        "movd     16(%%esi), %%mm2      \n\t"   \
+        "pmuludq  %%mm0,     %%mm2      \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     20(%%esi), %%mm4      \n\t"   \
+        "pmuludq  %%mm0,     %%mm4      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     24(%%esi), %%mm6      \n\t"   \
+        "pmuludq  %%mm0,     %%mm6      \n\t"   \
+        "movd     %%mm1,     4(%%edi)   \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     28(%%esi), %%mm3      \n\t"   \
+        "pmuludq  %%mm0,     %%mm3      \n\t"   \
+        "paddq    %%mm5,     %%mm1      \n\t"   \
+        "movd     16(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm2      \n\t"   \
+        "movd     %%mm1,     8(%%edi)   \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm7,     %%mm1      \n\t"   \
+        "movd     20(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm4      \n\t"   \
+        "movd     %%mm1,     12(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm2,     %%mm1      \n\t"   \
+        "movd     24(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm6      \n\t"   \
+        "movd     %%mm1,     16(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm4,     %%mm1      \n\t"   \
+        "movd     28(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm3      \n\t"   \
+        "movd     %%mm1,     20(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm6,     %%mm1      \n\t"   \
+        "movd     %%mm1,     24(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     %%mm1,     28(%%edi)  \n\t"   \
+        "addl     $32,       %%edi      \n\t"   \
+        "addl     $32,       %%esi      \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     %%mm1,     %%ecx      \n\t"
+
+#define MULADDC_STOP                    \
+        "emms                   \n\t"   \
+        "movl   %4, %%ebx       \n\t"   \
+        "movl   %%ecx, %1       \n\t"   \
+        "movl   %%edi, %2       \n\t"   \
+        "movl   %%esi, %3       \n\t"   \
         : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
         : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
         : "eax", "ecx", "edx", "esi", "edi"             \
 
 #else
 
-#define MULADDC_STOP            \
-        "                       \
-        movl   %4, %%ebx;       \
-        movl   %%ecx, %1;       \
-        movl   %%edi, %2;       \
-        movl   %%esi, %3;       \
-        "                       \
+#define MULADDC_STOP                    \
+        "movl   %4, %%ebx       \n\t"   \
+        "movl   %%ecx, %1       \n\t"   \
+        "movl   %%edi, %2       \n\t"   \
+        "movl   %%esi, %3       \n\t"   \
         : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
         : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
         : "eax", "ecx", "edx", "esi", "edi"             \
 
 #if defined(__amd64__) || defined (__x86_64__)
 
-#define MULADDC_INIT                            \
-    asm( "movq   %0, %%rsi      " :: "m" (s));  \
-    asm( "movq   %0, %%rdi      " :: "m" (d));  \
-    asm( "movq   %0, %%rcx      " :: "m" (c));  \
-    asm( "movq   %0, %%rbx      " :: "m" (b));  \
-    asm( "xorq   %r8, %r8       " );
-
-#define MULADDC_CORE                            \
-    asm( "movq  (%rsi),%rax     " );            \
-    asm( "mulq   %rbx           " );            \
-    asm( "addq   $8,   %rsi     " );            \
-    asm( "addq   %rcx, %rax     " );            \
-    asm( "movq   %r8,  %rcx     " );            \
-    asm( "adcq   $0,   %rdx     " );            \
-    asm( "nop                   " );            \
-    asm( "addq   %rax, (%rdi)   " );            \
-    asm( "adcq   %rdx, %rcx     " );            \
-    asm( "addq   $8,   %rdi     " );
-
-#define MULADDC_STOP                            \
-    asm( "movq   %%rcx, %0      " : "=m" (c));  \
-    asm( "movq   %%rdi, %0      " : "=m" (d));  \
-    asm( "movq   %%rsi, %0      " : "=m" (s) :: \
-    "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "movq   %3, %%rsi           \n\t"   \
+        "movq   %4, %%rdi           \n\t"   \
+        "movq   %5, %%rcx           \n\t"   \
+        "movq   %6, %%rbx           \n\t"   \
+        "xorq   %%r8, %%r8          \n\t"
+
+#define MULADDC_CORE                        \
+        "movq   (%%rsi), %%rax      \n\t"   \
+        "mulq   %%rbx               \n\t"   \
+        "addq   $8,      %%rsi      \n\t"   \
+        "addq   %%rcx,   %%rax      \n\t"   \
+        "movq   %%r8,    %%rcx      \n\t"   \
+        "adcq   $0,      %%rdx      \n\t"   \
+        "nop                        \n\t"   \
+        "addq   %%rax,   (%%rdi)    \n\t"   \
+        "adcq   %%rdx,   %%rcx      \n\t"   \
+        "addq   $8,      %%rdi      \n\t"
+
+#define MULADDC_STOP                        \
+        "movq   %%rcx, %0           \n\t"   \
+        "movq   %%rdi, %1           \n\t"   \
+        "movq   %%rsi, %2           \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)                      \
+        : "m" (s), "m" (d), "m" (c), "m" (b)                \
+        : "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8"    \
+    );
 
 #endif /* AMD64 */
 
 #if defined(__mc68020__) || defined(__mcpu32__)
 
-#define MULADDC_INIT                            \
-    asm( "movl   %0, %%a2       " :: "m" (s));  \
-    asm( "movl   %0, %%a3       " :: "m" (d));  \
-    asm( "movl   %0, %%d3       " :: "m" (c));  \
-    asm( "movl   %0, %%d2       " :: "m" (b));  \
-    asm( "moveq  #0, %d0        " );
+#define MULADDC_INIT                    \
+    asm(                                \
+        "movl   %3, %%a2        \n\t"   \
+        "movl   %4, %%a3        \n\t"   \
+        "movl   %5, %%d3        \n\t"   \
+        "movl   %6, %%d2        \n\t"   \
+        "moveq  #0, %%d0        \n\t"
 
-#define MULADDC_CORE                            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addl   %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "moveq  #0,  %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "addxl  %d4, %d3       " );
+#define MULADDC_CORE                    \
+        "movel  %%a2@+, %%d1    \n\t"   \
+        "mulul  %%d2, %%d4:%%d1 \n\t"   \
+        "addl   %%d3, %%d1      \n\t"   \
+        "addxl  %%d0, %%d4      \n\t"   \
+        "moveq  #0,   %%d3      \n\t"   \
+        "addl   %%d1, %%a3@+    \n\t"   \
+        "addxl  %%d4, %%d3      \n\t"
 
-#define MULADDC_STOP                            \
-    asm( "movl   %%d3, %0       " : "=m" (c));  \
-    asm( "movl   %%a3, %0       " : "=m" (d));  \
-    asm( "movl   %%a2, %0       " : "=m" (s) :: \
-    "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
+#define MULADDC_STOP                    \
+        "movl   %%d3, %0        \n\t"   \
+        "movl   %%a3, %1        \n\t"   \
+        "movl   %%a2, %2        \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "d0", "d1", "d2", "d3", "d4", "a2", "a3"  \
+    );
 
-#define MULADDC_HUIT                            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "addxl  %d0, %d3       " );
+#define MULADDC_HUIT                        \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"
 
 #endif /* MC68000 */
 
-#if defined(__powerpc__)   || defined(__ppc__)
 #if defined(__powerpc64__) || defined(__ppc64__)
 
 #if defined(__MACH__) && defined(__APPLE__)
 
-#define MULADDC_INIT                            \
-    asm( "ld     r3, %0         " :: "m" (s));  \
-    asm( "ld     r4, %0         " :: "m" (d));  \
-    asm( "ld     r5, %0         " :: "m" (c));  \
-    asm( "ld     r6, %0         " :: "m" (b));  \
-    asm( "addi   r3, r3, -8     " );            \
-    asm( "addi   r4, r4, -8     " );            \
-    asm( "addic  r5, r5,  0     " );
-
-#define MULADDC_CORE                            \
-    asm( "ldu    r7, 8(r3)      " );            \
-    asm( "mulld  r8, r7, r6     " );            \
-    asm( "mulhdu r9, r7, r6     " );            \
-    asm( "adde   r8, r8, r5     " );            \
-    asm( "ld     r7, 8(r4)      " );            \
-    asm( "addze  r5, r9         " );            \
-    asm( "addc   r8, r8, r7     " );            \
-    asm( "stdu   r8, 8(r4)      " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  r5, r5         " );            \
-    asm( "addi   r4, r4, 8      " );            \
-    asm( "addi   r3, r3, 8      " );            \
-    asm( "std    r5, %0         " : "=m" (c));  \
-    asm( "std    r4, %0         " : "=m" (d));  \
-    asm( "std    r3, %0         " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#else
-
-#define MULADDC_INIT                            \
-    asm( "ld     %%r3, %0       " :: "m" (s));  \
-    asm( "ld     %%r4, %0       " :: "m" (d));  \
-    asm( "ld     %%r5, %0       " :: "m" (c));  \
-    asm( "ld     %%r6, %0       " :: "m" (b));  \
-    asm( "addi   %r3, %r3, -8   " );            \
-    asm( "addi   %r4, %r4, -8   " );            \
-    asm( "addic  %r5, %r5,  0   " );
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "ld     r3, %3              \n\t"   \
+        "ld     r4, %4              \n\t"   \
+        "ld     r5, %5              \n\t"   \
+        "ld     r6, %6              \n\t"   \
+        "addi   r3, r3, -8          \n\t"   \
+        "addi   r4, r4, -8          \n\t"   \
+        "addic  r5, r5,  0          \n\t"
+
+#define MULADDC_CORE                        \
+        "ldu    r7, 8(r3)           \n\t"   \
+        "mulld  r8, r7, r6          \n\t"   \
+        "mulhdu r9, r7, r6          \n\t"   \
+        "adde   r8, r8, r5          \n\t"   \
+        "ld     r7, 8(r4)           \n\t"   \
+        "addze  r5, r9              \n\t"   \
+        "addc   r8, r8, r7          \n\t"   \
+        "stdu   r8, 8(r4)           \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  r5, r5              \n\t"   \
+        "addi   r4, r4, 8           \n\t"   \
+        "addi   r3, r3, 8           \n\t"   \
+        "std    r5, %0              \n\t"   \
+        "std    r4, %1              \n\t"   \
+        "std    r3, %2              \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
 
-#define MULADDC_CORE                            \
-    asm( "ldu    %r7, 8(%r3)    " );            \
-    asm( "mulld  %r8, %r7, %r6  " );            \
-    asm( "mulhdu %r9, %r7, %r6  " );            \
-    asm( "adde   %r8, %r8, %r5  " );            \
-    asm( "ld     %r7, 8(%r4)    " );            \
-    asm( "addze  %r5, %r9       " );            \
-    asm( "addc   %r8, %r8, %r7  " );            \
-    asm( "stdu   %r8, 8(%r4)    " );
 
-#define MULADDC_STOP                            \
-    asm( "addze  %r5, %r5       " );            \
-    asm( "addi   %r4, %r4, 8    " );            \
-    asm( "addi   %r3, %r3, 8    " );            \
-    asm( "std    %%r5, %0       " : "=m" (c));  \
-    asm( "std    %%r4, %0       " : "=m" (d));  \
-    asm( "std    %%r3, %0       " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "ld     %%r3, %3            \n\t"   \
+        "ld     %%r4, %4            \n\t"   \
+        "ld     %%r5, %5            \n\t"   \
+        "ld     %%r6, %6            \n\t"   \
+        "addi   %%r3, %%r3, -8      \n\t"   \
+        "addi   %%r4, %%r4, -8      \n\t"   \
+        "addic  %%r5, %%r5,  0      \n\t"
+
+#define MULADDC_CORE                        \
+        "ldu    %%r7, 8(%%r3)       \n\t"   \
+        "mulld  %%r8, %%r7, %%r6    \n\t"   \
+        "mulhdu %%r9, %%r7, %%r6    \n\t"   \
+        "adde   %%r8, %%r8, %%r5    \n\t"   \
+        "ld     %%r7, 8(%%r4)       \n\t"   \
+        "addze  %%r5, %%r9          \n\t"   \
+        "addc   %%r8, %%r8, %%r7    \n\t"   \
+        "stdu   %%r8, 8(%%r4)       \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  %%r5, %%r5          \n\t"   \
+        "addi   %%r4, %%r4, 8       \n\t"   \
+        "addi   %%r3, %%r3, 8       \n\t"   \
+        "std    %%r5, %0            \n\t"   \
+        "std    %%r4, %1            \n\t"   \
+        "std    %%r3, %2            \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
 
-#endif
+#endif /* __MACH__ && __APPLE__ */
 
-#else /* PPC32 */
+#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32  */
 
 #if defined(__MACH__) && defined(__APPLE__)
 
-#define MULADDC_INIT                            \
-    asm( "lwz    r3, %0         " :: "m" (s));  \
-    asm( "lwz    r4, %0         " :: "m" (d));  \
-    asm( "lwz    r5, %0         " :: "m" (c));  \
-    asm( "lwz    r6, %0         " :: "m" (b));  \
-    asm( "addi   r3, r3, -4     " );            \
-    asm( "addi   r4, r4, -4     " );            \
-    asm( "addic  r5, r5,  0     " );
-
-#define MULADDC_CORE                            \
-    asm( "lwzu   r7, 4(r3)      " );            \
-    asm( "mullw  r8, r7, r6     " );            \
-    asm( "mulhwu r9, r7, r6     " );            \
-    asm( "adde   r8, r8, r5     " );            \
-    asm( "lwz    r7, 4(r4)      " );            \
-    asm( "addze  r5, r9         " );            \
-    asm( "addc   r8, r8, r7     " );            \
-    asm( "stwu   r8, 4(r4)      " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  r5, r5         " );            \
-    asm( "addi   r4, r4, 4      " );            \
-    asm( "addi   r3, r3, 4      " );            \
-    asm( "stw    r5, %0         " : "=m" (c));  \
-    asm( "stw    r4, %0         " : "=m" (d));  \
-    asm( "stw    r3, %0         " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#else
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lwz    r3, %3          \n\t"   \
+        "lwz    r4, %4          \n\t"   \
+        "lwz    r5, %5          \n\t"   \
+        "lwz    r6, %6          \n\t"   \
+        "addi   r3, r3, -4      \n\t"   \
+        "addi   r4, r4, -4      \n\t"   \
+        "addic  r5, r5,  0      \n\t"
 
-#define MULADDC_INIT                            \
-    asm( "lwz    %%r3, %0       " :: "m" (s));  \
-    asm( "lwz    %%r4, %0       " :: "m" (d));  \
-    asm( "lwz    %%r5, %0       " :: "m" (c));  \
-    asm( "lwz    %%r6, %0       " :: "m" (b));  \
-    asm( "addi   %r3, %r3, -4   " );            \
-    asm( "addi   %r4, %r4, -4   " );            \
-    asm( "addic  %r5, %r5,  0   " );
+#define MULADDC_CORE                    \
+        "lwzu   r7, 4(r3)       \n\t"   \
+        "mullw  r8, r7, r6      \n\t"   \
+        "mulhwu r9, r7, r6      \n\t"   \
+        "adde   r8, r8, r5      \n\t"   \
+        "lwz    r7, 4(r4)       \n\t"   \
+        "addze  r5, r9          \n\t"   \
+        "addc   r8, r8, r7      \n\t"   \
+        "stwu   r8, 4(r4)       \n\t"
 
-#define MULADDC_CORE                            \
-    asm( "lwzu   %r7, 4(%r3)    " );            \
-    asm( "mullw  %r8, %r7, %r6  " );            \
-    asm( "mulhwu %r9, %r7, %r6  " );            \
-    asm( "adde   %r8, %r8, %r5  " );            \
-    asm( "lwz    %r7, 4(%r4)    " );            \
-    asm( "addze  %r5, %r9       " );            \
-    asm( "addc   %r8, %r8, %r7  " );            \
-    asm( "stwu   %r8, 4(%r4)    " );
+#define MULADDC_STOP                    \
+        "addze  r5, r5          \n\t"   \
+        "addi   r4, r4, 4       \n\t"   \
+        "addi   r3, r3, 4       \n\t"   \
+        "stw    r5, %0          \n\t"   \
+        "stw    r4, %1          \n\t"   \
+        "stw    r3, %2          \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
 
-#define MULADDC_STOP                            \
-    asm( "addze  %r5, %r5       " );            \
-    asm( "addi   %r4, %r4, 4    " );            \
-    asm( "addi   %r3, %r3, 4    " );            \
-    asm( "stw    %%r5, %0       " : "=m" (c));  \
-    asm( "stw    %%r4, %0       " : "=m" (d));  \
-    asm( "stw    %%r3, %0       " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_INIT                        \
+    asm(                                    \
+        "lwz    %%r3, %3            \n\t"   \
+        "lwz    %%r4, %4            \n\t"   \
+        "lwz    %%r5, %5            \n\t"   \
+        "lwz    %%r6, %6            \n\t"   \
+        "addi   %%r3, %%r3, -4      \n\t"   \
+        "addi   %%r4, %%r4, -4      \n\t"   \
+        "addic  %%r5, %%r5,  0      \n\t"
+
+#define MULADDC_CORE                        \
+        "lwzu   %%r7, 4(%%r3)       \n\t"   \
+        "mullw  %%r8, %%r7, %%r6    \n\t"   \
+        "mulhwu %%r9, %%r7, %%r6    \n\t"   \
+        "adde   %%r8, %%r8, %%r5    \n\t"   \
+        "lwz    %%r7, 4(%%r4)       \n\t"   \
+        "addze  %%r5, %%r9          \n\t"   \
+        "addc   %%r8, %%r8, %%r7    \n\t"   \
+        "stwu   %%r8, 4(%%r4)       \n\t"
+
+#define MULADDC_STOP                        \
+        "addze  %%r5, %%r5          \n\t"   \
+        "addi   %%r4, %%r4, 4       \n\t"   \
+        "addi   %%r3, %%r3, 4       \n\t"   \
+        "stw    %%r5, %0            \n\t"   \
+        "stw    %%r4, %1            \n\t"   \
+        "stw    %%r3, %2            \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
 
-#endif
+#endif /* __MACH__ && __APPLE__ */
 
 #endif /* PPC32 */
-#endif /* PPC64 */
-
-#if defined(__sparc__) && defined(__sparc64__)
-
-#define MULADDC_INIT                            \
-    asm(                                        \
-         "                                      \
-                ldx     %3, %%o0;               \
-                ldx     %4, %%o1;               \
-                ld      %5, %%o2;               \
-                ld      %6, %%o3;               \
-         "
 
-#define MULADDC_CORE                            \
-         "                                      \
-                ld      [%%o0], %%o4;           \
-                inc     4, %%o0;                \
-                ld      [%%o1], %%o5;           \
-                umul    %%o3, %%o4, %%o4;       \
-                addcc   %%o4, %%o2, %%o4;       \
-                rd      %%y, %%g1;              \
-                addx    %%g1, 0, %%g1;          \
-                addcc   %%o4, %%o5, %%o4;       \
-                st      %%o4, [%%o1];           \
-                addx    %%g1, 0, %%o2;          \
-                inc     4, %%o1;                \
-        "
-
-#define MULADDC_STOP                            \
-        "                                       \
-                st      %%o2, %0;               \
-                stx     %%o1, %1;               \
-                stx     %%o0, %2;               \
-        "                                       \
+/*
+ * The Sparc64 assembly is reported to be broken.
+ * Disable it for now, until we're able to fix it.
+ */
+#if 0 && defined(__sparc__) && defined(__sparc64__)
+
+#define MULADDC_INIT                                    \
+    asm(                                                \
+                "ldx     %3, %%o0               \n\t"   \
+                "ldx     %4, %%o1               \n\t"   \
+                "ld      %5, %%o2               \n\t"   \
+                "ld      %6, %%o3               \n\t"
+
+#define MULADDC_CORE                                    \
+                "ld      [%%o0], %%o4           \n\t"   \
+                "inc     4, %%o0                \n\t"   \
+                "ld      [%%o1], %%o5           \n\t"   \
+                "umul    %%o3, %%o4, %%o4       \n\t"   \
+                "addcc   %%o4, %%o2, %%o4       \n\t"   \
+                "rd      %%y, %%g1              \n\t"   \
+                "addx    %%g1, 0, %%g1          \n\t"   \
+                "addcc   %%o4, %%o5, %%o4       \n\t"   \
+                "st      %%o4, [%%o1]           \n\t"   \
+                "addx    %%g1, 0, %%o2          \n\t"   \
+                "inc     4, %%o1                \n\t"
+
+        #define MULADDC_STOP                            \
+                "st      %%o2, %0               \n\t"   \
+                "stx     %%o1, %1               \n\t"   \
+                "stx     %%o0, %2               \n\t"   \
         : "=m" (c), "=m" (d), "=m" (s)          \
         : "m" (s), "m" (d), "m" (c), "m" (b)    \
         : "g1", "o0", "o1", "o2", "o3", "o4",   \
 
 #if defined(__sparc__) && !defined(__sparc64__)
 
-#define MULADDC_INIT                            \
-    asm(                                        \
-         "                                      \
-                ld      %3, %%o0;               \
-                ld      %4, %%o1;               \
-                ld      %5, %%o2;               \
-                ld      %6, %%o3;               \
-         "
-
-#define MULADDC_CORE                            \
-         "                                      \
-                ld      [%%o0], %%o4;           \
-                inc     4, %%o0;                \
-                ld      [%%o1], %%o5;           \
-                umul    %%o3, %%o4, %%o4;       \
-                addcc   %%o4, %%o2, %%o4;       \
-                rd      %%y, %%g1;              \
-                addx    %%g1, 0, %%g1;          \
-                addcc   %%o4, %%o5, %%o4;       \
-                st      %%o4, [%%o1];           \
-                addx    %%g1, 0, %%o2;          \
-                inc     4, %%o1;                \
-        "
-
-#define MULADDC_STOP                            \
-        "                                       \
-                st      %%o2, %0;               \
-                st      %%o1, %1;               \
-                st      %%o0, %2;               \
-        "                                       \
+#define MULADDC_INIT                                    \
+    asm(                                                \
+                "ld      %3, %%o0               \n\t"   \
+                "ld      %4, %%o1               \n\t"   \
+                "ld      %5, %%o2               \n\t"   \
+                "ld      %6, %%o3               \n\t"
+
+#define MULADDC_CORE                                    \
+                "ld      [%%o0], %%o4           \n\t"   \
+                "inc     4, %%o0                \n\t"   \
+                "ld      [%%o1], %%o5           \n\t"   \
+                "umul    %%o3, %%o4, %%o4       \n\t"   \
+                "addcc   %%o4, %%o2, %%o4       \n\t"   \
+                "rd      %%y, %%g1              \n\t"   \
+                "addx    %%g1, 0, %%g1          \n\t"   \
+                "addcc   %%o4, %%o5, %%o4       \n\t"   \
+                "st      %%o4, [%%o1]           \n\t"   \
+                "addx    %%g1, 0, %%o2          \n\t"   \
+                "inc     4, %%o1                \n\t"
+
+#define MULADDC_STOP                                    \
+                "st      %%o2, %0               \n\t"   \
+                "st      %%o1, %1               \n\t"   \
+                "st      %%o0, %2               \n\t"   \
         : "=m" (c), "=m" (d), "=m" (s)          \
         : "m" (s), "m" (d), "m" (c), "m" (b)    \
         : "g1", "o0", "o1", "o2", "o3", "o4",   \
 
 #if defined(__microblaze__) || defined(microblaze)
 
-#define MULADDC_INIT                            \
-    asm( "lwi   r3,   %0        " :: "m" (s));  \
-    asm( "lwi   r4,   %0        " :: "m" (d));  \
-    asm( "lwi   r5,   %0        " :: "m" (c));  \
-    asm( "lwi   r6,   %0        " :: "m" (b));  \
-    asm( "andi  r7,   r6, 0xffff" );            \
-    asm( "bsrli r6,   r6, 16    " );
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lwi   r3,   %3         \n\t"   \
+        "lwi   r4,   %4         \n\t"   \
+        "lwi   r5,   %5         \n\t"   \
+        "lwi   r6,   %6         \n\t"   \
+        "andi  r7,   r6, 0xffff \n\t"   \
+        "bsrli r6,   r6, 16     \n\t"
 
-#define MULADDC_CORE                            \
-    asm( "lhui  r8,   r3,   0   " );            \
-    asm( "addi  r3,   r3,   2   " );            \
-    asm( "lhui  r9,   r3,   0   " );            \
-    asm( "addi  r3,   r3,   2   " );            \
-    asm( "mul   r10,  r9,  r6   " );            \
-    asm( "mul   r11,  r8,  r7   " );            \
-    asm( "mul   r12,  r9,  r7   " );            \
-    asm( "mul   r13,  r8,  r6   " );            \
-    asm( "bsrli  r8, r10,  16   " );            \
-    asm( "bsrli  r9, r11,  16   " );            \
-    asm( "add   r13, r13,  r8   " );            \
-    asm( "add   r13, r13,  r9   " );            \
-    asm( "bslli r10, r10,  16   " );            \
-    asm( "bslli r11, r11,  16   " );            \
-    asm( "add   r12, r12, r10   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "add   r12, r12, r11   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "lwi   r10,  r4,   0   " );            \
-    asm( "add   r12, r12, r10   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "add   r12, r12,  r5   " );            \
-    asm( "addc   r5, r13,  r0   " );            \
-    asm( "swi   r12,  r4,   0   " );            \
-    asm( "addi   r4,  r4,   4   " );
+#define MULADDC_CORE                    \
+        "lhui  r8,   r3,   0    \n\t"   \
+        "addi  r3,   r3,   2    \n\t"   \
+        "lhui  r9,   r3,   0    \n\t"   \
+        "addi  r3,   r3,   2    \n\t"   \
+        "mul   r10,  r9,  r6    \n\t"   \
+        "mul   r11,  r8,  r7    \n\t"   \
+        "mul   r12,  r9,  r7    \n\t"   \
+        "mul   r13,  r8,  r6    \n\t"   \
+        "bsrli  r8, r10,  16    \n\t"   \
+        "bsrli  r9, r11,  16    \n\t"   \
+        "add   r13, r13,  r8    \n\t"   \
+        "add   r13, r13,  r9    \n\t"   \
+        "bslli r10, r10,  16    \n\t"   \
+        "bslli r11, r11,  16    \n\t"   \
+        "add   r12, r12, r10    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "add   r12, r12, r11    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "lwi   r10,  r4,   0    \n\t"   \
+        "add   r12, r12, r10    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "add   r12, r12,  r5    \n\t"   \
+        "addc   r5, r13,  r0    \n\t"   \
+        "swi   r12,  r4,   0    \n\t"   \
+        "addi   r4,  r4,   4    \n\t"
 
-#define MULADDC_STOP                            \
-    asm( "swi   r5,   %0        " : "=m" (c));  \
-    asm( "swi   r4,   %0        " : "=m" (d));  \
-    asm( "swi   r3,   %0        " : "=m" (s) :: \
-     "r3", "r4" , "r5" , "r6" , "r7" , "r8" ,   \
-     "r9", "r10", "r11", "r12", "r13" );
+#define MULADDC_STOP                    \
+        "swi   r5,   %0         \n\t"   \
+        "swi   r4,   %1         \n\t"   \
+        "swi   r3,   %2         \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4"  "r5", "r6", "r7", "r8",       \
+          "r9", "r10", "r11", "r12", "r13"          \
+    );
 
 #endif /* MicroBlaze */
 
 #if defined(__tricore__)
 
 #define MULADDC_INIT                            \
-    asm( "ld.a   %%a2, %0       " :: "m" (s));  \
-    asm( "ld.a   %%a3, %0       " :: "m" (d));  \
-    asm( "ld.w   %%d4, %0       " :: "m" (c));  \
-    asm( "ld.w   %%d1, %0       " :: "m" (b));  \
-    asm( "xor    %d5, %d5       " );
+    asm(                                        \
+        "ld.a   %%a2, %3                \n\t"   \
+        "ld.a   %%a3, %4                \n\t"   \
+        "ld.w   %%d4, %5                \n\t"   \
+        "ld.w   %%d1, %6                \n\t"   \
+        "xor    %%d5, %%d5              \n\t"
 
 #define MULADDC_CORE                            \
-    asm( "ld.w   %d0,   [%a2+]      " );        \
-    asm( "madd.u %e2, %e4, %d0, %d1 " );        \
-    asm( "ld.w   %d0,   [%a3]       " );        \
-    asm( "addx   %d2,    %d2,  %d0  " );        \
-    asm( "addc   %d3,    %d3,    0  " );        \
-    asm( "mov    %d4,    %d3        " );        \
-    asm( "st.w  [%a3+],  %d2        " );
+        "ld.w   %%d0,   [%%a2+]         \n\t"   \
+        "madd.u %%e2, %%e4, %%d0, %%d1  \n\t"   \
+        "ld.w   %%d0,   [%%a3]          \n\t"   \
+        "addx   %%d2,    %%d2,  %%d0    \n\t"   \
+        "addc   %%d3,    %%d3,    0     \n\t"   \
+        "mov    %%d4,    %%d3           \n\t"   \
+        "st.w  [%%a3+],  %%d2           \n\t"
 
 #define MULADDC_STOP                            \
-    asm( "st.w   %0, %%d4       " : "=m" (c));  \
-    asm( "st.a   %0, %%a3       " : "=m" (d));  \
-    asm( "st.a   %0, %%a2       " : "=m" (s) :: \
-    "d0", "d1", "e2", "d4", "a2", "a3" );
+        "st.w   %0, %%d4                \n\t"   \
+        "st.a   %1, %%a3                \n\t"   \
+        "st.a   %2, %%a2                \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "d0", "d1", "e2", "d4", "a2", "a3"    \
+    );
 
 #endif /* TriCore */
 
 
 #if defined(__thumb__) && !defined(__thumb2__)
 
-#define MULADDC_INIT                            \
-    asm(                                        \
-         "                                      \
-            ldr    r0, %3;                      \
-            ldr    r1, %4;                      \
-            ldr    r2, %5;                      \
-            ldr    r3, %6;                      \
-            lsr    r7, r3, #16;                 \
-            mov    r9, r7;                      \
-            lsl    r7, r3, #16;                 \
-            lsr    r7, r7, #16;                 \
-            mov    r8, r7;                      \
-         "
-
-#define MULADDC_CORE                            \
-         "                                      \
-            ldmia  r0!, {r6};                   \
-            lsr    r7, r6, #16;                 \
-            lsl    r6, r6, #16;                 \
-            lsr    r6, r6, #16;                 \
-            mov    r4, r8;                      \
-            mul    r4, r6;                      \
-            mov    r3, r9;                      \
-            mul    r6, r3;                      \
-            mov    r5, r9;                      \
-            mul    r5, r7;                      \
-            mov    r3, r8;                      \
-            mul    r7, r3;                      \
-            lsr    r3, r6, #16;                 \
-            add    r5, r5, r3;                  \
-            lsr    r3, r7, #16;                 \
-            add    r5, r5, r3;                  \
-            add    r4, r4, r2;                  \
-            mov    r2, #0;                      \
-            adc    r5, r2;                      \
-            lsl    r3, r6, #16;                 \
-            add    r4, r4, r3;                  \
-            adc    r5, r2;                      \
-            lsl    r3, r7, #16;                 \
-            add    r4, r4, r3;                  \
-            adc    r5, r2;                      \
-            ldr    r3, [r1];                    \
-            add    r4, r4, r3;                  \
-            adc    r2, r5;                      \
-            stmia  r1!, {r4};                   \
-         "
-
-#define MULADDC_STOP                            \
-         "                                      \
-            str    r2, %0;                      \
-            str    r1, %1;                      \
-            str    r0, %2;                      \
-         "                                      \
+#define MULADDC_INIT                                    \
+    asm(                                                \
+            "ldr    r0, %3                      \n\t"   \
+            "ldr    r1, %4                      \n\t"   \
+            "ldr    r2, %5                      \n\t"   \
+            "ldr    r3, %6                      \n\t"   \
+            "lsr    r7, r3, #16                 \n\t"   \
+            "mov    r9, r7                      \n\t"   \
+            "lsl    r7, r3, #16                 \n\t"   \
+            "lsr    r7, r7, #16                 \n\t"   \
+            "mov    r8, r7                      \n\t"
+
+#define MULADDC_CORE                                    \
+            "ldmia  r0!, {r6}                   \n\t"   \
+            "lsr    r7, r6, #16                 \n\t"   \
+            "lsl    r6, r6, #16                 \n\t"   \
+            "lsr    r6, r6, #16                 \n\t"   \
+            "mov    r4, r8                      \n\t"   \
+            "mul    r4, r6                      \n\t"   \
+            "mov    r3, r9                      \n\t"   \
+            "mul    r6, r3                      \n\t"   \
+            "mov    r5, r9                      \n\t"   \
+            "mul    r5, r7                      \n\t"   \
+            "mov    r3, r8                      \n\t"   \
+            "mul    r7, r3                      \n\t"   \
+            "lsr    r3, r6, #16                 \n\t"   \
+            "add    r5, r5, r3                  \n\t"   \
+            "lsr    r3, r7, #16                 \n\t"   \
+            "add    r5, r5, r3                  \n\t"   \
+            "add    r4, r4, r2                  \n\t"   \
+            "mov    r2, #0                      \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "lsl    r3, r6, #16                 \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "lsl    r3, r7, #16                 \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "ldr    r3, [r1]                    \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r2, r5                      \n\t"   \
+            "stmia  r1!, {r4}                   \n\t"
+
+#define MULADDC_STOP                                    \
+            "str    r2, %0                      \n\t"   \
+            "str    r1, %1                      \n\t"   \
+            "str    r0, %2                      \n\t"   \
          : "=m" (c),  "=m" (d), "=m" (s)        \
          : "m" (s), "m" (d), "m" (c), "m" (b)   \
          : "r0", "r1", "r2", "r3", "r4", "r5",  \
 
 #else
 
-#define MULADDC_INIT                            \
-    asm(                                        \
-         "                                     \
-            ldr    r0, %3;                      \
-            ldr    r1, %4;                      \
-            ldr    r2, %5;                      \
-            ldr    r3, %6;                      \
-         "
-
-#define MULADDC_CORE                            \
-         "                                      \
-            ldr    r4, [r0], #4;                \
-            mov    r5, #0;                      \
-            ldr    r6, [r1];                    \
-            umlal  r2, r5, r3, r4;              \
-            adds   r7, r6, r2;                  \
-            adc    r2, r5, #0;                  \
-            str    r7, [r1], #4;                \
-         "
-
-#define MULADDC_STOP                            \
-         "                                      \
-            str    r2, %0;                      \
-            str    r1, %1;                      \
-            str    r0, %2;                      \
-         "                                      \
+#define MULADDC_INIT                                    \
+    asm(                                                \
+            "ldr    r0, %3                      \n\t"   \
+            "ldr    r1, %4                      \n\t"   \
+            "ldr    r2, %5                      \n\t"   \
+            "ldr    r3, %6                      \n\t"
+
+#define MULADDC_CORE                                    \
+            "ldr    r4, [r0], #4                \n\t"   \
+            "mov    r5, #0                      \n\t"   \
+            "ldr    r6, [r1]                    \n\t"   \
+            "umlal  r2, r5, r3, r4              \n\t"   \
+            "adds   r7, r6, r2                  \n\t"   \
+            "adc    r2, r5, #0                  \n\t"   \
+            "str    r7, [r1], #4                \n\t"
+
+#define MULADDC_STOP                                    \
+            "str    r2, %0                      \n\t"   \
+            "str    r1, %1                      \n\t"   \
+            "str    r0, %2                      \n\t"   \
          : "=m" (c),  "=m" (d), "=m" (s)        \
          : "m" (s), "m" (d), "m" (c), "m" (b)   \
          : "r0", "r1", "r2", "r3", "r4", "r5",  \
 
 #if defined(__alpha__)
 
-#define MULADDC_INIT                            \
-    asm( "ldq    $1, %0         " :: "m" (s));  \
-    asm( "ldq    $2, %0         " :: "m" (d));  \
-    asm( "ldq    $3, %0         " :: "m" (c));  \
-    asm( "ldq    $4, %0         " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "ldq    $6,  0($1)     " );            \
-    asm( "addq   $1,  8, $1     " );            \
-    asm( "mulq   $6, $4, $7     " );            \
-    asm( "umulh  $6, $4, $6     " );            \
-    asm( "addq   $7, $3, $7     " );            \
-    asm( "cmpult $7, $3, $3     " );            \
-    asm( "ldq    $5,  0($2)     " );            \
-    asm( "addq   $7, $5, $7     " );            \
-    asm( "cmpult $7, $5, $5     " );            \
-    asm( "stq    $7,  0($2)     " );            \
-    asm( "addq   $2,  8, $2     " );            \
-    asm( "addq   $6, $3, $3     " );            \
-    asm( "addq   $5, $3, $3     " );
-
-#define MULADDC_STOP                            \
-    asm( "stq    $3, %0         " : "=m" (c));  \
-    asm( "stq    $2, %0         " : "=m" (d));  \
-    asm( "stq    $1, %0         " : "=m" (s) :: \
-    "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
+#define MULADDC_INIT                    \
+    asm(                                \
+        "ldq    $1, %3          \n\t"   \
+        "ldq    $2, %4          \n\t"   \
+        "ldq    $3, %5          \n\t"   \
+        "ldq    $4, %6          \n\t"
 
+#define MULADDC_CORE                    \
+        "ldq    $6,  0($1)      \n\t"   \
+        "addq   $1,  8, $1      \n\t"   \
+        "mulq   $6, $4, $7      \n\t"   \
+        "umulh  $6, $4, $6      \n\t"   \
+        "addq   $7, $3, $7      \n\t"   \
+        "cmpult $7, $3, $3      \n\t"   \
+        "ldq    $5,  0($2)      \n\t"   \
+        "addq   $7, $5, $7      \n\t"   \
+        "cmpult $7, $5, $5      \n\t"   \
+        "stq    $7,  0($2)      \n\t"   \
+        "addq   $2,  8, $2      \n\t"   \
+        "addq   $6, $3, $3      \n\t"   \
+        "addq   $5, $3, $3      \n\t"
+
+#define MULADDC_STOP                                    \
+        "stq    $3, %0          \n\t"   \
+        "stq    $2, %1          \n\t"   \
+        "stq    $1, %2          \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "$1", "$2", "$3", "$4", "$5", "$6", "$7"  \
+    );
 #endif /* Alpha */
 
-#if defined(__mips__)
+#if defined(__mips__) && !defined(__mips64__)
 
-#define MULADDC_INIT                            \
-    asm( "lw     $10, %0        " :: "m" (s));  \
-    asm( "lw     $11, %0        " :: "m" (d));  \
-    asm( "lw     $12, %0        " :: "m" (c));  \
-    asm( "lw     $13, %0        " :: "m" (b));
+#define MULADDC_INIT                    \
+    asm(                                \
+        "lw     $10, %3         \n\t"   \
+        "lw     $11, %4         \n\t"   \
+        "lw     $12, %5         \n\t"   \
+        "lw     $13, %6         \n\t"
 
-#define MULADDC_CORE                            \
-    asm( "lw     $14, 0($10)    " );            \
-    asm( "multu  $13, $14       " );            \
-    asm( "addi   $10, $10, 4    " );            \
-    asm( "mflo   $14            " );            \
-    asm( "mfhi   $9             " );            \
-    asm( "addu   $14, $12, $14  " );            \
-    asm( "lw     $15, 0($11)    " );            \
-    asm( "sltu   $12, $14, $12  " );            \
-    asm( "addu   $15, $14, $15  " );            \
-    asm( "sltu   $14, $15, $14  " );            \
-    asm( "addu   $12, $12, $9   " );            \
-    asm( "sw     $15, 0($11)    " );            \
-    asm( "addu   $12, $12, $14  " );            \
-    asm( "addi   $11, $11, 4    " );
+#define MULADDC_CORE                    \
+        "lw     $14, 0($10)     \n\t"   \
+        "multu  $13, $14        \n\t"   \
+        "addi   $10, $10, 4     \n\t"   \
+        "mflo   $14             \n\t"   \
+        "mfhi   $9              \n\t"   \
+        "addu   $14, $12, $14   \n\t"   \
+        "lw     $15, 0($11)     \n\t"   \
+        "sltu   $12, $14, $12   \n\t"   \
+        "addu   $15, $14, $15   \n\t"   \
+        "sltu   $14, $15, $14   \n\t"   \
+        "addu   $12, $12, $9    \n\t"   \
+        "sw     $15, 0($11)     \n\t"   \
+        "addu   $12, $12, $14   \n\t"   \
+        "addi   $11, $11, 4     \n\t"
 
-#define MULADDC_STOP                            \
-    asm( "sw     $12, %0        " : "=m" (c));  \
-    asm( "sw     $11, %0        " : "=m" (d));  \
-    asm( "sw     $10, %0        " : "=m" (s) :: \
-    "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
+#define MULADDC_STOP                    \
+        "sw     $12, %0         \n\t"   \
+        "sw     $11, %1         \n\t"   \
+        "sw     $10, %2         \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)                      \
+        : "m" (s), "m" (d), "m" (c), "m" (b)                \
+        : "$9", "$10", "$11", "$12", "$13", "$14", "$15"    \
+    );
 
 #endif /* MIPS */
 #endif /* GNUC */
index c98512f3d103822cdcc1eb59686491e1fd6eed4f..8488d1df83663bd51b08306af7980e3bb81a7367 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief Camellia block cipher
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_CAMELLIA_H
 #define POLARSSL_CAMELLIA_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -62,16 +66,31 @@ typedef struct
 }
 camellia_context;
 
+/**
+ * \brief          Initialize CAMELLIA context
+ *
+ * \param ctx      CAMELLIA context to be initialized
+ */
+void camellia_init( camellia_context *ctx );
+
+/**
+ * \brief          Clear CAMELLIA context
+ *
+ * \param ctx      CAMELLIA context to be cleared
+ */
+void camellia_free( camellia_context *ctx );
+
 /**
  * \brief          CAMELLIA key schedule (encryption)
  *
  * \param ctx      CAMELLIA context to be initialized
  * \param key      encryption key
  * \param keysize  must be 128, 192 or 256
- * 
+ *
  * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
  */
-int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key,
+                         unsigned int keysize );
 
 /**
  * \brief          CAMELLIA key schedule (decryption)
@@ -79,10 +98,11 @@ int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsign
  * \param ctx      CAMELLIA context to be initialized
  * \param key      decryption key
  * \param keysize  must be 128, 192 or 256
- * 
+ *
  * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH
  */
-int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize );
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key,
+                         unsigned int keysize );
 
 /**
  * \brief          CAMELLIA-ECB block encryption/decryption
@@ -91,7 +111,7 @@ int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsign
  * \param mode     CAMELLIA_ENCRYPT or CAMELLIA_DECRYPT
  * \param input    16-byte input block
  * \param output   16-byte output block
- * 
+ *
  * \return         0 if successful
  */
 int camellia_crypt_ecb( camellia_context *ctx,
@@ -111,8 +131,9 @@ int camellia_crypt_ecb( camellia_context *ctx,
  * \param iv       initialization vector (updated after use)
  * \param input    buffer holding the input data
  * \param output   buffer holding the output data
- * 
- * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ *
+ * \return         0 if successful, or
+ *                 POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
  */
 int camellia_crypt_cbc( camellia_context *ctx,
                     int mode,
@@ -138,7 +159,8 @@ int camellia_crypt_cbc( camellia_context *ctx,
  * \param input    buffer holding the input data
  * \param output   buffer holding the output data
  *
- * \return         0 if successful, or POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ * \return         0 if successful, or
+ *                 POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH
  */
 int camellia_crypt_cfb128( camellia_context *ctx,
                        int mode,
diff --git a/pdns/ext/polarssl/include/polarssl/ccm.h b/pdns/ext/polarssl/include/polarssl/ccm.h
new file mode 100644 (file)
index 0000000..439152f
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+ * \file ccm.h
+ *
+ * \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers
+ *
+ *  Copyright (C) 2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_CCM_H
+#define POLARSSL_CCM_H
+
+#include "cipher.h"
+
+#define POLARSSL_ERR_CCM_BAD_INPUT      -0x000D /**< Bad input parameters to function. */
+#define POLARSSL_ERR_CCM_AUTH_FAILED    -0x000F /**< Authenticated decryption failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          CCM context structure
+ */
+typedef struct {
+    cipher_context_t cipher_ctx;    /*!< cipher context used */
+}
+ccm_context;
+
+/**
+ * \brief           CCM initialization (encryption and decryption)
+ *
+ * \param ctx       CCM context to be initialized
+ * \param cipher    cipher to use (a 128-bit block cipher)
+ * \param key       encryption key
+ * \param keysize   key size in bits (must be acceptable by the cipher)
+ *
+ * \return          0 if successful, or a cipher specific error code
+ */
+int ccm_init( ccm_context *ctx, cipher_id_t cipher,
+              const unsigned char *key, unsigned int keysize );
+
+/**
+ * \brief           Free a CCM context and underlying cipher sub-context
+ *
+ * \param ctx       CCM context to free
+ */
+void ccm_free( ccm_context *ctx );
+
+/**
+ * \brief           CCM buffer encryption
+ *
+ * \param ctx       CCM context
+ * \param length    length of the input data in bytes
+ * \param iv        nonce (initialization vector)
+ * \param iv_len    length of IV in bytes
+ *                  must be 2, 3, 4, 5, 6, 7 or 8
+ * \param add       additional data
+ * \param add_len   length of additional data in bytes
+ *                  must be less than 2^16 - 2^8
+ * \param input     buffer holding the input data
+ * \param output    buffer for holding the output data
+ *                  must be at least 'length' bytes wide
+ * \param tag       buffer for holding the tag
+ * \param tag_len   length of the tag to generate in bytes
+ *                  must be 4, 6, 8, 10, 14 or 16
+ *
+ * \note            The tag is written to a separate buffer. To get the tag
+ *                  concatenated with the output as in the CCM spec, use
+ *                  tag = output + length and make sure the output buffer is
+ *                  at least length + tag_len wide.
+ *
+ * \return          0 if successful
+ */
+int ccm_encrypt_and_tag( ccm_context *ctx, size_t length,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output,
+                         unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief           CCM buffer authenticated decryption
+ *
+ * \param ctx       CCM context
+ * \param length    length of the input data
+ * \param iv        initialization vector
+ * \param iv_len    length of IV
+ * \param add       additional data
+ * \param add_len   length of additional data
+ * \param input     buffer holding the input data
+ * \param output    buffer for holding the output data
+ * \param tag       buffer holding the tag
+ * \param tag_len   length of the tag
+ *
+ * \return         0 if successful and authenticated,
+ *                 POLARSSL_ERR_CCM_AUTH_FAILED if tag does not match
+ */
+int ccm_auth_decrypt( ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      const unsigned char *tag, size_t tag_len );
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int ccm_self_test( int verbose );
+#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* POLARSSL_CGM_H */
diff --git a/pdns/ext/polarssl/include/polarssl/check_config.h b/pdns/ext/polarssl/include/polarssl/check_config.h
new file mode 100644 (file)
index 0000000..328b881
--- /dev/null
@@ -0,0 +1,326 @@
+/**
+ * \file check_config.h
+ *
+ * \brief Consistency checks for configuration options
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * It is recommended to include this file from your config.h
+ * in order to catch dependency issues early.
+ */
+
+#ifndef POLARSSL_CHECK_CONFIG_H
+#define POLARSSL_CHECK_CONFIG_H
+
+#if defined(POLARSSL_AESNI_C) && !defined(POLARSSL_HAVE_ASM)
+#error "POLARSSL_AESNI_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_CERTS_C) && !defined(POLARSSL_PEM_PARSE_C)
+#error "POLARSSL_CERTS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_CTR_DRBG_C) && !defined(POLARSSL_AES_C)
+#error "POLARSSL_CTR_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_DHM_C) && !defined(POLARSSL_BIGNUM_C)
+#error "POLARSSL_DHM_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDH_C) && !defined(POLARSSL_ECP_C)
+#error "POLARSSL_ECDH_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDSA_C) &&            \
+    ( !defined(POLARSSL_ECP_C) ||           \
+      !defined(POLARSSL_ASN1_PARSE_C) ||    \
+      !defined(POLARSSL_ASN1_WRITE_C) )
+#error "POLARSSL_ECDSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC) && !defined(POLARSSL_HMAC_DRBG_C)
+#error "POLARSSL_ECDSA_DETERMINISTIC defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ECP_C) && ( !defined(POLARSSL_BIGNUM_C) || (   \
+    !defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_BP256R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_BP384R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_BP512R1_ENABLED)   &&                  \
+    !defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) &&                  \
+    !defined(POLARSSL_ECP_DP_SECP256K1_ENABLED) ) )
+#error "POLARSSL_ECP_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_ENTROPY_C) && (!defined(POLARSSL_SHA512_C) &&      \
+                                    !defined(POLARSSL_SHA256_C))
+#error "POLARSSL_ENTROPY_C defined, but not all prerequisites"
+#endif
+#if defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_SHA512_C) &&         \
+    defined(CTR_DRBG_ENTROPY_LEN) && (CTR_DRBG_ENTROPY_LEN > 64)
+#error "CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(POLARSSL_ENTROPY_C) &&                                            \
+    ( !defined(POLARSSL_SHA512_C) || defined(POLARSSL_ENTROPY_FORCE_SHA256) ) \
+    && defined(CTR_DRBG_ENTROPY_LEN) && (CTR_DRBG_ENTROPY_LEN > 32)
+#error "CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(POLARSSL_ENTROPY_C) && \
+    defined(POLARSSL_ENTROPY_FORCE_SHA256) && !defined(POLARSSL_SHA256_C)
+#error "POLARSSL_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_GCM_C) && (                                        \
+        !defined(POLARSSL_AES_C) && !defined(POLARSSL_CAMELLIA_C) )
+#error "POLARSSL_GCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_HAVEGE_C) && !defined(POLARSSL_TIMING_C)
+#error "POLARSSL_HAVEGE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_HMAC_DRBG) && !defined(POLARSSL_MD_C)
+#error "POLARSSL_HMAC_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(POLARSSL_DHM_C)
+#error "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) &&                     \
+    !defined(POLARSSL_ECDH_C)
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) &&                   \
+    ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) ||           \
+      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_RSA_C) ||          \
+      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                 \
+    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) ||          \
+      !defined(POLARSSL_X509_CRT_PARSE_C) )
+#error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) &&                   \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
+      !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) &&                       \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
+      !defined(POLARSSL_PKCS1_V15) )
+#error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) &&                          \
+    ( !defined(POLARSSL_PLATFORM_C) || !defined(POLARSSL_PLATFORM_MEMORY) )
+#error "POLARSSL_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PADLOCK_C) && !defined(POLARSSL_HAVE_ASM)
+#error "POLARSSL_PADLOCK_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PBKDF2_C) && !defined(POLARSSL_MD_C)
+#error "POLARSSL_PBKDF2_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PEM_PARSE_C) && !defined(POLARSSL_BASE64_C)
+#error "POLARSSL_PEM_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PEM_WRITE_C) && !defined(POLARSSL_BASE64_C)
+#error "POLARSSL_PEM_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PK_PARSE_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PK_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PK_WRITE_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PK_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C)
+#error "POLARSSL_PKCS11_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_RSA_C) && ( !defined(POLARSSL_BIGNUM_C) ||         \
+    !defined(POLARSSL_OID_C) )
+#error "POLARSSL_RSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) &&                        \
+    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_PKCS1_V21) )
+#error "POLARSSL_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_SSL3 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_TLS1 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) && ( !defined(POLARSSL_MD5_C) ||     \
+    !defined(POLARSSL_SHA1_C) )
+#error "POLARSSL_SSL_PROTO_TLS1_1 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_PROTO_TLS1_2) && ( !defined(POLARSSL_SHA1_C) &&     \
+    !defined(POLARSSL_SHA256_C) && !defined(POLARSSL_SHA512_C) )
+#error "POLARSSL_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_CLI_C) && !defined(POLARSSL_SSL_TLS_C)
+#error "POLARSSL_SSL_CLI_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_CIPHER_C) ||     \
+    !defined(POLARSSL_MD_C) )
+#error "POLARSSL_SSL_TLS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_SRV_C) && !defined(POLARSSL_SSL_TLS_C)
+#error "POLARSSL_SSL_SRV_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (!defined(POLARSSL_SSL_PROTO_SSL3) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1) && !defined(POLARSSL_SSL_PROTO_TLS1_1) && \
+    !defined(POLARSSL_SSL_PROTO_TLS1_2))
+#error "POLARSSL_SSL_TLS_C defined, but no protocols are active"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_1) && !defined(POLARSSL_SSL_PROTO_TLS1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_TLS1) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_2) && !defined(POLARSSL_SSL_PROTO_TLS1_1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
+    defined(POLARSSL_SSL_PROTO_TLS1_2) && (!defined(POLARSSL_SSL_PROTO_TLS1) || \
+    !defined(POLARSSL_SSL_PROTO_TLS1_1)))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \
+    ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) ||            \
+      !defined(POLARSSL_CIPHER_MODE_CBC) )
+#error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && \
+        !defined(POLARSSL_X509_CRT_PARSE_C)
+#error "POLARSSL_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_THREADING_PTHREAD)
+#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites"
+#endif
+#define POLARSSL_THREADING_IMPL
+#endif
+
+#if defined(POLARSSL_THREADING_ALT)
+#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_ALT defined, but not all prerequisites"
+#endif
+#define POLARSSL_THREADING_IMPL
+#endif
+
+#if defined(POLARSSL_THREADING_C) && !defined(POLARSSL_THREADING_IMPL)
+#error "POLARSSL_THREADING_C defined, single threading implementation required"
+#endif
+#undef POLARSSL_THREADING_IMPL
+
+#if defined(POLARSSL_VERSION_FEATURES) && !defined(POLARSSL_VERSION_C)
+#error "POLARSSL_VERSION_FEATURES defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_USE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
+    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) ||      \
+    !defined(POLARSSL_PK_PARSE_C) )
+#error "POLARSSL_X509_USE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CREATE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
+    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) ||       \
+    !defined(POLARSSL_PK_WRITE_C) )
+#error "POLARSSL_X509_CREATE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CRT_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRL_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CRL_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CSR_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
+#error "POLARSSL_X509_CSR_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CRT_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
+#error "POLARSSL_X509_CRT_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(POLARSSL_X509_CSR_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
+#error "POLARSSL_X509_CSR_WRITE_C defined, but not all prerequisites"
+#endif
+
+#endif /* POLARSSL_CHECK_CONFIG_H */
index c7ad5b780881ed94daac6f113ed9aa2d1a87232e..087e590680269b7b16ac697764b33e0c3f38beea 100644 (file)
@@ -1,11 +1,11 @@
 /**
  * \file cipher.h
- * 
+ *
  * \brief Generic cipher wrapper.
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_CIPHER_H
 #define POLARSSL_CIPHER_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
-#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C)
 #define POLARSSL_CIPHER_MODE_AEAD
 #endif
 
@@ -57,6 +61,9 @@
 #define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED            -0x6280  /**< Decryption of block requires a full block. */
 #define POLARSSL_ERR_CIPHER_AUTH_FAILED                    -0x6300  /**< Authentication failed (for AEAD modes). */
 
+#define POLARSSL_CIPHER_VARIABLE_IV_LEN     0x01    /**< Cipher accepts IVs of variable length */
+#define POLARSSL_CIPHER_VARIABLE_KEY_LEN    0x02    /**< Cipher accepts keys of variable length */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -116,6 +123,12 @@ typedef enum {
     POLARSSL_CIPHER_BLOWFISH_CFB64,
     POLARSSL_CIPHER_BLOWFISH_CTR,
     POLARSSL_CIPHER_ARC4_128,
+    POLARSSL_CIPHER_AES_128_CCM,
+    POLARSSL_CIPHER_AES_192_CCM,
+    POLARSSL_CIPHER_AES_256_CCM,
+    POLARSSL_CIPHER_CAMELLIA_128_CCM,
+    POLARSSL_CIPHER_CAMELLIA_192_CCM,
+    POLARSSL_CIPHER_CAMELLIA_256_CCM,
 } cipher_type_t;
 
 typedef enum {
@@ -123,10 +136,11 @@ typedef enum {
     POLARSSL_MODE_ECB,
     POLARSSL_MODE_CBC,
     POLARSSL_MODE_CFB,
-    POLARSSL_MODE_OFB,
+    POLARSSL_MODE_OFB, /* Unused! */
     POLARSSL_MODE_CTR,
     POLARSSL_MODE_GCM,
     POLARSSL_MODE_STREAM,
+    POLARSSL_MODE_CCM,
 } cipher_mode_t;
 
 typedef enum {
@@ -169,29 +183,34 @@ typedef struct {
 
     /** Encrypt using ECB */
     int (*ecb_func)( void *ctx, operation_t mode,
-            const unsigned char *input, unsigned char *output );
+                     const unsigned char *input, unsigned char *output );
 
     /** Encrypt using CBC */
-    int (*cbc_func)( void *ctx, operation_t mode, size_t length, unsigned char *iv,
-            const unsigned char *input, unsigned char *output );
+    int (*cbc_func)( void *ctx, operation_t mode, size_t length,
+                     unsigned char *iv, const unsigned char *input,
+                     unsigned char *output );
 
     /** Encrypt using CFB (Full length) */
     int (*cfb_func)( void *ctx, operation_t mode, size_t length, size_t *iv_off,
-            unsigned char *iv, const unsigned char *input, unsigned char *output );
+                     unsigned char *iv, const unsigned char *input,
+                     unsigned char *output );
 
     /** Encrypt using CTR */
-    int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter,
-            unsigned char *stream_block, const unsigned char *input, unsigned char *output );
+    int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
+                     unsigned char *nonce_counter, unsigned char *stream_block,
+                     const unsigned char *input, unsigned char *output );
 
     /** Encrypt using STREAM */
     int (*stream_func)( void *ctx, size_t length,
                         const unsigned char *input, unsigned char *output );
 
     /** Set key for encryption purposes */
-    int (*setkey_enc_func)( void *ctx, const unsigned char *key, unsigned int key_length);
+    int (*setkey_enc_func)( void *ctx, const unsigned char *key,
+                            unsigned int key_length );
 
     /** Set key for decryption purposes */
-    int (*setkey_dec_func)( void *ctx, const unsigned char *key, unsigned int key_length);
+    int (*setkey_dec_func)( void *ctx, const unsigned char *key,
+                            unsigned int key_length);
 
     /** Allocate a new context */
     void * (*ctx_alloc_func)( void );
@@ -222,8 +241,8 @@ typedef struct {
      *  For cipher that accept many sizes: recommended size */
     unsigned int iv_size;
 
-    /** Flag for ciphers that accept many sizes of IV/NONCE */
-    int accepts_variable_iv_size;
+    /** Flags for variable IV size, variable key size, etc. */
+    int flags;
 
     /** block size, in bytes */
     unsigned int block_size;
@@ -312,16 +331,32 @@ const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id,
                                               int key_length,
                                               const cipher_mode_t mode );
 
+/**
+ * \brief               Initialize a cipher_context (as NONE)
+ */
+void cipher_init( cipher_context_t *ctx );
+
+/**
+ * \brief               Free and clear the cipher-specific context of ctx.
+ *                      Freeing ctx itself remains the responsibility of the
+ *                      caller.
+ */
+void cipher_free( cipher_context_t *ctx );
+
 /**
  * \brief               Initialises and fills the cipher context structure with
  *                      the appropriate values.
  *
+ * \note                Currently also clears structure. In future versions you
+ *                      will be required to call cipher_init() on the structure
+ *                      first.
+ *
  * \param ctx           context to initialise. May not be NULL.
  * \param cipher_info   cipher to use.
  *
- * \return              \c 0 on success,
- *                      \c POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
- *                      \c POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ * \return              0 on success,
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
+ *                      POLARSSL_ERR_CIPHER_ALLOC_FAILED if allocation of the
  *                      cipher-specific context failed.
  */
 int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info );
@@ -330,10 +365,11 @@ int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info );
  * \brief               Free the cipher-specific context of ctx. Freeing ctx
  *                      itself remains the responsibility of the caller.
  *
+ * \note                Deprecated: Redirects to cipher_free()
+ *
  * \param ctx           Free the cipher-specific context
  *
- * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if
- *                      parameter verification fails.
+ * \returns             0
  */
 int cipher_free_ctx( cipher_context_t *ctx );
 
@@ -470,8 +506,8 @@ static inline operation_t cipher_get_operation( const cipher_context_t *ctx )
  *                      parameter verification fails or a cipher specific
  *                      error code.
  */
-int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, int key_length,
-        const operation_t operation );
+int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
+                   int key_length, const operation_t operation );
 
 #if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
 /**
@@ -497,7 +533,7 @@ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode );
  * \param iv_len        IV length for ciphers with variable-size IV;
  *                      discarded by ciphers with fixed-size IV.
  *
- * \returns             O on success, or POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
+ * \returns             0 on success, or POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
  *
  * \note                Some ciphers don't use IVs nor NONCE. For these
  *                      ciphers, this function has no effect.
@@ -515,25 +551,21 @@ int cipher_set_iv( cipher_context_t *ctx,
  */
 int cipher_reset( cipher_context_t *ctx );
 
-#if defined(POLARSSL_CIPHER_MODE_AEAD)
+#if defined(POLARSSL_GCM_C)
 /**
  * \brief               Add additional data (for AEAD ciphers).
- *                      This function has no effect for non-AEAD ciphers.
- *                      For AEAD ciphers, it may or may not be called
- *                      repeatedly, and/or interleaved with calls to
- *                      cipher_udpate(), depending on the cipher.
- *                      E.g. for GCM is must be called exactly once, right
- *                      after cipher_reset().
+ *                      Currently only supported with GCM.
+ *                      Must be called exactly once, after cipher_reset().
  *
  * \param ctx           generic cipher context
  * \param ad            Additional data to use.
  * \param ad_len        Length of ad.
  *
- * \returns             0 on success, or a specific error code.
+ * \return              0 on success, or a specific error code.
  */
 int cipher_update_ad( cipher_context_t *ctx,
                       const unsigned char *ad, size_t ad_len );
-#endif /* POLARSSL_CIPHER_MODE_AEAD */
+#endif /* POLARSSL_GCM_C */
 
 /**
  * \brief               Generic cipher update function. Encrypts/decrypts
@@ -564,8 +596,8 @@ int cipher_update_ad( cipher_context_t *ctx,
  *                      function, except the last one before cipher_finish(),
  *                      must have ilen a multiple of the block size.
  */
-int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
-        unsigned char *output, size_t *olen );
+int cipher_update( cipher_context_t *ctx, const unsigned char *input,
+                   size_t ilen, unsigned char *output, size_t *olen );
 
 /**
  * \brief               Generic cipher finalisation function. If data still
@@ -587,10 +619,10 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
 int cipher_finish( cipher_context_t *ctx,
                    unsigned char *output, size_t *olen );
 
-#if defined(POLARSSL_CIPHER_MODE_AEAD)
+#if defined(POLARSSL_GCM_C)
 /**
  * \brief               Write tag for AEAD ciphers.
- *                      No effect for other ciphers.
+ *                      Currently only supported with GCM.
  *                      Must be called after cipher_finish().
  *
  * \param ctx           Generic cipher context
@@ -604,9 +636,8 @@ int cipher_write_tag( cipher_context_t *ctx,
 
 /**
  * \brief               Check tag for AEAD ciphers.
- *                      No effect for other ciphers.
- *                      Calling time depends on the cipher:
- *                      for GCM, must be called after cipher_finish().
+ *                      Currently only supported with GCM.
+ *                      Must be called after cipher_finish().
  *
  * \param ctx           Generic cipher context
  * \param tag           Buffer holding the tag
@@ -616,6 +647,103 @@ int cipher_write_tag( cipher_context_t *ctx,
  */
 int cipher_check_tag( cipher_context_t *ctx,
                       const unsigned char *tag, size_t tag_len );
+#endif /* POLARSSL_GCM_C */
+
+/**
+ * \brief               Generic all-in-one encryption/decryption
+ *                      (for all ciphers except AEAD constructs).
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data. Should be able to hold at
+ *                      least ilen + block_size. Cannot be the same buffer as
+ *                      input!
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ *
+ * \note                Some ciphers don't use IVs nor NONCE. For these
+ *                      ciphers, use iv = NULL and iv_len = 0.
+ *
+ * \returns             0 on success, or
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
+ *                      expected a full block but was not provided one, or
+ *                      POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding
+ *                      while decrypting, or
+ *                      a cipher specific error code.
+ */
+int cipher_crypt( cipher_context_t *ctx,
+                  const unsigned char *iv, size_t iv_len,
+                  const unsigned char *input, size_t ilen,
+                  unsigned char *output, size_t *olen );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+/**
+ * \brief               Generic autenticated encryption (AEAD ciphers).
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ * \param ad            Additional data to authenticate.
+ * \param ad_len        Length of ad.
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data.
+ *                      Should be able to hold at least ilen.
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ * \param tag           buffer for the authentication tag
+ * \param tag_len       desired tag length
+ *
+ * \returns             0 on success, or
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      a cipher specific error code.
+ */
+int cipher_auth_encrypt( cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief               Generic autenticated decryption (AEAD ciphers).
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ * \param ad            Additional data to be authenticated.
+ * \param ad_len        Length of ad.
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data.
+ *                      Should be able to hold at least ilen.
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ * \param tag           buffer holding the authentication tag
+ * \param tag_len       length of the authentication tag
+ *
+ * \returns             0 on success, or
+ *                      POLARSSL_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      POLARSSL_ERR_CIPHER_AUTH_FAILED if data isn't authentic,
+ *                      or a cipher specific error code.
+ *
+ * \note                If the data is not authentic, then the output buffer
+ *                      is zeroed out to prevent the unauthentic plaintext to
+ *                      be used by mistake, making this interface safer.
+ */
+int cipher_auth_decrypt( cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         const unsigned char *tag, size_t tag_len );
 #endif /* POLARSSL_CIPHER_MODE_AEAD */
 
 /**
index 63bd093fcbc4bb956bbb1173401a766bf864f999..46bc757a8ea37cbfda771442cb2d3449096d60c9 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * \file cipher_wrap.h
- * 
+ *
  * \brief Cipher wrappers.
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
 #ifndef POLARSSL_CIPHER_WRAP_H
 #define POLARSSL_CIPHER_WRAP_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 #include "cipher.h"
 
 #ifdef __cplusplus
index 64d1d636540b6f18bdc27d241c8ed25ba7e11611..15b5aa1f2ac1dd4a194933a273e7514fdcb3a93a 100644 (file)
 #ifndef POLARSSL_COMPAT_1_2_H
 #define POLARSSL_COMPAT_1_2_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 // Comment out to disable prototype change warnings
 #define SHOW_PROTOTYPE_CHANGE_WARNINGS
  */
 typedef sha256_context sha2_context;
 
-inline void sha2_starts( sha256_context *ctx, int is224 ) {
+static inline void sha2_starts( sha256_context *ctx, int is224 ) {
     sha256_starts( ctx, is224 );
 }
-inline void sha2_update( sha256_context *ctx, const unsigned char *input,
+static inline void sha2_update( sha256_context *ctx, const unsigned char *input,
                          size_t ilen ) {
     sha256_update( ctx, input, ilen );
 }
-inline void sha2_finish( sha256_context *ctx, unsigned char output[32] ) {
+static inline void sha2_finish( sha256_context *ctx, unsigned char output[32] ) {
     sha256_finish( ctx, output );
 }
-inline int sha2_file( const char *path, unsigned char output[32], int is224 ) {
+static inline int sha2_file( const char *path, unsigned char output[32], int is224 ) {
     return sha256_file( path, output, is224 );
 }
-inline void sha2( const unsigned char *input, size_t ilen,
+static inline void sha2( const unsigned char *input, size_t ilen,
                   unsigned char output[32], int is224 ) {
     sha256( input, ilen, output, is224 );
 }
-inline void sha2_hmac_starts( sha256_context *ctx, const unsigned char *key,
+static inline void sha2_hmac_starts( sha256_context *ctx, const unsigned char *key,
                               size_t keylen, int is224 ) {
     sha256_hmac_starts( ctx, key, keylen, is224 );
 }
-inline void sha2_hmac_update( sha256_context *ctx, const unsigned char *input, size_t ilen ) {
+static inline void sha2_hmac_update( sha256_context *ctx, const unsigned char *input, size_t ilen ) {
     sha256_hmac_update( ctx, input, ilen );
 }
-inline void sha2_hmac_finish( sha256_context *ctx, unsigned char output[32] ) {
+static inline void sha2_hmac_finish( sha256_context *ctx, unsigned char output[32] ) {
     sha256_hmac_finish( ctx, output );
 }
-inline void sha2_hmac_reset( sha256_context *ctx ) {
+static inline void sha2_hmac_reset( sha256_context *ctx ) {
     sha256_hmac_reset( ctx );
 }
-inline void sha2_hmac( const unsigned char *key, size_t keylen,
+static inline void sha2_hmac( const unsigned char *key, size_t keylen,
                        const unsigned char *input, size_t ilen,
                        unsigned char output[32], int is224 ) {
     sha256_hmac( key, keylen, input, ilen, output, is224 );
 }
-inline int sha2_self_test( int verbose ) {
+static inline int sha2_self_test( int verbose ) {
     return sha256_self_test( verbose );
 }
 #endif /* POLARSSL_SHA256_C */
@@ -107,42 +111,42 @@ inline int sha2_self_test( int verbose ) {
  */
 typedef sha512_context sha4_context;
 
-inline void sha4_starts( sha512_context *ctx, int is384 ) {
+static inline void sha4_starts( sha512_context *ctx, int is384 ) {
     sha512_starts( ctx, is384 );
 }
-inline void sha4_update( sha512_context *ctx, const unsigned char *input,
+static inline void sha4_update( sha512_context *ctx, const unsigned char *input,
                          size_t ilen ) {
     sha512_update( ctx, input, ilen );
 }
-inline void sha4_finish( sha512_context *ctx, unsigned char output[64] ) {
+static inline void sha4_finish( sha512_context *ctx, unsigned char output[64] ) {
     sha512_finish( ctx, output );
 }
-inline int sha4_file( const char *path, unsigned char output[64], int is384 ) {
+static inline int sha4_file( const char *path, unsigned char output[64], int is384 ) {
     return sha512_file( path, output, is384 );
 }
-inline void sha4( const unsigned char *input, size_t ilen,
+static inline void sha4( const unsigned char *input, size_t ilen,
                   unsigned char output[32], int is384 ) {
     sha512( input, ilen, output, is384 );
 }
-inline void sha4_hmac_starts( sha512_context *ctx, const unsigned char *key,
+static inline void sha4_hmac_starts( sha512_context *ctx, const unsigned char *key,
                               size_t keylen, int is384 ) {
     sha512_hmac_starts( ctx, key, keylen, is384 );
 }
-inline void sha4_hmac_update( sha512_context *ctx, const unsigned char *input, size_t ilen ) {
+static inline void sha4_hmac_update( sha512_context *ctx, const unsigned char *input, size_t ilen ) {
     sha512_hmac_update( ctx, input, ilen );
 }
-inline void sha4_hmac_finish( sha512_context *ctx, unsigned char output[64] ) {
+static inline void sha4_hmac_finish( sha512_context *ctx, unsigned char output[64] ) {
     sha512_hmac_finish( ctx, output );
 }
-inline void sha4_hmac_reset( sha512_context *ctx ) {
+static inline void sha4_hmac_reset( sha512_context *ctx ) {
     sha512_hmac_reset( ctx );
 }
-inline void sha4_hmac( const unsigned char *key, size_t keylen,
+static inline void sha4_hmac( const unsigned char *key, size_t keylen,
                        const unsigned char *input, size_t ilen,
                        unsigned char output[64], int is384 ) {
     sha512_hmac( key, keylen, input, ilen, output, is384 );
 }
-inline int sha4_self_test( int verbose ) {
+static inline int sha4_self_test( int verbose ) {
     return sha512_self_test( verbose );
 }
 #endif /* POLARSSL_SHA512_C */
@@ -167,7 +171,7 @@ inline int sha4_self_test( int verbose ) {
 #warning "rsa_pkcs1_verify() prototype changed. Manual change required if used"
 #warning "rsa_pkcs1_decrypt() prototype changed. Manual change required if used"
 #endif
-#endif
+#endif /* POLARSSL_RSA_C */
 
 #if defined(POLARSSL_DHM_C)
 #if defined(SHOW_PROTOTYPE_CHANGE_WARNINGS)
@@ -202,13 +206,13 @@ inline int sha4_self_test( int verbose ) {
 #define POLARSSL_ERR_X509_CERT_INVALID_SERIAL POLARSSL_ERR_X509_INVALID_SERIAL
 #define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION POLARSSL_ERR_X509_UNKNOWN_VERSION
 
-inline int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial ) {
+static inline int x509parse_serial_gets( char *buf, size_t size, const x509_buf *serial ) {
     return x509_serial_gets( buf, size, serial );
 }
-inline int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn ) {
+static inline int x509parse_dn_gets( char *buf, size_t size, const x509_name *dn ) {
     return x509_dn_gets( buf, size, dn );
 }
-inline int x509parse_time_expired( const x509_time *time ) {
+static inline int x509parse_time_expired( const x509_time *time ) {
     return x509_time_expired( time );
 }
 #endif /* POLARSSL_X509_USE_C || POLARSSL_X509_CREATE_C */
@@ -218,33 +222,33 @@ inline int x509parse_time_expired( const x509_time *time ) {
 #include "x509_crt.h"
 typedef x509_crt x509_cert;
 
-inline int x509parse_crt_der( x509_cert *chain, const unsigned char *buf,
+static inline int x509parse_crt_der( x509_cert *chain, const unsigned char *buf,
                               size_t buflen ) {
     return x509_crt_parse_der( chain, buf, buflen );
 }
-inline int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ) {
+static inline int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ) {
     return x509_crt_parse( chain, buf, buflen );
 }
-inline int x509parse_crtfile( x509_cert *chain, const char *path ) {
+static inline int x509parse_crtfile( x509_cert *chain, const char *path ) {
     return x509_crt_parse_file( chain, path );
 }
-inline int x509parse_crtpath( x509_cert *chain, const char *path ) {
+static inline int x509parse_crtpath( x509_cert *chain, const char *path ) {
     return x509_crt_parse_path( chain, path );
 }
-inline int x509parse_cert_info( char *buf, size_t size, const char *prefix,
+static inline int x509parse_cert_info( char *buf, size_t size, const char *prefix,
                                 const x509_cert *crt ) {
     return x509_crt_info( buf, size, prefix, crt );
 }
-inline int x509parse_verify( x509_cert *crt, x509_cert *trust_ca,
+static inline int x509parse_verify( x509_cert *crt, x509_cert *trust_ca,
                              x509_crl *ca_crl, const char *cn, int *flags,
                              int (*f_vrfy)(void *, x509_cert *, int, int *),
                              void *p_vrfy ) {
     return x509_crt_verify( crt, trust_ca, ca_crl, cn, flags, f_vrfy, p_vrfy );
 }
-inline int x509parse_revoked( const x509_cert *crt, const x509_crl *crl ) {
+static inline int x509parse_revoked( const x509_cert *crt, const x509_crl *crl ) {
     return x509_crt_revoked( crt, crl );
 }
-inline void x509_free( x509_cert *crt ) {
+static inline void x509_free( x509_cert *crt ) {
     x509_crt_free( crt );
 }
 #endif /* POLARSSL_X509_CRT_PARSE_C */
@@ -252,13 +256,13 @@ inline void x509_free( x509_cert *crt ) {
 #if defined(POLARSSL_X509_CRL_PARSE_C)
 #define POLARSSL_X509_PARSE_C
 #include "x509_crl.h"
-inline int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) {
+static inline int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) {
     return x509_crl_parse( chain, buf, buflen );
 }
-inline int x509parse_crlfile( x509_crl *chain, const char *path ) {
+static inline int x509parse_crlfile( x509_crl *chain, const char *path ) {
     return x509_crl_parse_file( chain, path );
 }
-inline int x509parse_crl_info( char *buf, size_t size, const char *prefix,
+static inline int x509parse_crl_info( char *buf, size_t size, const char *prefix,
                                const x509_crl *crl ) {
     return x509_crl_info( buf, size, prefix, crl );
 }
@@ -267,13 +271,13 @@ inline int x509parse_crl_info( char *buf, size_t size, const char *prefix,
 #if defined(POLARSSL_X509_CSR_PARSE_C)
 #define POLARSSL_X509_PARSE_C
 #include "x509_csr.h"
-inline int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) {
+static inline int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) {
     return x509_csr_parse( csr, buf, buflen );
 }
-inline int x509parse_csrfile( x509_csr *csr, const char *path ) {
+static inline int x509parse_csrfile( x509_csr *csr, const char *path ) {
     return x509_csr_parse_file( csr, path );
 }
-inline int x509parse_csr_info( char *buf, size_t size, const char *prefix,
+static inline int x509parse_csr_info( char *buf, size_t size, const char *prefix,
                                const x509_csr *csr ) {
     return x509_csr_info( buf, size, prefix, csr );
 }
@@ -295,7 +299,7 @@ inline int x509parse_csr_info( char *buf, size_t size, const char *prefix,
 #define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY POLARSSL_ERR_PK_INVALID_PUBKEY
 
 #if defined(POLARSSL_FS_IO)
-inline int x509parse_keyfile( rsa_context *rsa, const char *path,
+static inline int x509parse_keyfile( rsa_context *rsa, const char *path,
                               const char *pwd ) {
     int ret;
     pk_context pk;
@@ -310,7 +314,7 @@ inline int x509parse_keyfile( rsa_context *rsa, const char *path,
     pk_free( &pk );
     return( ret );
 }
-inline int x509parse_public_keyfile( rsa_context *rsa, const char *path ) {
+static inline int x509parse_public_keyfile( rsa_context *rsa, const char *path ) {
     int ret;
     pk_context pk;
     pk_init( &pk );
@@ -326,7 +330,7 @@ inline int x509parse_public_keyfile( rsa_context *rsa, const char *path ) {
 }
 #endif /* POLARSSL_FS_IO */
 
-inline int x509parse_key( rsa_context *rsa, const unsigned char *key,
+static inline int x509parse_key( rsa_context *rsa, const unsigned char *key,
                           size_t keylen,
                           const unsigned char *pwd, size_t pwdlen ) {
     int ret;
@@ -343,7 +347,7 @@ inline int x509parse_key( rsa_context *rsa, const unsigned char *key,
     return( ret );
 }
 
-inline int x509parse_public_key( rsa_context *rsa,
+static inline int x509parse_public_key( rsa_context *rsa,
                                  const unsigned char *key, size_t keylen )
 {
     int ret;
@@ -363,7 +367,7 @@ inline int x509parse_public_key( rsa_context *rsa,
 
 #if defined(POLARSSL_PK_WRITE_C) && defined(POLARSSL_RSA_C)
 #include "pk.h"
-inline int x509_write_pubkey_der( unsigned char *buf, size_t len, rsa_context *rsa ) {
+static inline int x509_write_pubkey_der( unsigned char *buf, size_t len, rsa_context *rsa ) {
     int ret;
     pk_context ctx;
     if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret );
@@ -372,7 +376,7 @@ inline int x509_write_pubkey_der( unsigned char *buf, size_t len, rsa_context *r
     pk_free( &ctx );
     return( ret );
 }
-inline int x509_write_key_der( unsigned char *buf, size_t len, rsa_context *rsa ) {
+static inline int x509_write_key_der( unsigned char *buf, size_t len, rsa_context *rsa ) {
     int ret;
     pk_context ctx;
     if( ( ret = pk_init_ctx( &ctx, pk_info_from_type( POLARSSL_PK_RSA ) ) ) != 0 ) return( ret );
index a631a4a90030de3f87d9ac6bf12f0744dc5031f8..d43365ff5e36316584c353afe6c71e483d6c2c97 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief Configuration options (set of defines)
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 //#define POLARSSL_HAVE_SSE2
 
 /**
- * \def POLARSSL_HAVE_READDIR_R
+ * \def POLARSSL_HAVE_TIME
+ *
+ * System has time.h and time() / localtime()  / gettimeofday().
+ *
+ * Comment if your system does not support time functions
+ */
+#define POLARSSL_HAVE_TIME
+
+/**
+ * \def POLARSSL_HAVE_IPV6
  *
- * (Non Windows) System has readdir_r().
+ * System supports the basic socket interface for IPv6 (RFC 3493),
+ * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage.
  *
- * Required for x509_crt_parse_path() in non-Windows systems.
+ * Note: on Windows/MingW, XP or higher is required.
  *
- * Comment if your system does not have support.
+ * Comment if your system does not support the IPv6 socket interface
  */
-#define POLARSSL_HAVE_READDIR_R
+#define POLARSSL_HAVE_IPV6
 
 /**
- * \def POLARSSL_HAVE_TIME
+ * \def POLARSSL_PLATFORM_MEMORY
  *
- * System has time.h and time() / localtime()  / gettimeofday().
+ * Enable the memory allocation layer.
  *
- * Comment if your system does not support time functions
+ * By default PolarSSL uses the system-provided malloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling POLARSSL_PLATFORM_MEMORY will provide "platform_set_malloc_free()"
+ * to allow you to set an alternative malloc() and free() function pointer.
+ *
+ * Requires: POLARSSL_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
  */
-#define POLARSSL_HAVE_TIME
+//#define POLARSSL_PLATFORM_MEMORY
+
+/**
+ * \def POLARSSL_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. malloc() to
+ * POLARSSL_PLATFORM_STD_MALLOC and printf() to POLARSSL_PLATFORM_STD_PRINTF)
+ *
+ * This makes sure there are no linking errors on platforms that do not support
+ * these functions. You will HAVE to provide alternatives, either at runtime
+ * via the platform_set_xxx() functions or at compile time by setting
+ * the POLARSSL_PLATFORM_STD_XXX defines.
+ *
+ * Requires: POLARSSL_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def POLARSSL_PLATFORM_XXX_ALT
+ *
+ * Uncomment a macro to let PolarSSL support the function in the platform
+ * abstraction layer.
+ *
+ * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, PolarSSL will
+ * provide a function "platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require POLARSSL_PLATFORM_C to be defined!
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define POLARSSL_PLATFORM_PRINTF_ALT
+//#define POLARSSL_PLATFORM_FPRINTF_ALT
 /* \} name SECTION: System support */
 
 /**
  * \{
  */
 
+/**
+ * \def POLARSSL_TIMING_ALT
+ *
+ * Uncomment to provide your own alternate implementation for hardclock(),
+ * get_timer(), set_alarm() and m_sleep().
+ *
+ * Only works if you have POLARSSL_TIMING_C enabled.
+ *
+ * You will need to provide a header "timing_alt.h" and an implementation at
+ * compile time.
+ */
+//#define POLARSSL_TIMING_ALT
+
 /**
  * \def POLARSSL_XXX_ALT
  *
 //#define POLARSSL_MD2_ALT
 //#define POLARSSL_MD4_ALT
 //#define POLARSSL_MD5_ALT
+//#define POLARSSL_RIPEMD160_ALT
 //#define POLARSSL_SHA1_ALT
 //#define POLARSSL_SHA256_ALT
 //#define POLARSSL_SHA512_ALT
  *
  * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable
  * the following ciphersuites:
+ *      TLS_ECDH_ECDSA_WITH_NULL_SHA
+ *      TLS_ECDH_RSA_WITH_NULL_SHA
  *      TLS_ECDHE_ECDSA_WITH_NULL_SHA
  *      TLS_ECDHE_RSA_WITH_NULL_SHA
  *      TLS_ECDHE_PSK_WITH_NULL_SHA384
  *      TLS_PSK_WITH_NULL_SHA
  *
  * Uncomment this macro to enable the NULL cipher and ciphersuites
-#define POLARSSL_CIPHER_NULL_CIPHER
  */
+//#define POLARSSL_CIPHER_NULL_CIPHER
 
 /**
  * \def POLARSSL_CIPHER_PADDING_XXX
  *      TLS_DHE_RSA_WITH_DES_CBC_SHA
  *
  * Uncomment this macro to enable weak ciphersuites
-#define POLARSSL_ENABLE_WEAK_CIPHERSUITES
  */
+//#define POLARSSL_ENABLE_WEAK_CIPHERSUITES
+
+/**
+ * \def POLARSSL_REMOVE_ARC4_CIPHERSUITES
+ *
+ * Remove RC4 ciphersuites by default in SSL / TLS.
+ * This flag removes the ciphersuites based on RC4 from the default list as
+ * returned by ssl_list_ciphersuites(). However, it is still possible to
+ * enable (some of) them with ssl_set_ciphersuites() by including them
+ * explicitly.
+ *
+ * Uncomment this macro to remove RC4 ciphersuites by default.
+ */
+//#define POLARSSL_REMOVE_ARC4_CIPHERSUITES
 
 /**
  * \def POLARSSL_ECP_XXXX_ENABLED
 #define POLARSSL_ECP_DP_SECP256R1_ENABLED
 #define POLARSSL_ECP_DP_SECP384R1_ENABLED
 #define POLARSSL_ECP_DP_SECP521R1_ENABLED
+#define POLARSSL_ECP_DP_SECP192K1_ENABLED
+#define POLARSSL_ECP_DP_SECP224K1_ENABLED
+#define POLARSSL_ECP_DP_SECP256K1_ENABLED
 #define POLARSSL_ECP_DP_BP256R1_ENABLED
 #define POLARSSL_ECP_DP_BP384R1_ENABLED
 #define POLARSSL_ECP_DP_BP512R1_ENABLED
+//#define POLARSSL_ECP_DP_M221_ENABLED  // Not implemented yet!
+#define POLARSSL_ECP_DP_M255_ENABLED
+//#define POLARSSL_ECP_DP_M383_ENABLED  // Not implemented yet!
+//#define POLARSSL_ECP_DP_M511_ENABLED  // Not implemented yet!
 
 /**
  * \def POLARSSL_ECP_NIST_OPTIM
  */
 #define POLARSSL_ECP_NIST_OPTIM
 
+/**
+ * \def POLARSSL_ECDSA_DETERMINISTIC
+ *
+ * Enable deterministic ECDSA (RFC 6979).
+ * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
+ * may result in a compromise of the long-term signing key. This is avoided by
+ * the deterministic variant.
+ *
+ * Requires: POLARSSL_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define POLARSSL_ECDSA_DETERMINISTIC
+
 /**
  * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED
  *
  */
 #define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ *
+ * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+
+/**
+ * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED
+ *
+ * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED
+
+/**
+ * \def POLARSSL_PK_PARSE_EC_EXTENDED
+ *
+ * Enhance support for reading EC keys using variants of SEC1 not allowed by
+ * RFC 5915 and RFC 5480.
+ *
+ * Currently this means parsing the SpecifiedECDomain choice of EC
+ * parameters (only known groups are supported, not arbitrary domains, to
+ * avoid validation issues).
+ *
+ * Disable if you only need to support RFC 5915 + 5480 key formats.
+ */
+#define POLARSSL_PK_PARSE_EC_EXTENDED
+
 /**
  * \def POLARSSL_ERROR_STRERROR_BC
  *
  * Make available the backward compatible error_strerror() next to the
  * current polarssl_strerror().
  *
+ * For new code, it is recommended to use polarssl_strerror() instead and
+ * disable this.
+ *
  * Disable if you run into name conflicts and want to really remove the
  * error_strerror()
  */
  * \def POLARSSL_ERROR_STRERROR_DUMMY
  *
  * Enable a dummy error function to make use of polarssl_strerror() in
- * third party libraries easier.
+ * third party libraries easier when POLARSSL_ERROR_C is disabled
+ * (no effect when POLARSSL_ERROR_C is enabled).
+ *
+ * You can safely disable this if POLARSSL_ERROR_C is enabled, or if you're
+ * not using polarssl_strerror() or error_strerror() in your application.
  *
  * Disable if you run into name conflicts and want to really remove the
  * polarssl_strerror()
  * Do not add default entropy sources. These are the platform specific,
  * hardclock and HAVEGE based poll functions.
  *
- * This is useful to have more control over the added entropy sources in an 
+ * This is useful to have more control over the added entropy sources in an
  * application.
  *
  * Uncomment this macro to prevent loading of default entropy functions.
  */
 //#define POLARSSL_NO_PLATFORM_ENTROPY
 
+/**
+ * \def POLARSSL_ENTROPY_FORCE_SHA256
+ *
+ * Force the entropy accumulator to use a SHA-256 accumulator instead of the
+ * default SHA-512 based one (if both are available).
+ *
+ * Requires: POLARSSL_SHA256_C
+ *
+ * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
+ * if you have performance concerns.
+ *
+ * This option is only useful if both POLARSSL_SHA256_C and
+ * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define POLARSSL_ENTROPY_FORCE_SHA256
+
 /**
  * \def POLARSSL_MEMORY_DEBUG
  *
  * function for 'debug output' of allocated memory.
  *
  * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C
- *           fprintf()
  *
  * Uncomment this macro to let the buffer allocator print out error messages.
  */
  */
 #define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
 
+/**
+ * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+ *
+ * Pick the ciphersuite according to the client's preferences rather than ours
+ * in the SSL Server module (POLARSSL_SSL_SRV_C).
+ *
+ * Uncomment this macro to respect client's ciphersuite order
+ */
+//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+
 /**
  * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH
  *
  */
 #define POLARSSL_SSL_PROTO_TLS1_2
 
+/**
+ * \def POLARSSL_SSL_ALPN
+ *
+ * Enable support for Application Layer Protocol Negotiation.
+ * draft-ietf-tls-applayerprotoneg-05
+ *
+ * Comment this macro to disable support for ALPN.
+ */
+#define POLARSSL_SSL_ALPN
+
 /**
  * \def POLARSSL_SSL_SESSION_TICKETS
  *
 #define POLARSSL_SSL_TRUNCATED_HMAC
 
 /**
- * \def POLARSSL_THREADING_ALT
+ * \def POLARSSL_SSL_SET_CURVES
  *
- * Provide your own alternate threading implementation.
+ * Enable ssl_set_curves().
  *
- * Requires: POLARSSL_THREADING_C
+ * This is disabled by default since it breaks binary compatibility with the
+ * 1.3.x line. If you choose to enable it, you will need to rebuild your
+ * application against the new header files, relinking will not be enough.
+ * It will be enabled by default, or no longer an option, in the 1.4 branch.
  *
- * Uncomment this to allow your own alternate threading implementation.
+ * Uncomment to make ssl_set_curves() available.
  */
-//#define POLARSSL_THREADING_ALT
+//#define POLARSSL_SSL_SET_CURVES
 
 /**
- * \def POLARSSL_THREADING_DUMMY
+ * \def POLARSSL_THREADING_ALT
  *
- * Provide a dummy threading implementation.
- * Warning: If you use this, all claims of thread-safety in the documentation
- *          are void!
+ * Provide your own alternate threading implementation.
  *
  * Requires: POLARSSL_THREADING_C
  *
- * Uncomment this to enable code to compile like with threading enabled
+ * Uncomment this to allow your own alternate threading implementation.
  */
-//#define POLARSSL_THREADING_DUMMY
+//#define POLARSSL_THREADING_ALT
 
 /**
  * \def POLARSSL_THREADING_PTHREAD
  */
 //#define POLARSSL_THREADING_PTHREAD
 
+/**
+ * \def POLARSSL_VERSION_FEATURES
+ *
+ * Allow run-time checking of compile-time enabled features. Thus allowing users
+ * to check at run-time if the library is for instance compiled with threading
+ * support via version_check_feature().
+ *
+ * Requires: POLARSSL_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+#define POLARSSL_VERSION_FEATURES
+
 /**
  * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3
  *
  */
 //#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
 
+/**
+ * \def POLARSSL_X509_CHECK_KEY_USAGE
+ *
+ * Enable verification of the keyUsage extension (CA and leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused
+ * (intermediate) CA and leaf certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip keyUsage checking for both CA and leaf certificates.
+ */
+#define POLARSSL_X509_CHECK_KEY_USAGE
+
+/**
+ * \def POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE
+ *
+ * Enable verification of the extendedKeyUsage extension (leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip extendedKeyUsage checking for certificates.
+ */
+#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE
+
+/**
+ * \def POLARSSL_X509_RSASSA_PSS_SUPPORT
+ *
+ * Enable parsing and verification of X.509 certificates, CRLs and CSRS
+ * signed with RSASSA-PSS (aka PKCS#1 v2.1).
+ *
+ * Comment this macro to disallow using RSASSA-PSS in certificates.
+ */
+#define POLARSSL_X509_RSASSA_PSS_SUPPORT
+
 /**
  * \def POLARSSL_ZLIB_SUPPORT
  *
  * If set, the SSL/TLS module uses ZLIB to support compression and
  * decompression of packet data.
  *
+ * \warning TLS-level compression MAY REDUCE SECURITY! See for example the
+ * CRIME attack. Before enabling this option, you should examine with care if
+ * CRIME or similar exploits may be a applicable to your use case.
+ *
  * Used in: library/ssl_tls.c
  *          library/ssl_cli.c
  *          library/ssl_srv.c
  * \{
  */
 
+/**
+ * \def POLARSSL_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module:  library/aesni.c
+ * Caller:  library/aes.c
+ *
+ * Requires: POLARSSL_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+#define POLARSSL_AESNI_C
+
 /**
  * \def POLARSSL_AES_C
  *
  *
  * This module enables the following ciphersuites (if other requisites are
  * enabled as well):
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
  *      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  *      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  *      TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
  *
  * This module enables the following ciphersuites (if other requisites are
  * enabled as well):
+ *      TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      TLS_ECDH_RSA_WITH_RC4_128_SHA
  *      TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
  *      TLS_ECDHE_RSA_WITH_RC4_128_SHA
  *      TLS_ECDHE_PSK_WITH_RC4_128_SHA
  * Module:  library/bignum.c
  * Caller:  library/dhm.c
  *          library/ecp.c
+ *          library/ecdsa.c
  *          library/rsa.c
  *          library/ssl_tls.c
  *
- * This module is required for RSA and DHM support.
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
  */
 #define POLARSSL_BIGNUM_C
 
  *
  * This module enables the following ciphersuites (if other requisites are
  * enabled as well):
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
  *      TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
  *      TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
  *      TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
  */
 #define POLARSSL_CAMELLIA_C
 
+/**
+ * \def POLARSSL_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module:  library/ccm.c
+ *
+ * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C
+ *
+ * This module enables the AES-CCM ciphersuites, if other requisites are
+ * enabled as well.
+ */
+#define POLARSSL_CCM_C
+
 /**
  * \def POLARSSL_CERTS_C
  *
  *
  * This module enables the following ciphersuites (if other requisites are
  * enabled as well):
+ *      TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
  *      TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
  *      TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
  *      TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
  * Module:  library/entropy.c
  * Caller:
  *
- * Requires: POLARSSL_SHA512_C
+ * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C
  *
  * This module provides a generic entropy pool
  */
  * Module:  library/error.c
  * Caller:
  *
- * This module enables err_strerror().
+ * This module enables polarssl_strerror().
  */
 #define POLARSSL_ERROR_C
 
  */
 //#define POLARSSL_HAVEGE_C
 
+/**
+ * \def POLARSSL_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module:  library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: POLARSSL_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define POLARSSL_HMAC_DRBG_C
+
 /**
  * \def POLARSSL_MD_C
  *
 
 /**
  * \def POLARSSL_MEMORY_C
- *
- * Enable the memory allocation layer.
- * By default PolarSSL uses the system-provided malloc() and free().
- * (As long as POLARSSL_MEMORY_STDMALLOC and POLARSSL_MEMORY_STDFREE
- * are defined and unmodified)
- *
- * This allows different allocators (self-implemented or provided)
- *
- * Enable this layer to allow use of alternative memory allocators.
+ * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead.
  */
 //#define POLARSSL_MEMORY_C
 
  *
  * Module:  library/memory_buffer_alloc.c
  *
- * Requires: POLARSSL_MEMORY_C
+ * Requires: POLARSSL_PLATFORM_C
+ *           POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL)
  *
  * Enable this module to enable the buffer memory allocator.
  */
  * Module:  library/padlock.c
  * Caller:  library/aes.c
  *
+ * Requires: POLARSSL_HAVE_ASM
+ *
  * This modules adds support for the VIA PadLock on x86.
  */
 #define POLARSSL_PADLOCK_C
  */
 #define POLARSSL_PKCS12_C
 
+/**
+ * \def POLARSSL_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like malloc(), free(), printf(), fprintf()
+ *
+ * Module:  library/platform.c
+ * Caller:  Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define POLARSSL_PLATFORM_C
+
+/**
+ * \def POLARSSL_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module:  library/ripemd160.c
+ * Caller:  library/md.c
+ *
+ */
+#define POLARSSL_RIPEMD160_C
+
 /**
  * \def POLARSSL_RSA_C
  *
  * This allows different threading implementations (self-implemented or
  * provided).
  *
- * You will have to enable either POLARSSL_THREADING_ALT,
- * POLARSSL_THREADING_PTHREAD or POLARSSL_THREADING_DUMMY.
+ * You will have to enable either POLARSSL_THREADING_ALT or
+ * POLARSSL_THREADING_PTHREAD.
  *
  * Enable this layer to allow use of mutexes within PolarSSL
  */
  * This section allows for the setting of module specific sizes and
  * configuration options. The default values are already present in the
  * relevant header files and should suffice for the regular use cases.
- * Our advice is to enable POLARSSL_CONFIG_OPTIONS and change values here
- * only if you have a good reason and know the consequences.
  *
- * If POLARSSL_CONFIG_OPTIONS is undefined here the options in the module
- * header file take precedence.
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
  *
  * Please check the respective header file for documentation on these
  * parameters (to prevent duplicate documentation).
- *
- * Uncomment POLARSSL_CONFIG_OPTIONS to enable using the values defined here.
  * \{
  */
-//#define POLARSSL_CONFIG_OPTIONS   /**< Enable config.h module value configuration */
 
-#if defined(POLARSSL_CONFIG_OPTIONS)
+/* MPI / BIGNUM options */
+//#define POLARSSL_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
+//#define POLARSSL_MPI_MAX_SIZE             512 /**< Maximum number of bytes for usable MPIs. */
 
-// MPI / BIGNUM options
-//
-#define POLARSSL_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
-#define POLARSSL_MPI_MAX_SIZE             512 /**< Maximum number of bytes for usable MPIs. */
+/* CTR_DRBG options */
+//#define CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+//#define CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
+//#define CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
+//#define CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
+//#define CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
 
-// CTR_DRBG options
-//
-#define CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
-#define CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
-#define CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
-#define CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
-#define CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
+/* HMAC_DRBG options */
+//#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
+//#define POLARSSL_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */
+//#define POLARSSL_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */
+//#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
 
-// Entropy options
-//
-#define ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
-#define ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
+/* ECP options */
+//#define POLARSSL_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
+//#define POLARSSL_ECP_WINDOW_SIZE            6 /**< Maximum window size used */
+//#define POLARSSL_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */
 
-// Memory options
-#define MEMORY_ALIGN_MULTIPLE               4 /**< Align on multiples of this value */
-#define POLARSSL_MEMORY_STDMALLOC      malloc /**< Default allocator to use, can be undefined */
-#define POLARSSL_MEMORY_STDFREE          free /**< Default free to use, can be undefined */
+/* Entropy options */
+//#define ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
+//#define ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
 
-// SSL Cache options
-//
-#define SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
-#define SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
+/* Memory buffer allocator options */
+//#define POLARSSL_MEMORY_ALIGN_MULTIPLE      4 /**< Align on multiples of this value */
 
-// SSL options
-//
-#define SSL_MAX_CONTENT_LEN             16384 /**< Size of the input / output buffer */
-#define SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
+/* Platform options */
+//#define POLARSSL_PLATFORM_STD_MEM_HDR <stdlib.h> /**< Header to include if POLARSSL_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define POLARSSL_PLATFORM_STD_MALLOC   malloc /**< Default allocator to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_FREE       free /**< Default free to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_PRINTF   printf /**< Default printf to use, can be undefined */
+//#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */
 
-#endif /* POLARSSL_CONFIG_OPTIONS */
+/* SSL Cache options */
+//#define SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
+//#define SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
 
-/* \} name */
+/* SSL options */
+//#define SSL_MAX_CONTENT_LEN             16384 /**< Size of the input / output buffer */
+//#define SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
+//#define POLARSSL_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
 
-/*
- * Sanity checks on defines and dependencies
+/**
+ * Complete list of ciphersuites to use, in order of preference.
+ *
+ * \warning No dependency checking is done on that field! This option can only
+ * be used to restrict the set of available ciphersuites. It is your
+ * responsibility to make sure the needed modules are active.
+ *
+ * Use this to save a few hundred bytes of ROM (default ordering of all
+ * available ciphersuites) and a few to a few hundred bytes of RAM.
+ *
+ * The value below is only an example, not the default.
  */
-#if defined(POLARSSL_CERTS_C) && !defined(POLARSSL_PEM_PARSE_C)
-#error "POLARSSL_CERTS_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_CTR_DRBG_C) && !defined(POLARSSL_AES_C)
-#error "POLARSSL_CTR_DRBG_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_DHM_C) && !defined(POLARSSL_BIGNUM_C)
-#error "POLARSSL_DHM_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_ECDH_C) && !defined(POLARSSL_ECP_C)
-#error "POLARSSL_ECDH_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_ECDSA_C) &&            \
-    ( !defined(POLARSSL_ECP_C) ||           \
-      !defined(POLARSSL_ASN1_PARSE_C) ||    \
-      !defined(POLARSSL_ASN1_WRITE_C) )
-#error "POLARSSL_ECDSA_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_ECP_C) && ( !defined(POLARSSL_BIGNUM_C) || (   \
-    !defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) &&                  \
-    !defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) &&                  \
-    !defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) &&                  \
-    !defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) &&                  \
-    !defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) &&                  \
-    !defined(POLARSSL_ECP_DP_BP256R1_ENABLED)   &&                  \
-    !defined(POLARSSL_ECP_DP_BP384R1_ENABLED)   &&                  \
-    !defined(POLARSSL_ECP_DP_BP512R1_ENABLED) ) )
-#error "POLARSSL_ECP_C defined, but not all prerequisites"
-#endif
+//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 
-#if defined(POLARSSL_ENTROPY_C) && (!defined(POLARSSL_SHA512_C) &&      \
-                                    !defined(POLARSSL_SHA256_C))
-#error "POLARSSL_ENTROPY_C defined, but not all prerequisites"
-#endif
-#if defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_SHA512_C) &&         \
-    defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 64)
-#error "CTR_DRBG_ENTROPY_LEN value too high"
-#endif
-#if defined(POLARSSL_ENTROPY_C) && !defined(POLARSSL_SHA512_C) &&        \
-    defined(POLARSSL_CONFIG_OPTIONS) && (CTR_DRBG_ENTROPY_LEN > 32)
-#error "CTR_DRBG_ENTROPY_LEN value too high"
-#endif
+/* Debug options */
+//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */
 
-#if defined(POLARSSL_GCM_C) && (                                        \
-        !defined(POLARSSL_AES_C) && !defined(POLARSSL_CAMELLIA_C) )
-#error "POLARSSL_GCM_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_HAVEGE_C) && !defined(POLARSSL_TIMING_C)
-#error "POLARSSL_HAVEGE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(POLARSSL_DHM_C)
-#error "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) &&                     \
-    !defined(POLARSSL_ECDH_C)
-#error "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) &&                   \
-    ( !defined(POLARSSL_DHM_C) || !defined(POLARSSL_RSA_C) ||           \
-      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
-#error "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) &&                 \
-    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_RSA_C) ||          \
-      !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_PKCS1_V15) )
-#error "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                 \
-    ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_ECDSA_C) ||          \
-      !defined(POLARSSL_X509_CRT_PARSE_C) )
-#error "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
-#endif
+/* \} name SECTION: Module configuration options */
 
-#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED) &&                   \
-    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
-      !defined(POLARSSL_PKCS1_V15) )
-#error "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) &&                       \
-    ( !defined(POLARSSL_RSA_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ||\
-      !defined(POLARSSL_PKCS1_V15) )
-#error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) && !defined(POLARSSL_MEMORY_C)
-#error "POLARSSL_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_PBKDF2_C) && !defined(POLARSSL_MD_C)
-#error "POLARSSL_PBKDF2_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_PEM_PARSE_C) && !defined(POLARSSL_BASE64_C)
-#error "POLARSSL_PEM_PARSE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_PEM_WRITE_C) && !defined(POLARSSL_BASE64_C)
-#error "POLARSSL_PEM_WRITE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_PK_PARSE_C) && !defined(POLARSSL_PK_C)
-#error "POLARSSL_PK_PARSE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_PK_WRITE_C) && !defined(POLARSSL_PK_C)
-#error "POLARSSL_PK_WRITE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_PK_C)
-#error "POLARSSL_PKCS11_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_RSA_C) && ( !defined(POLARSSL_BIGNUM_C) ||         \
-    !defined(POLARSSL_OID_C) )
-#error "POLARSSL_RSA_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_SSL_PROTO_SSL3) && ( !defined(POLARSSL_MD5_C) ||     \
-    !defined(POLARSSL_SHA1_C) )
-#error "POLARSSL_SSL_PROTO_SSL3 defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_SSL_PROTO_TLS1) && ( !defined(POLARSSL_MD5_C) ||     \
-    !defined(POLARSSL_SHA1_C) )
-#error "POLARSSL_SSL_PROTO_TLS1 defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_SSL_PROTO_TLS1_1) && ( !defined(POLARSSL_MD5_C) ||     \
-    !defined(POLARSSL_SHA1_C) )
-#error "POLARSSL_SSL_PROTO_TLS1_1 defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_SSL_PROTO_TLS1_2) && ( !defined(POLARSSL_SHA1_C) &&     \
-    !defined(POLARSSL_SHA256_C) && !defined(POLARSSL_SHA512_C) )
-#error "POLARSSL_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_SSL_CLI_C) && !defined(POLARSSL_SSL_TLS_C)
-#error "POLARSSL_SSL_CLI_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_SSL_TLS_C) && ( !defined(POLARSSL_CIPHER_C) ||     \
-    !defined(POLARSSL_MD_C) )
-#error "POLARSSL_SSL_TLS_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_SSL_SRV_C) && !defined(POLARSSL_SSL_TLS_C)
-#error "POLARSSL_SSL_SRV_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_SSL_TLS_C) && (!defined(POLARSSL_SSL_PROTO_SSL3) && \
-    !defined(POLARSSL_SSL_PROTO_TLS1) && !defined(POLARSSL_SSL_PROTO_TLS1_1) && \
-    !defined(POLARSSL_SSL_PROTO_TLS1_2))
-#error "POLARSSL_SSL_TLS_C defined, but no protocols are active"
-#endif
-
-#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
-    defined(POLARSSL_SSL_PROTO_TLS1_1) && !defined(POLARSSL_SSL_PROTO_TLS1))
-#error "Illegal protocol selection"
-#endif
-
-#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_TLS1) && \
-    defined(POLARSSL_SSL_PROTO_TLS1_2) && !defined(POLARSSL_SSL_PROTO_TLS1_1))
-#error "Illegal protocol selection"
-#endif
-
-#if defined(POLARSSL_SSL_TLS_C) && (defined(POLARSSL_SSL_PROTO_SSL3) && \
-    defined(POLARSSL_SSL_PROTO_TLS1_2) && (!defined(POLARSSL_SSL_PROTO_TLS1) || \
-    !defined(POLARSSL_SSL_PROTO_TLS1_1)))
-#error "Illegal protocol selection"
-#endif
-
-#if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \
-    ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) ||            \
-      !defined(POLARSSL_CIPHER_MODE_CBC) )
-#error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_THREADING_DUMMY)
-#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
-#error "POLARSSL_THREADING_DUMMY defined, but not all prerequisites"
-#endif
-#define POLARSSL_THREADING_IMPL
-#endif
-
-#if defined(POLARSSL_THREADING_PTHREAD)
-#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
-#error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites"
-#endif
-#define POLARSSL_THREADING_IMPL
-#endif
-
-#if defined(POLARSSL_THREADING_ALT)
-#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
-#error "POLARSSL_THREADING_ALT defined, but not all prerequisites"
-#endif
-#define POLARSSL_THREADING_IMPL
-#endif
-
-#if defined(POLARSSL_THREADING_C) && !defined(POLARSSL_THREADING_IMPL)
-#error "POLARSSL_THREADING_C defined, single threading implementation required"
-#endif
-#undef POLARSSL_THREADING_IMPL
-
-#if defined(POLARSSL_X509_USE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
-    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_PARSE_C) ||      \
-    !defined(POLARSSL_PK_PARSE_C) )
-#error "POLARSSL_X509_USE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_X509_CREATE_C) && ( !defined(POLARSSL_BIGNUM_C) ||  \
-    !defined(POLARSSL_OID_C) || !defined(POLARSSL_ASN1_WRITE_C) ||       \
-    !defined(POLARSSL_PK_WRITE_C) )
-#error "POLARSSL_X509_CREATE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_X509_CRT_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
-#error "POLARSSL_X509_CRT_PARSE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_X509_CRL_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
-#error "POLARSSL_X509_CRL_PARSE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_X509_CSR_PARSE_C) && ( !defined(POLARSSL_X509_USE_C) )
-#error "POLARSSL_X509_CSR_PARSE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_X509_CRT_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
-#error "POLARSSL_X509_CRT_WRITE_C defined, but not all prerequisites"
-#endif
-
-#if defined(POLARSSL_X509_CSR_WRITE_C) && ( !defined(POLARSSL_X509_CREATE_C) )
-#error "POLARSSL_X509_CSR_WRITE_C defined, but not all prerequisites"
-#endif
+#include "check_config.h"
 
-#endif /* config.h */
+#endif /* POLARSSL_CONFIG_H */
index 756b5a32610fa973d8deab44980da71e864847ac..bebbfe93118ef546e1732c2bc3cbf90e18907268 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief CTR_DRBG based on AES-256 (NIST SP 800-90)
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #define CTR_DRBG_SEEDLEN            ( CTR_DRBG_KEYSIZE + CTR_DRBG_BLOCKSIZE )
                                             /**< The seed length (counter + AES key)            */
 
-#if !defined(POLARSSL_CONFIG_OPTIONS)
-#if defined(POLARSSL_SHA512_C)
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(CTR_DRBG_ENTROPY_LEN)
+#if defined(POLARSSL_SHA512_C) && !defined(POLARSSL_ENTROPY_FORCE_SHA256)
 #define CTR_DRBG_ENTROPY_LEN        48      /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
 #else
 #define CTR_DRBG_ENTROPY_LEN        32      /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
 #endif
+#endif
+
+#if !defined(CTR_DRBG_RESEED_INTERVAL)
 #define CTR_DRBG_RESEED_INTERVAL    10000   /**< Interval before reseed is performed by default */
+#endif
+
+#if !defined(CTR_DRBG_MAX_INPUT)
 #define CTR_DRBG_MAX_INPUT          256     /**< Maximum number of additional input bytes */
+#endif
+
+#if !defined(CTR_DRBG_MAX_REQUEST)
 #define CTR_DRBG_MAX_REQUEST        1024    /**< Maximum number of requested bytes per call */
+#endif
+
+#if !defined(CTR_DRBG_MAX_SEED_INPUT)
 #define CTR_DRBG_MAX_SEED_INPUT     384     /**< Maximum size of (re)seed buffer */
-#endif /* !POLARSSL_CONFIG_OPTIONS */
+#endif
+
+/* \} name SECTION: Module settings */
 
 #define CTR_DRBG_PR_OFF             0       /**< No prediction resistance       */
 #define CTR_DRBG_PR_ON              1       /**< Prediction resistance enabled  */
@@ -69,8 +91,9 @@ typedef struct
     unsigned char counter[16];  /*!<  counter (V)       */
     int reseed_counter;         /*!<  reseed counter    */
     int prediction_resistance;  /*!<  enable prediction resistance (Automatic
-                                      reseed before every random generation)        */
-    size_t entropy_len;         /*!<  amount of entropy grabbed on each (re)seed    */
+                                      reseed before every random generation)  */
+    size_t entropy_len;         /*!<  amount of entropy grabbed on each
+                                      (re)seed          */
     int reseed_interval;        /*!<  reseed interval   */
 
     aes_context aes_ctx;        /*!<  AES context       */
@@ -86,7 +109,7 @@ ctr_drbg_context;
 
 /**
  * \brief               CTR_DRBG initialization
- * 
+ *
  * Note: Personalization data can be provided in addition to the more generic
  *       entropy source to make this instantiation as unique as possible.
  *
@@ -107,6 +130,13 @@ int ctr_drbg_init( ctr_drbg_context *ctx,
                    const unsigned char *custom,
                    size_t len );
 
+/**
+ * \brief               Clear CTR_CRBG context data
+ *
+ * \param ctx           CTR_DRBG context to clear
+ */
+void ctr_drbg_free( ctr_drbg_context *ctx );
+
 /**
  * \brief               Enable / disable prediction resistance (Default: Off)
  *
@@ -141,7 +171,7 @@ void ctr_drbg_set_reseed_interval( ctr_drbg_context *ctx,
 
 /**
  * \brief               CTR_DRBG reseeding (extracts data from entropy source)
- * 
+ *
  * \param ctx           CTR_DRBG context
  * \param additional    Additional data to add to state (Can be NULL)
  * \param len           Length of additional data
@@ -204,7 +234,8 @@ int ctr_drbg_random( void *p_rng,
  * \param ctx           CTR_DRBG context
  * \param path          Name of the file
  *
- * \return              0 if successful, 1 on file error, or
+ * \return              0 if successful,
+ *                      POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or
  *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
  */
 int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path );
@@ -216,12 +247,13 @@ int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path );
  * \param ctx           CTR_DRBG context
  * \param path          Name of the file
  *
- * \return              0 if successful, 1 on file error,
+ * \return              0 if successful,
+ *                      POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR on file error,
  *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
  *                      POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG
  */
 int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path );
-#endif
+#endif /* POLARSSL_FS_IO */
 
 /**
  * \brief               Checkup routine
@@ -231,7 +263,9 @@ int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path );
 int ctr_drbg_self_test( int verbose );
 
 /* Internal functions (do not call directly) */
-int ctr_drbg_init_entropy_len( ctr_drbg_context *, int (*)(void *, unsigned char *, size_t), void *, const unsigned char *, size_t, size_t );
+int ctr_drbg_init_entropy_len( ctr_drbg_context *,
+                               int (*)(void *, unsigned char *, size_t), void *,
+                               const unsigned char *, size_t, size_t );
 
 #ifdef __cplusplus
 }
index 7335ad372f5956b424dffc0e0fbf14ae493cf828..0dd79d52f04fbd8b1c3d1d86988edf43d6cf5f9c 100644 (file)
 #ifndef POLARSSL_DEBUG_H
 #define POLARSSL_DEBUG_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 #include "ssl.h"
 #if defined(POLARSSL_ECP_C)
 #include "ecp.h"
 
 #if defined(POLARSSL_DEBUG_C)
 
+#define POLARSSL_DEBUG_LOG_FULL         0 /**< Include file:line in log lines */
+#define POLARSSL_DEBUG_LOG_RAW          1 /**< Only log raw debug lines */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(POLARSSL_DEBUG_DFL_MODE)
+#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */
+#endif
+
+/* \} name SECTION: Module settings */
+
+
 #define SSL_DEBUG_MSG( level, args )                    \
     debug_print_msg( ssl, level, __FILE__, __LINE__, debug_fmt args );
 
@@ -59,7 +81,7 @@
     debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt );
 #endif
 
-#else
+#else /* POLARSSL_DEBUG_C */
 
 #define SSL_DEBUG_MSG( level, args )            do { } while( 0 )
 #define SSL_DEBUG_RET( level, text, ret )       do { } while( 0 )
 #define SSL_DEBUG_ECP( level, text, X )         do { } while( 0 )
 #define SSL_DEBUG_CRT( level, text, crt )       do { } while( 0 )
 
-#endif
+#endif /* POLARSSL_DEBUG_C */
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/**
+ * \brief   Set the log mode for the debug functions globally
+ *          (Default value: POLARSSL_DEBUG_DFL_MODE)
+ *
+ * \param log_mode      The log mode to use (POLARSSL_DEBUG_LOG_FULL or
+ *                                           POLARSSL_DEBUG_LOG_RAW)
+ */
+void debug_set_log_mode( int log_mode );
+
+/**
+ * \brief   Set the level threshold to handle globally. Messages that have a
+ *          level over the threshold value are ignored.
+ *          (Default value: 0 (No debug))
+ *
+ * \param threshold     maximum level of messages to pass on
+ */
+void debug_set_threshold( int threshold );
+
 char *debug_fmt( const char *format, ... );
 
 void debug_print_msg( const ssl_context *ssl, int level,
index d29bd1dee08e69e5e208cc17b5515c452d892282..89bb394e01728bf13291ac8ae2dcd6a68e49fdb6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief DES block cipher
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_DES_H
 #define POLARSSL_DES_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -73,6 +77,34 @@ typedef struct
 }
 des3_context;
 
+/**
+ * \brief          Initialize DES context
+ *
+ * \param ctx      DES context to be initialized
+ */
+void des_init( des_context *ctx );
+
+/**
+ * \brief          Clear DES context
+ *
+ * \param ctx      DES context to be cleared
+ */
+void des_free( des_context *ctx );
+
+/**
+ * \brief          Initialize Triple-DES context
+ *
+ * \param ctx      DES3 context to be initialized
+ */
+void des3_init( des3_context *ctx );
+
+/**
+ * \brief          Clear Triple-DES context
+ *
+ * \param ctx      DES3 context to be cleared
+ */
+void des3_free( des3_context *ctx );
+
 /**
  * \brief          Set key parity on the given key to odd.
  *
@@ -132,7 +164,8 @@ int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
  *
  * \return         0
  */
-int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+int des3_set2key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] );
 
 /**
  * \brief          Triple-DES key schedule (112-bit, decryption)
@@ -142,7 +175,8 @@ int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE *
  *
  * \return         0
  */
-int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+int des3_set2key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] );
 
 /**
  * \brief          Triple-DES key schedule (168-bit, encryption)
@@ -152,7 +186,8 @@ int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE *
  *
  * \return         0
  */
-int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+int des3_set3key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] );
 
 /**
  * \brief          Triple-DES key schedule (168-bit, decryption)
@@ -162,7 +197,8 @@ int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE *
  *
  * \return         0
  */
-int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+int des3_set3key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] );
 
 /**
  * \brief          DES-ECB block encryption/decryption
index 4665ff9f97281afc403cb2f8e2e8e9a2703d6422..064472f3589ab96405f9b5b67149384037e1e616 100644 (file)
@@ -43,6 +43,8 @@
 #define POLARSSL_ERR_DHM_FILE_IO_ERROR                     -0x3480  /**< Read/write of file failed. */
 
 /**
+ * RFC 2409 defines a number of standardized Diffie-Hellman groups
+ * that can be used.
  * RFC 3526 defines a number of standardized Diffie-Hellman groups
  * for IKE.
  * RFC 5114 defines a number of standardized Diffie-Hellman groups
  * Some are included here for convenience.
  *
  * Included are:
+ *  RFC 2409 6.2.  1024-bit MODP Group (Second Oakley Group)
  *  RFC 3526 3.    2048-bit MODP Group
  *  RFC 3526 4.    3072-bit MODP Group
  *  RFC 5114 2.1.  1024-bit MODP Group with 160-bit Prime Order Subgroup
  *  RFC 5114 2.2.  2048-bit MODP Group with 224-bit Prime Order Subgroup
  */
+#define POLARSSL_DHM_RFC2409_MODP_1024_P               \
+    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
+    "FFFFFFFFFFFFFFFF"
+
+#define POLARSSL_DHM_RFC2409_MODP_1024_G          "02"
+
 #define POLARSSL_DHM_RFC3526_MODP_2048_P               \
     "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
     "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
@@ -156,6 +169,13 @@ typedef struct
 }
 dhm_context;
 
+/**
+ * \brief          Initialize DHM context
+ *
+ * \param ctx      DHM context to be initialized
+ */
+void dhm_init( dhm_context *ctx );
+
 /**
  * \brief          Parse the ServerKeyExchange parameters
  *
@@ -224,7 +244,8 @@ int dhm_make_public( dhm_context *ctx, int x_size,
  *
  * \param ctx      DHM context
  * \param output   destination buffer
- * \param olen     number of chars written
+ * \param olen     on entry, must hold the size of the destination buffer
+ *                 on exit, holds the actual number of bytes written
  * \param f_rng    RNG function, for blinding purposes
  * \param p_rng    RNG parameter
  *
@@ -242,7 +263,9 @@ int dhm_calc_secret( dhm_context *ctx,
                      void *p_rng );
 
 /**
- * \brief          Free the components of a DHM key
+ * \brief          Free and clear the components of a DHM key
+ *
+ * \param ctx      DHM context to free and clear
  */
 void dhm_free( dhm_context *ctx );
 
@@ -285,4 +308,4 @@ int dhm_self_test( int verbose );
 }
 #endif
 
-#endif
+#endif /* dhm.h */
index 4c82f25f2de0d453311fa1244f3c2cbe3894d1ba..525cade98226d333da4a287e4126df3d94158f24 100644 (file)
 extern "C" {
 #endif
 
+/**
+ * When importing from an EC key, select if it is our key or the peer's key
+ */
+typedef enum
+{
+    POLARSSL_ECDH_OURS,
+    POLARSSL_ECDH_THEIRS,
+} ecdh_side;
+
 /**
  * \brief           ECDH context structure
  */
 typedef struct
 {
-    ecp_group grp;      /*!<  ellipitic curve used      */
-    mpi d;              /*!<  our secret value          */
-    ecp_point Q;        /*!<  our public value          */
-    ecp_point Qp;       /*!<  peer's public value       */
-    mpi z;              /*!<  shared secret             */
-    int point_format;   /*!<  format for point export   */
-    ecp_point Vi;       /*!<  blinding value (for later)    */
-    ecp_point Vf;       /*!<  un-blinding value (for later) */
-    mpi _d;             /*!<  previous d                    */
+    ecp_group grp;      /*!<  elliptic curve used                           */
+    mpi d;              /*!<  our secret value (private key)                */
+    ecp_point Q;        /*!<  our public value (public key)                 */
+    ecp_point Qp;       /*!<  peer's public value (public key)              */
+    mpi z;              /*!<  shared secret                                 */
+    int point_format;   /*!<  format for point export in TLS messages       */
+    ecp_point Vi;       /*!<  blinding value (for later)                    */
+    ecp_point Vf;       /*!<  un-blinding value (for later)                 */
+    mpi _d;             /*!<  previous d (for later)                        */
 }
 ecdh_context;
 
 /**
- * \brief           Generate a public key
+ * \brief           Generate a public key.
+ *                  Raw function that only does the core computation.
  *
  * \param grp       ECP group
- * \param d         Destination MPI (secret exponent)
+ * \param d         Destination MPI (secret exponent, aka private key)
  * \param Q         Destination point (public key)
  * \param f_rng     RNG function
  * \param p_rng     RNG parameter
@@ -68,11 +78,12 @@ int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q,
 
 /**
  * \brief           Compute shared secret
+ *                  Raw function that only does the core computation.
  *
  * \param grp       ECP group
  * \param z         Destination MPI (shared secret)
  * \param Q         Public key from other party
- * \param d         Our secret exponent
+ * \param d         Our secret exponent (private key)
  * \param f_rng     RNG function (see notes)
  * \param p_rng     RNG parameter
  *
@@ -103,7 +114,8 @@ void ecdh_init( ecdh_context *ctx );
 void ecdh_free( ecdh_context *ctx );
 
 /**
- * \brief           Setup and write the ServerKeyExhange parameters
+ * \brief           Generate a public key and a TLS ServerKeyExchange payload.
+ *                  (First function used by a TLS server for ECDHE.)
  *
  * \param ctx       ECDH context
  * \param olen      number of chars written
@@ -123,7 +135,8 @@ int ecdh_make_params( ecdh_context *ctx, size_t *olen,
                       void *p_rng );
 
 /**
- * \brief           Parse the ServerKeyExhange parameters
+ * \brief           Parse and procress a TLS ServerKeyExhange payload.
+ *                  (First function used by a TLS client for ECDHE.)
  *
  * \param ctx       ECDH context
  * \param buf       pointer to start of input buffer
@@ -135,7 +148,23 @@ int ecdh_read_params( ecdh_context *ctx,
                       const unsigned char **buf, const unsigned char *end );
 
 /**
- * \brief           Setup and export the client's public value
+ * \brief           Setup an ECDH context from an EC key.
+ *                  (Used by clients and servers in place of the
+ *                  ServerKeyEchange for static ECDH: import ECDH parameters
+ *                  from a certificate's EC key information.)
+ *
+ * \param ctx       ECDH constext to set
+ * \param key       EC key to use
+ * \param side      Is it our key (1) or the peer's key (0) ?
+ *
+ * \return          0 if successful, or an POLARSSL_ERR_ECP_XXX error code
+ */
+int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key,
+                     ecdh_side side );
+
+/**
+ * \brief           Generate a public key and a TLS ClientKeyExchange payload.
+ *                  (Second function used by a TLS client for ECDH(E).)
  *
  * \param ctx       ECDH context
  * \param olen      number of bytes actually written
@@ -152,7 +181,8 @@ int ecdh_make_public( ecdh_context *ctx, size_t *olen,
                       void *p_rng );
 
 /**
- * \brief           Parse and import the client's public value
+ * \brief           Parse and process a TLS ClientKeyExchange payload.
+ *                  (Second function used by a TLS server for ECDH(E).)
  *
  * \param ctx       ECDH context
  * \param buf       start of input buffer
@@ -164,7 +194,8 @@ int ecdh_read_public( ecdh_context *ctx,
                       const unsigned char *buf, size_t blen );
 
 /**
- * \brief           Derive and export the shared secret
+ * \brief           Derive and export the shared secret.
+ *                  (Last function used by both TLS client en servers.)
  *
  * \param ctx       ECDH context
  * \param olen      number of bytes written
@@ -191,4 +222,4 @@ int ecdh_self_test( int verbose );
 }
 #endif
 
-#endif
+#endif /* ecdh.h */
index ee60d26952c5a449af87a95480f8e4dd162641cd..d99a17a28939c4f83138764266de6e6a6a7ff0a6 100644 (file)
 
 #include "ecp.h"
 
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+#include "md.h"
+#endif
+
 /**
  * \brief           ECDSA context structure
  *
@@ -36,7 +40,7 @@
  */
 typedef struct
 {
-    ecp_group grp;      /*!<  ellipitic curve used          */
+    ecp_group grp;      /*!<  elliptic curve used           */
     mpi d;              /*!<  secret signature key          */
     ecp_point Q;        /*!<  public signature key          */
     mpi r;              /*!<  first integer from signature  */
@@ -67,6 +71,27 @@ int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s,
                 const mpi *d, const unsigned char *buf, size_t blen,
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
 
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/**
+ * \brief           Compute ECDSA signature of a previously hashed message
+ *                  (deterministic version)
+ *
+ * \param grp       ECP group
+ * \param r         First output integer
+ * \param s         Second output integer
+ * \param d         Private signing key
+ * \param buf       Message hash
+ * \param blen      Length of buf
+ * \param md_alg    MD algorithm used to hash the message
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ */
+int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s,
+                    const mpi *d, const unsigned char *buf, size_t blen,
+                    md_type_t md_alg );
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
 /**
  * \brief           Verify ECDSA signature of a previously hashed message
  *
@@ -112,6 +137,34 @@ int ecdsa_write_signature( ecdsa_context *ctx,
                            int (*f_rng)(void *, unsigned char *, size_t),
                            void *p_rng );
 
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/**
+ * \brief           Compute ECDSA signature and write it to buffer,
+ *                  serialized as defined in RFC 4492 page 20.
+ *                  Deterministic version, RFC 6979.
+ *                  (Not thread-safe to use same context in multiple threads)
+ *
+ * \param ctx       ECDSA context
+ * \param hash      Message hash
+ * \param hlen      Length of hash
+ * \param sig       Buffer that will hold the signature
+ * \param slen      Length of the signature written
+ * \param md_alg    MD algorithm used to hash the message
+ *
+ * \note            The "sig" buffer must be at least as large as twice the
+ *                  size of the curve used, plus 7 (eg. 71 bytes if a 256-bit
+ *                  curve is used).
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP, POLARSSL_ERR_MPI or
+ *                  POLARSSL_ERR_ASN1 error code
+ */
+int ecdsa_write_signature_det( ecdsa_context *ctx,
+                               const unsigned char *hash, size_t hlen,
+                               unsigned char *sig, size_t *slen,
+                               md_type_t md_alg );
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
 /**
  * \brief           Read and verify an ECDSA signature
  *
@@ -122,7 +175,9 @@ int ecdsa_write_signature( ecdsa_context *ctx,
  * \param slen      Size of sig
  *
  * \return          0 if successful,
- *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid,
+ *                  POLARSSL_ERR_ECP_SIG_LEN_MISTMATCH if the signature is
+ *                  valid but its actual length is less than siglen,
  *                  or a POLARSSL_ERR_ECP or POLARSSL_ERR_MPI error code
  */
 int ecdsa_read_signature( ecdsa_context *ctx,
@@ -178,4 +233,4 @@ int ecdsa_self_test( int verbose );
 }
 #endif
 
-#endif
+#endif /* ecdsa.h */
index 02f6f934948eabb774b20965e1fa9a8654cb6176..7192f1e6c3ea80c3e83b621d4e4ac6a50f4e5657 100644 (file)
@@ -39,6 +39,7 @@
 #define POLARSSL_ERR_ECP_MALLOC_FAILED                     -0x4D80  /**< Memory allocation failed. */
 #define POLARSSL_ERR_ECP_RANDOM_FAILED                     -0x4D00  /**< Generation of random value, such as (ephemeral) key, failed. */
 #define POLARSSL_ERR_ECP_INVALID_KEY                       -0x4C80  /**< Invalid private or public key. */
+#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH                  -0x4C00  /**< Signature is valid but shorter than the user-supplied length. */
 
 #ifdef __cplusplus
 extern "C" {
@@ -64,12 +65,21 @@ typedef enum
     POLARSSL_ECP_DP_BP256R1,        /*!< 256-bits Brainpool curve */
     POLARSSL_ECP_DP_BP384R1,        /*!< 384-bits Brainpool curve */
     POLARSSL_ECP_DP_BP512R1,        /*!< 512-bits Brainpool curve */
+    POLARSSL_ECP_DP_M221,           /*!< (not implemented yet)    */
+    POLARSSL_ECP_DP_M255,           /*!< Curve25519               */
+    POLARSSL_ECP_DP_M383,           /*!< (not implemented yet)    */
+    POLARSSL_ECP_DP_M511,           /*!< (not implemented yet)    */
+    POLARSSL_ECP_DP_SECP192K1,      /*!< 192-bits "Koblitz" curve */
+    POLARSSL_ECP_DP_SECP224K1,      /*!< 224-bits "Koblitz" curve */
+    POLARSSL_ECP_DP_SECP256K1,      /*!< 256-bits "Koblitz" curve */
 } ecp_group_id;
 
 /**
- * Number of supported curves (plus one for NONE)
+ * Number of supported curves (plus one for NONE).
+ *
+ * (Montgomery curves excluded for now.)
  */
-#define POLARSSL_ECP_DP_MAX     9
+#define POLARSSL_ECP_DP_MAX     12
 
 /**
  * Curve information for use by other modules
@@ -102,10 +112,19 @@ ecp_point;
 /**
  * \brief           ECP group structure
  *
- * The curves we consider are defined by y^2 = x^3 + A x + B mod P,
- * and a generator for a large subgroup of order N is fixed.
+ * We consider two types of curves equations:
+ * 1. Short Weierstrass y^2 = x^3 + A x + B     mod P   (SEC1 + RFC 4492)
+ * 2. Montgomery,       y^2 = x^3 + A x^2 + x   mod P   (M255 + draft)
+ * In both cases, a generator G for a prime-order subgroup is fixed. In the
+ * short weierstrass, this subgroup is actually the whole curve, and its
+ * cardinal is denoted by N.
+ *
+ * In the case of Short Weierstrass curves, our code requires that N is an odd
+ * prime. (Use odd in ecp_mul() and prime in ecdsa_sign() for blinding.)
  *
- * pbits and nbits must be the size of P and N in bits.
+ * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is
+ * the quantity actually used in the formulas. Also, nbits is not the size of N
+ * but the required size for private keys.
  *
  * If modp is NULL, reduction modulo P is done using a generic algorithm.
  * Otherwise, it must point to a function that takes an mpi in the range
@@ -118,18 +137,18 @@ typedef struct
 {
     ecp_group_id id;    /*!<  internal group identifier                     */
     mpi P;              /*!<  prime modulus of the base field               */
-    mpi A;              /*!<  linear term in the equation                   */
-    mpi B;              /*!<  constant term in the equation                 */
-    ecp_point G;        /*!<  generator of the subgroup used                */
-    mpi N;              /*!<  the order of G                                */
+    mpi A;              /*!<  1. A in the equation, or 2. (A + 2) / 4       */
+    mpi B;              /*!<  1. B in the equation, or 2. unused            */
+    ecp_point G;        /*!<  generator of the (sub)group used              */
+    mpi N;              /*!<  1. the order of G, or 2. unused               */
     size_t pbits;       /*!<  number of bits in P                           */
-    size_t nbits;       /*!<  number of bits in N                           */
-    unsigned int h;     /*!<  cofactor (unused now: assume 1)               */
+    size_t nbits;       /*!<  number of bits in 1. P, or 2. private keys    */
+    unsigned int h;     /*!<  internal: 1 if the constants are static       */
     int (*modp)(mpi *); /*!<  function for fast reduction mod P             */
-    int (*t_pre)(ecp_point *, void *);  /*!< currently unused               */
-    int (*t_post)(ecp_point *, void *); /*!< currently unused               */
-    void *t_data;                       /*!< currently unused               */
-    ecp_point *T;       /*!<  pre-computed points for ecp_mul()             */
+    int (*t_pre)(ecp_point *, void *);  /*!< unused                         */
+    int (*t_post)(ecp_point *, void *); /*!< unused                         */
+    void *t_data;                       /*!< unused                         */
+    ecp_point *T;       /*!<  pre-computed points for ecp_mul_comb()        */
     size_t T_size;      /*!<  number for pre-computed points                */
 }
 ecp_group;
@@ -149,24 +168,64 @@ typedef struct
 }
 ecp_keypair;
 
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(POLARSSL_ECP_MAX_BITS)
 /**
  * Maximum size of the groups (that is, of N and P)
  */
-#define POLARSSL_ECP_MAX_BITS     521
+#define POLARSSL_ECP_MAX_BITS     521   /**< Maximum bit size of groups */
+#endif
+
 #define POLARSSL_ECP_MAX_BYTES    ( ( POLARSSL_ECP_MAX_BITS + 7 ) / 8 )
 #define POLARSSL_ECP_MAX_PT_LEN   ( 2 * POLARSSL_ECP_MAX_BYTES + 1 )
 
+#if !defined(POLARSSL_ECP_WINDOW_SIZE)
 /*
- * Maximum window size (actually, NAF width) used for point multipliation.
- * Default: 8.
- * Minimum value: 2. Maximum value: 8.
+ * Maximum "window" size used for point multiplication.
+ * Default: 6.
+ * Minimum value: 2. Maximum value: 7.
  *
  * Result is an array of at most ( 1 << ( POLARSSL_ECP_WINDOW_SIZE - 1 ) )
- * points used for point multiplication.
+ * points used for point multiplication. This value is directly tied to EC
+ * peak memory usage, so decreasing it by one should roughly cut memory usage
+ * by two (if large curves are in use).
  *
- * Reduction in size may reduce speed for big curves.
+ * Reduction in size may reduce speed, but larger curves are impacted first.
+ * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1):
+ *      w-size:     6       5       4       3       2
+ *      521       145     141     135     120      97
+ *      384       214     209     198     177     146
+ *      256       320     320     303     262     226
+
+ *      224       475     475     453     398     342
+ *      192       640     640     633     587     476
  */
-#define POLARSSL_ECP_WINDOW_SIZE    8   /**< Maximum NAF width used. */
+#define POLARSSL_ECP_WINDOW_SIZE    6   /**< Maximum window size used */
+#endif /* POLARSSL_ECP_WINDOW_SIZE */
+
+#if !defined(POLARSSL_ECP_FIXED_POINT_OPTIM)
+/*
+ * Trade memory for speed on fixed-point multiplication.
+ *
+ * This speeds up repeated multiplication of the generator (that is, the
+ * multiplication in ECDSA signatures, and half of the multiplications in
+ * ECDSA verification and ECDHE) by a factor roughly 3 to 4.
+ *
+ * The cost is increasing EC peak memory usage by a factor roughly 2.
+ *
+ * Change this value to 0 to reduce peak memory usage.
+ */
+#define POLARSSL_ECP_FIXED_POINT_OPTIM  1   /**< Enable fixed-point speed-up */
+#endif /* POLARSSL_ECP_FIXED_POINT_OPTIM */
+
+/* \} name SECTION: Module settings */
 
 /*
  * Point formats, from RFC 4492's enum ECPointFormat
@@ -180,12 +239,22 @@ ecp_keypair;
 #define POLARSSL_ECP_TLS_NAMED_CURVE    3   /**< ECCurveType's named_curve */
 
 /**
- * \brief           Return the list of supported curves with associated info
+ * \brief           Get the list of supported curves in order of preferrence
+ *                  (full information)
  *
  * \return          A statically allocated array, the last entry is 0.
  */
 const ecp_curve_info *ecp_curve_list( void );
 
+/**
+ * \brief           Get the list of supported curves in order of preferrence
+ *                  (grp_id only)
+ *
+ * \return          A statically allocated array,
+ *                  terminated with POLARSSL_ECP_DP_NONE.
+ */
+const ecp_group_id *ecp_grp_id_list( void );
+
 /**
  * \brief           Get curve information from an internal group identifier
  *
@@ -198,12 +267,21 @@ const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id );
 /**
  * \brief           Get curve information from a TLS NamedCurve value
  *
- * \param grp_id    A POLARSSL_ECP_DP_XXX value
+ * \param tls_id    A POLARSSL_ECP_DP_XXX value
  *
  * \return          The associated curve information or NULL
  */
 const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id );
 
+/**
+ * \brief           Get curve information from a human-readable name
+ *
+ * \param name      The name
+ *
+ * \return          The associated curve information or NULL
+ */
+const ecp_curve_info *ecp_curve_info_from_name( const char *name );
+
 /**
  * \brief           Initialize a point (as zero)
  */
@@ -315,8 +393,10 @@ int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P,
  * \param ilen      Actual length of input
  *
  * \return          0 if successful,
- *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid
- *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if input is invalid,
+ *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed,
+ *                  POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE if the point format
+ *                  is not implemented.
  *
  * \note            This function does NOT check that the point actually
  *                  belongs to the given group, see ecp_check_pubkey() for
@@ -429,6 +509,9 @@ int ecp_tls_write_group( const ecp_group *grp, size_t *olen,
  *
  * \return          0 if successful,
  *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ *
+ * \note            This function does not support Montgomery curves, such as
+ *                  Curve25519.
  */
 int ecp_add( const ecp_group *grp, ecp_point *R,
              const ecp_point *P, const ecp_point *Q );
@@ -443,6 +526,9 @@ int ecp_add( const ecp_group *grp, ecp_point *R,
  *
  * \return          0 if successful,
  *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
+ *
+ * \note            This function does not support Montgomery curves, such as
+ *                  Curve25519.
  */
 int ecp_sub( const ecp_group *grp, ecp_point *R,
              const ecp_point *P, const ecp_point *Q );
@@ -459,28 +545,24 @@ int ecp_sub( const ecp_group *grp, ecp_point *R,
  * \param p_rng     RNG parameter
  *
  * \return          0 if successful,
+ *                  POLARSSL_ERR_ECP_INVALID_KEY if m is not a valid privkey
+ *                  or P is not a valid pubkey,
  *                  POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed
- *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if m < 0 of m has greater
- *                  bit length than N, the number of points in the group.
- *
- * \note            In order to prevent simple timing attacks, this function
- *                  executes a constant number of operations (that is, point
- *                  doubling and addition of distinct points) for random m in
- *                  the allowed range.
- *
- * \note            If f_rng is not NULL, it is used to randomize projective
- *                  coordinates of indermediate results, in order to prevent
- *                  more elaborate timing attacks relying on intermediate
- *                  operations. (This is a prophylactic measure since no such
- *                  attack has been published yet.) Since this contermeasure
- *                  has very low overhead, it is recommended to always provide
- *                  a non-NULL f_rng parameter when using secret inputs.
+ *
+ * \note            In order to prevent timing attacks, this function
+ *                  executes the exact same sequence of (base field)
+ *                  operations for any valid m. It avoids any if-branch or
+ *                  array index depending on the value of m.
+ *
+ * \note            If f_rng is not NULL, it is used to randomize intermediate
+ *                  results in order to prevent potential timing attacks
+ *                  targeting these results. It is recommended to always
+ *                  provide a non-NULL f_rng (the overhead is negligible).
  */
 int ecp_mul( ecp_group *grp, ecp_point *R,
              const mpi *m, const ecp_point *P,
              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
 
-
 /**
  * \brief           Check that a point is a valid public key on this curve
  *
@@ -539,15 +621,31 @@ int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q,
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng );
 
+/**
+ * \brief           Generate a keypair
+ *
+ * \param grp_id    ECP group identifier
+ * \param key       Destination keypair
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
+ *
+ * \return          0 if successful,
+ *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ */
+int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+#if defined(POLARSSL_SELF_TEST)
 /**
  * \brief          Checkup routine
  *
- * \return         0 if successful, or 1 if the test failed
+ * \return         0 if successful, or 1 if a test failed
  */
 int ecp_self_test( int verbose );
+#endif
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif
+#endif /* ecp.h */
index 235b7733c9c4acb85d7965d5444ec7adde9b6ab0..f5fa92808fd69a5265231d48edf4c887d42e71d1 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief Entropy accumulator implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 
 #include <string.h>
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
-#if defined(POLARSSL_SHA512_C)
+#if defined(POLARSSL_SHA512_C) && !defined(POLARSSL_ENTROPY_FORCE_SHA256)
 #include "sha512.h"
 #define POLARSSL_ENTROPY_SHA512_ACCUMULATOR
 #else
 #define POLARSSL_ERR_ENTROPY_SOURCE_FAILED                 -0x003C  /**< Critical entropy source failure. */
 #define POLARSSL_ERR_ENTROPY_MAX_SOURCES                   -0x003E  /**< No more sources can be added. */
 #define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED            -0x0040  /**< No sources have been added to poll. */
+#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR                 -0x0058  /**< Read/write error in file. */
 
-#if !defined(POLARSSL_CONFIG_OPTIONS)
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(ENTROPY_MAX_SOURCES)
 #define ENTROPY_MAX_SOURCES     20      /**< Maximum number of sources supported */
+#endif
+
+#if !defined(ENTROPY_MAX_GATHER)
 #define ENTROPY_MAX_GATHER      128     /**< Maximum amount requested from entropy sources */
-#endif /* !POLARSSL_CONFIG_OPTIONS  */
+#endif
+
+/* \} name SECTION: Module settings */
 
 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
 #define ENTROPY_BLOCK_SIZE      64      /**< Block size of entropy accumulator (SHA-512) */
@@ -64,6 +82,7 @@
 #define ENTROPY_BLOCK_SIZE      32      /**< Block size of entropy accumulator (SHA-256) */
 #endif
 
+#define ENTROPY_MAX_SEED_SIZE   1024    /**< Maximum size of seed we read from seed file */
 #define ENTROPY_SOURCE_MANUAL   ENTROPY_MAX_SOURCES
 
 #ifdef __cplusplus
@@ -81,7 +100,8 @@ extern "C" {
  * \return          0 if no critical failures occurred,
  *                  POLARSSL_ERR_ENTROPY_SOURCE_FAILED otherwise
  */
-typedef int (*f_source_ptr)(void *, unsigned char *, size_t, size_t *);
+typedef int (*f_source_ptr)(void *data, unsigned char *output, size_t len,
+                            size_t *olen);
 
 /**
  * \brief           Entropy source state
@@ -132,6 +152,7 @@ void entropy_free( entropy_context *ctx );
 
 /**
  * \brief           Adds an entropy source to poll
+ *                  (Thread-safe if POLARSSL_THREADING_C is enabled)
  *
  * \param ctx       Entropy context
  * \param f_source  Entropy function
@@ -147,6 +168,7 @@ int entropy_add_source( entropy_context *ctx,
 
 /**
  * \brief           Trigger an extra gather poll for the accumulator
+ *                  (Thread-safe if POLARSSL_THREADING_C is enabled)
  *
  * \param ctx       Entropy context
  *
@@ -155,12 +177,13 @@ int entropy_add_source( entropy_context *ctx,
 int entropy_gather( entropy_context *ctx );
 
 /**
- * \brief           Retrieve entropy from the accumulator (Max ENTROPY_BLOCK_SIZE)
+ * \brief           Retrieve entropy from the accumulator
+ *                  (Maximum length: ENTROPY_BLOCK_SIZE)
  *                  (Thread-safe if POLARSSL_THREADING_C is enabled)
  *
  * \param data      Entropy context
  * \param output    Buffer to fill
- * \param len       Length of buffer
+ * \param len       Number of bytes desired, must be at most ENTROPY_BLOCK_SIZE
  *
  * \return          0 if successful, or POLARSSL_ERR_ENTROPY_SOURCE_FAILED
  */
@@ -168,7 +191,8 @@ int entropy_func( void *data, unsigned char *output, size_t len );
 
 /**
  * \brief           Add data to the accumulator manually
- * 
+ *                  (Thread-safe if POLARSSL_THREADING_C is enabled)
+ *
  * \param ctx       Entropy context
  * \param data      Data to add
  * \param len       Length of data
@@ -178,6 +202,43 @@ int entropy_func( void *data, unsigned char *output, size_t len );
 int entropy_update_manual( entropy_context *ctx,
                            const unsigned char *data, size_t len );
 
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief               Write a seed file
+ *
+ * \param ctx           Entropy context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful,
+ *                      POLARSSL_ERR_ENTROPY_FILE_IO_ERROR on file error, or
+ *                      POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_write_seed_file( entropy_context *ctx, const char *path );
+
+/**
+ * \brief               Read and update a seed file. Seed is added to this
+ *                      instance. No more than ENTROPY_MAX_SEED_SIZE bytes are
+ *                      read from the seed file. The rest is ignored.
+ *
+ * \param ctx           Entropy context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful,
+ *                      POLARSSL_ERR_ENTROPY_FILE_IO_ERROR on file error,
+ *                      POLARSSL_ERR_ENTROPY_SOURCE_FAILED
+ */
+int entropy_update_seed_file( entropy_context *ctx, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int entropy_self_test( int verbose );
+#endif /* POLARSSL_SELF_TEST */
+
 #ifdef __cplusplus
 }
 #endif
index 0116598290c970cbbe28e5714e2e38eb2fff38aa..92efa0045b0cfd4929c27c39dfa7e6ccbcf1eedf 100644 (file)
 
 #include <string.h>
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #ifdef __cplusplus
 extern "C" {
index 55a8a45af20aa5a19f4b67c658b54863e4cd4f50..cdee952e0691bdb5900534aed3c6a02209522b7d 100644 (file)
  *
  * 16 bit error code bit-segmentation
  *
- * 1 bit  - Intentionally not used
+ * 1 bit  - Sign bit
  * 3 bits - High level module ID
  * 5 bits - Module-dependent error code
- * 6 bits - Low level module errors
- * 1 bit  - Intentionally not used
+ * 7 bits - Low level module errors
  *
- * Low-level module errors (0x007E-0x0002)
+ * For historical reasons, low-level error codes are divided in even and odd,
+ * even codes were assigned first, and -1 is reserved for other errors.
  *
- * Module   Nr  Codes assigned 
+ * Low-level module errors (0x0002-0x007E, 0x0003-0x007F)
+ *
+ * Module   Nr  Codes assigned
  * MPI       7  0x0002-0x0010
  * GCM       2  0x0012-0x0014
  * BLOWFISH  2  0x0016-0x0018
  * CAMELLIA  2  0x0024-0x0026
  * XTEA      1  0x0028-0x0028
  * BASE64    2  0x002A-0x002C
- * OID       1  0x002E-0x002E
+ * OID       1  0x002E-0x002E   0x000B-0x000B
  * PADLOCK   1  0x0030-0x0030
  * DES       1  0x0032-0x0032
- * CTR_DBRG  3  0x0034-0x003A
+ * CTR_DBRG  4  0x0034-0x003A
  * ENTROPY   3  0x003C-0x0040
  * NET      11  0x0042-0x0056
+ * ENTROPY   1  0x0058-0x0058
  * ASN1      7  0x0060-0x006C
  * MD2       1  0x0070-0x0070
  * MD4       1  0x0072-0x0072
  * SHA256    1  0x0078-0x0078
  * SHA512    1  0x007A-0x007A
  * PBKDF2    1  0x007C-0x007C
+ * RIPEMD160 1  0x007E-0x007E
+ * HMAC_DRBG 4  0x0003-0x0009
+ * CCM       2                  0x000D-0x000F
  *
- * High-level module nr (3 bits - 0x1...-0x8...)
+ * High-level module nr (3 bits - 0x0...-0x7...)
  * Name      ID  Nr of Errors
  * PEM       1   9
  * PKCS#12   1   4 (Started from top)
  * X509      2   18
- * PK        2   13 (Started from top)
+ * PK        2   14 (Started from top, plus 0x2000)
  * DHM       3   9
  * PKCS5     3   4 (Started from top)
  * RSA       4   9
- * ECP       4   7 (Started from top)
+ * ECP       4   8 (Started from top)
  * MD        5   4
  * CIPHER    6   6
- * SSL       6   8 (Started from top)
+ * SSL       6   9 (Started from top)
  * SSL       7   31
  *
- * Module dependent error code (5 bits 0x.08.-0x.F8.)
+ * Module dependent error code (5 bits 0x.00.-0x.F8.)
  */
 
 #ifdef __cplusplus
index e4267c645f8fbd9ea48a761f2628bfa0c5d277bc..c2829a0092a420038b16ab6cb0b89591b1f5601e 100644 (file)
@@ -201,7 +201,7 @@ int gcm_finish( gcm_context *ctx,
 /**
  * \brief           Free a GCM context and underlying cipher sub-context
  *
- * \param ctx
+ * \param ctx       GCM context to free
  */
 void gcm_free( gcm_context *ctx );
 
index 5998903ec3f4ce4d97645fb64ed0b4d82c53ae00..536eb088227367d5fb1c3210d4a7346f79da2af7 100644 (file)
@@ -53,6 +53,13 @@ havege_state;
  */
 void havege_init( havege_state *hs );
 
+/**
+ * \brief          Clear HAVEGE state
+ *
+ * \param hs       HAVEGE state to be cleared
+ */
+void havege_free( havege_state *hs );
+
 /**
  * \brief          HAVEGE rand function
  *
diff --git a/pdns/ext/polarssl/include/polarssl/hmac_drbg.h b/pdns/ext/polarssl/include/polarssl/hmac_drbg.h
new file mode 100644 (file)
index 0000000..2d765d5
--- /dev/null
@@ -0,0 +1,284 @@
+/**
+ * \file hmac_drbg.h
+ *
+ * \brief HMAC_DRBG (NIST SP 800-90A)
+ *
+ *  Copyright (C) 2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_HMAC_DRBG_H
+#define POLARSSL_HMAC_DRBG_H
+
+#include "md.h"
+
+/*
+ * Error codes
+ */
+#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG              -0x0003  /**< Too many random requested in single call. */
+#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG                -0x0005  /**< Input too large (Entropy + additional). */
+#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR                -0x0007  /**< Read/write error in file. */
+#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED        -0x0009  /**< The entropy source failed. */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(POLARSSL_HMAC_DRBG_RESEED_INTERVAL)
+#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL   10000   /**< Interval before reseed is performed by default */
+#endif
+
+#if !defined(POLARSSL_HMAC_DRBG_MAX_INPUT)
+#define POLARSSL_HMAC_DRBG_MAX_INPUT         256     /**< Maximum number of additional input bytes */
+#endif
+
+#if !defined(POLARSSL_HMAC_DRBG_MAX_REQUEST)
+#define POLARSSL_HMAC_DRBG_MAX_REQUEST       1024    /**< Maximum number of requested bytes per call */
+#endif
+
+#if !defined(POLARSSL_HMAC_DRBG_MAX_SEED_INPUT)
+#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT    384     /**< Maximum size of (re)seed buffer */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define POLARSSL_HMAC_DRBG_PR_OFF   0   /**< No prediction resistance       */
+#define POLARSSL_HMAC_DRBG_PR_ON    1   /**< Prediction resistance enabled  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * HMAC_DRBG context.
+ */
+typedef struct
+{
+    /* Working state: the key K is not stored explicitely,
+     * but is implied by the HMAC context */
+    md_context_t md_ctx;                    /*!< HMAC context (inc. K)  */
+    unsigned char V[POLARSSL_MD_MAX_SIZE];  /*!< V in the spec          */
+    int reseed_counter;                     /*!< reseed counter         */
+
+    /* Administrative state */
+    size_t entropy_len;         /*!< entropy bytes grabbed on each (re)seed */
+    int prediction_resistance;  /*!< enable prediction resistance (Automatic
+                                     reseed before every random generation) */
+    int reseed_interval;        /*!< reseed interval   */
+
+    /* Callbacks */
+    int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */
+    void *p_entropy;            /*!< context for the entropy function        */
+} hmac_drbg_context;
+
+/**
+ * \brief               HMAC_DRBG initialisation
+ *
+ * \param ctx           HMAC_DRBG context to be initialised
+ * \param md_info       MD algorithm to use for HMAC_DRBG
+ * \param f_entropy     Entropy callback (p_entropy, buffer to fill, buffer
+ *                      length)
+ * \param p_entropy     Entropy context
+ * \param custom        Personalization data (Device specific identifiers)
+ *                      (Can be NULL)
+ * \param len           Length of personalization data
+ *
+ * \note                The "security strength" as defined by NIST is set to:
+ *                      128 bits if md_alg is SHA-1,
+ *                      192 bits if md_alg is SHA-224,
+ *                      256 bits if md_alg is SHA-256 or higher.
+ *                      Note that SHA-256 is just as efficient as SHA-224.
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_MD_BAD_INPUT_DATA, or
+ *                      POLARSSL_ERR_MD_ALLOC_FAILED, or
+ *                      POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED.
+ */
+int hmac_drbg_init( hmac_drbg_context *ctx,
+                    const md_info_t * md_info,
+                    int (*f_entropy)(void *, unsigned char *, size_t),
+                    void *p_entropy,
+                    const unsigned char *custom,
+                    size_t len );
+
+/**
+ * \brief               Initilisation of simpified HMAC_DRBG (never reseeds).
+ *                      (For use with deterministic ECDSA.)
+ *
+ * \param ctx           HMAC_DRBG context to be initialised
+ * \param md_info       MD algorithm to use for HMAC_DRBG
+ * \param data          Concatenation of entropy string and additional data
+ * \param data_len      Length of data in bytes
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_MD_BAD_INPUT_DATA, or
+ *                      POLARSSL_ERR_MD_ALLOC_FAILED.
+ */
+int hmac_drbg_init_buf( hmac_drbg_context *ctx,
+                        const md_info_t * md_info,
+                        const unsigned char *data, size_t data_len );
+
+/**
+ * \brief               Enable / disable prediction resistance (Default: Off)
+ *
+ * Note: If enabled, entropy is used for ctx->entropy_len before each call!
+ *       Only use this if you have ample supply of good entropy!
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param resistance    POLARSSL_HMAC_DRBG_PR_ON or POLARSSL_HMAC_DRBG_PR_OFF
+ */
+void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
+                                          int resistance );
+
+/**
+ * \brief               Set the amount of entropy grabbed on each reseed
+ *                      (Default: given by the security strength, which
+ *                      depends on the hash used, see \c hmac_drbg_init() )
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param len           Amount of entropy to grab, in bytes
+ */
+void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx,
+                                size_t len );
+
+/**
+ * \brief               Set the reseed interval
+ *                      (Default: POLARSSL_HMAC_DRBG_RESEED_INTERVAL)
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param interval      Reseed interval
+ */
+void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx,
+                                    int interval );
+
+/**
+ * \brief               HMAC_DRBG update state
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param additional    Additional data to update state with, or NULL
+ * \param add_len       Length of additional data, or 0
+ *
+ * \note                Additional data is optional, pass NULL and 0 as second
+ *                      third argument if no additional data is being used.
+ */
+void hmac_drbg_update( hmac_drbg_context *ctx,
+                       const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief               HMAC_DRBG reseeding (extracts data from entropy source)
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param additional    Additional data to add to state (Can be NULL)
+ * \param len           Length of additional data
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int hmac_drbg_reseed( hmac_drbg_context *ctx,
+                      const unsigned char *additional, size_t len );
+
+/**
+ * \brief               HMAC_DRBG generate random with additional update input
+ *
+ * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ *
+ * \param p_rng         HMAC_DRBG context
+ * \param output        Buffer to fill
+ * \param output_len    Length of the buffer
+ * \param additional    Additional data to update with (can be NULL)
+ * \param add_len       Length of additional data (can be 0)
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ *                      POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
+ *                      POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG.
+ */
+int hmac_drbg_random_with_add( void *p_rng,
+                               unsigned char *output, size_t output_len,
+                               const unsigned char *additional,
+                               size_t add_len );
+
+/**
+ * \brief               HMAC_DRBG generate random
+ *
+ * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ *
+ * \param p_rng         HMAC_DRBG context
+ * \param output        Buffer to fill
+ * \param out_len       Length of the buffer
+ *
+ * \return              0 if successful, or
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ *                      POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG
+ */
+int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
+
+/**
+ * \brief               Free an HMAC_DRBG context
+ *
+ * \param ctx           HMAC_DRBG context to free.
+ */
+void hmac_drbg_free( hmac_drbg_context *ctx );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief               Write a seed file
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful, 1 on file error, or
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path );
+
+/**
+ * \brief               Read and update a seed file. Seed is added to this
+ *                      instance
+ *
+ * \param ctx           HMAC_DRBG context
+ * \param path          Name of the file
+ *
+ * \return              0 if successful, 1 on file error,
+ *                      POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
+ *                      POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG
+ */
+int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path );
+#endif /* POLARSSL_FS_IO */
+
+
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief               Checkup routine
+ *
+ * \return              0 if successful, or 1 if the test failed
+ */
+int hmac_drbg_self_test( int verbose );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* hmac_drbg.h */
index eecf781139f1a506592d7632660cc16c6303466d..81d8a2e5c2e504a0b3307eaff4dcea9be927190f 100644 (file)
@@ -1,11 +1,11 @@
 /**
  * \file md.h
- * 
+ *
  * \brief Generic message digest wrapper
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -58,6 +58,7 @@ typedef enum {
     POLARSSL_MD_SHA256,
     POLARSSL_MD_SHA384,
     POLARSSL_MD_SHA512,
+    POLARSSL_MD_RIPEMD160,
 } md_type_t;
 
 #if defined(POLARSSL_SHA512_C)
@@ -91,16 +92,18 @@ typedef struct {
 
     /** Generic digest function */
     void (*digest_func)( const unsigned char *input, size_t ilen,
-                            unsigned char *output );
+                         unsigned char *output );
 
     /** Generic file digest function */
     int (*file_func)( const char *path, unsigned char *output );
 
     /** HMAC Initialisation function */
-    void (*hmac_starts_func)( void *ctx, const unsigned char *key, size_t keylen );
+    void (*hmac_starts_func)( void *ctx, const unsigned char *key,
+                              size_t keylen );
 
     /** HMAC update function */
-    void (*hmac_update_func)( void *ctx, const unsigned char *input, size_t ilen );
+    void (*hmac_update_func)( void *ctx, const unsigned char *input,
+                              size_t ilen );
 
     /** HMAC finalisation function */
     void (*hmac_finish_func)( void *ctx, unsigned char *output);
@@ -110,8 +113,8 @@ typedef struct {
 
     /** Generic HMAC function */
     void (*hmac_func)( const unsigned char *key, size_t keylen,
-                    const unsigned char *input, size_t ilen,
-                    unsigned char *output );
+                       const unsigned char *input, size_t ilen,
+                       unsigned char *output );
 
     /** Allocate a new context */
     void * (*ctx_alloc_func)( void );
@@ -170,8 +173,24 @@ const md_info_t *md_info_from_string( const char *md_name );
 const md_info_t *md_info_from_type( md_type_t md_type );
 
 /**
- * \brief          Initialises and fills the message digest context structure with
- *                 the appropriate values.
+ * \brief               Initialize a md_context (as NONE)
+ */
+void md_init( md_context_t *ctx );
+
+/**
+ * \brief               Free and clear the message-specific context of ctx.
+ *                      Freeing ctx itself remains the responsibility of the
+ *                      caller.
+ */
+void md_free( md_context_t *ctx );
+
+/**
+ * \brief          Initialises and fills the message digest context structure
+ *                 with the appropriate values.
+ *
+ * \note           Currently also clears structure. In future versions you
+ *                 will be required to call md_init() on the structure
+ *                 first.
  *
  * \param ctx      context to initialise. May not be NULL. The
  *                 digest-specific context (ctx->md_ctx) must be NULL. It will
@@ -188,10 +207,11 @@ int md_init_ctx( md_context_t *ctx, const md_info_t *md_info );
  * \brief          Free the message-specific context of ctx. Freeing ctx itself
  *                 remains the responsibility of the caller.
  *
+ * \note           Deprecated: Redirects to md_free()
+ *
  * \param ctx      Free the message-specific context
  *
- * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
- *                 verification fails.
+ * \returns        0
  */
 int md_free_ctx( md_context_t *ctx );
 
@@ -298,7 +318,8 @@ int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
  *                 failed, POLARSSL_ERR_MD_FILE_READ_FAILED if fread failed,
  *                 POLARSSL_ERR_MD_BAD_INPUT_DATA if md_info was NULL.
  */
-int md_file( const md_info_t *md_info, const char *path, unsigned char *output );
+int md_file( const md_info_t *md_info, const char *path,
+             unsigned char *output );
 
 /**
  * \brief          Generic HMAC context setup
@@ -310,7 +331,8 @@ int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
  * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
  *                 verification fails.
  */
-int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen );
+int md_hmac_starts( md_context_t *ctx, const unsigned char *key,
+                    size_t keylen );
 
 /**
  * \brief          Generic HMAC process buffer
@@ -322,7 +344,8 @@ int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen )
  * \returns        0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
  *                 verification fails.
  */
-int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
+int md_hmac_update( md_context_t *ctx, const unsigned char *input,
+                    size_t ilen );
 
 /**
  * \brief          Generic HMAC final digest
index a8e23d0dae135d0dd082ea671b2344da233694be..952b0bfceb91fcb157b38b93aa79442bd45d8330 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief MD2 message digest algorithm (hash function)
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_MD2_H
 #define POLARSSL_MD2_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -56,6 +60,20 @@ typedef struct
 }
 md2_context;
 
+/**
+ * \brief          Initialize MD2 context
+ *
+ * \param ctx      MD2 context to be initialized
+ */
+void md2_init( md2_context *ctx );
+
+/**
+ * \brief          Clear MD2 context
+ *
+ * \param ctx      MD2 context to be cleared
+ */
+void md2_free( md2_context *ctx );
+
 /**
  * \brief          MD2 context setup
  *
@@ -118,7 +136,8 @@ int md2_file( const char *path, unsigned char output[16] );
  * \param key      HMAC secret key
  * \param keylen   length of the HMAC key
  */
-void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen );
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key,
+                      size_t keylen );
 
 /**
  * \brief          MD2 HMAC process buffer
@@ -127,7 +146,8 @@ void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen
  * \param input    buffer holding the  data
  * \param ilen     length of the input data
  */
-void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen );
+void md2_hmac_update( md2_context *ctx, const unsigned char *input,
+                      size_t ilen );
 
 /**
  * \brief          MD2 HMAC final digest
index a1b5d459e4361a7e7df09d6c3fc133f679bdd7d1..fc5a5cd27a8549eb29ec6bad7b44abe6b0ddfb4c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief MD4 message digest algorithm (hash function)
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_MD4_H
 #define POLARSSL_MD4_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -62,6 +66,20 @@ typedef struct
 }
 md4_context;
 
+/**
+ * \brief          Initialize MD4 context
+ *
+ * \param ctx      MD4 context to be initialized
+ */
+void md4_init( md4_context *ctx );
+
+/**
+ * \brief          Clear MD4 context
+ *
+ * \param ctx      MD4 context to be cleared
+ */
+void md4_free( md4_context *ctx );
+
 /**
  * \brief          MD4 context setup
  *
@@ -124,7 +142,8 @@ int md4_file( const char *path, unsigned char output[16] );
  * \param key      HMAC secret key
  * \param keylen   length of the HMAC key
  */
-void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen );
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key,
+                      size_t keylen );
 
 /**
  * \brief          MD4 HMAC process buffer
@@ -133,7 +152,8 @@ void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen
  * \param input    buffer holding the  data
  * \param ilen     length of the input data
  */
-void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen );
+void md4_hmac_update( md4_context *ctx, const unsigned char *input,
+                      size_t ilen );
 
 /**
  * \brief          MD4 HMAC final digest
index df2a61b8ac415535751930388d533139bbd81a76..2f378f6cd746ca84e114ede2ab317fe8584132cc 100644 (file)
 #ifndef POLARSSL_MD5_H
 #define POLARSSL_MD5_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -62,6 +66,20 @@ typedef struct
 }
 md5_context;
 
+/**
+ * \brief          Initialize MD5 context
+ *
+ * \param ctx      MD5 context to be initialized
+ */
+void md5_init( md5_context *ctx );
+
+/**
+ * \brief          Clear MD5 context
+ *
+ * \param ctx      MD5 context to be cleared
+ */
+void md5_free( md5_context *ctx );
+
 /**
  * \brief          MD5 context setup
  *
index a41c875fc256211e0029af897c6d7c3f8a395801..eb1db0f1ef4642071df11ba56a18581b1b68ab92 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * \file md_wrap.h
- * 
+ *
  * \brief Message digest wrappers.
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
 #ifndef POLARSSL_MD_WRAP_H
 #define POLARSSL_MD_WRAP_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 #include "md.h"
 
 #ifdef __cplusplus
@@ -45,6 +49,9 @@ extern const md_info_t md4_info;
 #if defined(POLARSSL_MD5_C)
 extern const md_info_t md5_info;
 #endif
+#if defined(POLARSSL_RIPEMD160_C)
+extern const md_info_t ripemd160_info;
+#endif
 #if defined(POLARSSL_SHA1_C)
 extern const md_info_t sha1_info;
 #endif
index 6a3dab94bea8156fc16cba10fca7a239b6537bc6..3af39511b44655c2e29e01e81f883adfcd53241b 100644 (file)
@@ -1,9 +1,9 @@
 /**
  * \file memory.h
  *
- * \brief Memory allocation layer
+ * \brief Memory allocation layer (Deprecated to platform layer)
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_MEMORY_H
 #define POLARSSL_MEMORY_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <stdlib.h>
 
-#if !defined(POLARSSL_CONFIG_OPTIONS)
-#define POLARSSL_MEMORY_ALIGN_MULTIPLE       4 /**< Align on multiples of this value */
-
-#define POLARSSL_MEMORY_STDMALLOC       malloc /**< Default allocator to use, can be undefined */
-#define POLARSSL_MEMORY_STDFREE           free /**< Default free to use, can be undefined */
-#endif /* POLARSSL_CONFIG_OPTIONS */
-
-#define MEMORY_VERIFY_NONE         0
-#define MEMORY_VERIFY_ALLOC        (1 << 0)
-#define MEMORY_VERIFY_FREE         (1 << 1)
-#define MEMORY_VERIFY_ALWAYS       (MEMORY_VERIFY_ALLOC | MEMORY_VERIFY_FREE)
-
-#ifdef __cplusplus
-extern "C" {
+#if defined(POLARSSL_MEMORY_C) && !defined(POLARSSL_PLATFORM_MEMORY)
+#define POLARSSL_PLATFORM_MEMORY
 #endif
 
-/*
- * The function pointers for malloc and free
- */
-extern void * (*polarssl_malloc)( size_t len );
-extern void (*polarssl_free)( void *ptr );
+#include "platform.h"
+#include "memory_buffer_alloc.h"
 
-/**
- * \brief   Set your own memory implementation function pointers
- *
- * \param malloc_func   the malloc function implementation
- * \param free_func     the free function implementation
- *
- * \return              0 if successful
- */
 int memory_set_own( void * (*malloc_func)( size_t ),
-                    void (*free_func)( void * ) );
-
-#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
-/**
- * \brief   Initialize use of stack-based memory allocator.
- *          The stack-based allocator does memory management inside the
- *          presented buffer and does not call malloc() and free().
- *          It sets the global polarssl_malloc() and polarssl_free() pointers
- *          to its own functions.
- *          (Provided polarssl_malloc() and polarssl_free() are thread-safe if
- *           POLARSSL_THREADING_C is defined)
- *
- * \note    This code is not optimized and provides a straight-forward
- *          implementation of a stack-based memory allocator.
- *
- * \param buf   buffer to use as heap
- * \param len   size of the buffer
- *
- * \return              0 if successful
- */
-int memory_buffer_alloc_init( unsigned char *buf, size_t len );
-
-/**
- * \brief   Free the mutex for thread-safety and clear remaining memory
- */
-void memory_buffer_alloc_free();
-
-/**
- * \brief   Determine when the allocator should automatically verify the state
- *          of the entire chain of headers / meta-data.
- *          (Default: MEMORY_VERIFY_NONE)
- *
- * \param verify    One of MEMORY_VERIFY_NONE, MEMORY_VERIFY_ALLOC,
- *                  MEMORY_VERIFY_FREE or MEMORY_VERIFY_ALWAYS
- */
-void memory_buffer_set_verify( int verify );
-
-#if defined(POLARSSL_MEMORY_DEBUG)
-/**
- * \brief   Print out the status of the allocated memory (primarily for use
- *          after a program should have de-allocated all memory)
- *          Prints out a list of 'still allocated' blocks and their stack
- *          trace if POLARSSL_MEMORY_BACKTRACE is defined.
- */
-void memory_buffer_alloc_status();
-#endif /* POLARSSL_MEMORY_DEBUG */
-
-/**
- * \brief   Verifies that all headers in the memory buffer are correct
- *          and contain sane values. Helps debug buffer-overflow errors.
- *
- *          Prints out first failure if POLARSSL_MEMORY_DEBUG is defined.
- *          Prints out full header information if POLARSSL_MEMORY_DEBUG_HEADERS
- *          is defined. (Includes stack trace information for each block if
- *          POLARSSL_MEMORY_BACKTRACE is defined as well).
- *
- * \returns             0 if verified, 1 otherwise
- */
-int memory_buffer_alloc_verify();
-
-#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */
-
-#ifdef __cplusplus
+                    void (*free_func)( void * ) )
+{
+    return platform_set_malloc_free( malloc_func, free_func );
 }
-#endif
+
 
 #endif /* memory.h */
diff --git a/pdns/ext/polarssl/include/polarssl/memory_buffer_alloc.h b/pdns/ext/polarssl/include/polarssl/memory_buffer_alloc.h
new file mode 100644 (file)
index 0000000..c449752
--- /dev/null
@@ -0,0 +1,122 @@
+/**
+ * \file memory_buffer_alloc.h
+ *
+ * \brief Buffer-based memory allocator
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_MEMORY_BUFFER_ALLOC_H
+#define POLARSSL_MEMORY_BUFFER_ALLOC_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stdlib.h>
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(POLARSSL_MEMORY_ALIGN_MULTIPLE)
+#define POLARSSL_MEMORY_ALIGN_MULTIPLE       4 /**< Align on multiples of this value */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define MEMORY_VERIFY_NONE         0
+#define MEMORY_VERIFY_ALLOC        (1 << 0)
+#define MEMORY_VERIFY_FREE         (1 << 1)
+#define MEMORY_VERIFY_ALWAYS       (MEMORY_VERIFY_ALLOC | MEMORY_VERIFY_FREE)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief   Initialize use of stack-based memory allocator.
+ *          The stack-based allocator does memory management inside the
+ *          presented buffer and does not call malloc() and free().
+ *          It sets the global polarssl_malloc() and polarssl_free() pointers
+ *          to its own functions.
+ *          (Provided polarssl_malloc() and polarssl_free() are thread-safe if
+ *           POLARSSL_THREADING_C is defined)
+ *
+ * \note    This code is not optimized and provides a straight-forward
+ *          implementation of a stack-based memory allocator.
+ *
+ * \param buf   buffer to use as heap
+ * \param len   size of the buffer
+ *
+ * \return              0 if successful
+ */
+int memory_buffer_alloc_init( unsigned char *buf, size_t len );
+
+/**
+ * \brief   Free the mutex for thread-safety and clear remaining memory
+ */
+void memory_buffer_alloc_free( void );
+
+/**
+ * \brief   Determine when the allocator should automatically verify the state
+ *          of the entire chain of headers / meta-data.
+ *          (Default: MEMORY_VERIFY_NONE)
+ *
+ * \param verify    One of MEMORY_VERIFY_NONE, MEMORY_VERIFY_ALLOC,
+ *                  MEMORY_VERIFY_FREE or MEMORY_VERIFY_ALWAYS
+ */
+void memory_buffer_set_verify( int verify );
+
+#if defined(POLARSSL_MEMORY_DEBUG)
+/**
+ * \brief   Print out the status of the allocated memory (primarily for use
+ *          after a program should have de-allocated all memory)
+ *          Prints out a list of 'still allocated' blocks and their stack
+ *          trace if POLARSSL_MEMORY_BACKTRACE is defined.
+ */
+void memory_buffer_alloc_status( void );
+#endif /* POLARSSL_MEMORY_DEBUG */
+
+/**
+ * \brief   Verifies that all headers in the memory buffer are correct
+ *          and contain sane values. Helps debug buffer-overflow errors.
+ *
+ *          Prints out first failure if POLARSSL_MEMORY_DEBUG is defined.
+ *          Prints out full header information if POLARSSL_MEMORY_DEBUG_HEADERS
+ *          is defined. (Includes stack trace information for each block if
+ *          POLARSSL_MEMORY_BACKTRACE is defined as well).
+ *
+ * \returns             0 if verified, 1 otherwise
+ */
+int memory_buffer_alloc_verify( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* memory_buffer_alloc.h */
index 88302ac0a7268a35119d1b0b9e0fa6eba27d3952..22698b4ce47715a190153c8a80494b515c534212 100644 (file)
@@ -82,9 +82,10 @@ int net_bind( int *fd, const char *bind_ip, int port );
  * \param bind_fd   Relevant socket
  * \param client_fd Will contain the connected client socket
  * \param client_ip Will contain the client IP address
+ *                  Must be at least 4 bytes, or 16 if IPv6 is supported
  *
  * \return          0 if successful, POLARSSL_ERR_NET_ACCEPT_FAILED, or
- *                  POLARSSL_ERR_NET_WOULD_BLOCK is bind_fd was set to
+ *                  POLARSSL_ERR_NET_WANT_READ is bind_fd was set to
  *                  non-blocking and accept() is blocking.
  */
 int net_accept( int bind_fd, int *client_fd, void *client_ip );
index 93ef8a6ab36320edbb762557f150fa24d011df71..c4d5c3fba1c9048a5d5143a5ed6fd8ce7a1afcc6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief Object Identifier (OID) database
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #define POLARSSL_OID_H
 
 #include <string.h>
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 #include "asn1.h"
 #include "pk.h"
 #if defined(POLARSSL_CIPHER_C)
@@ -44,6 +48,7 @@
 #endif
 
 #define POLARSSL_ERR_OID_NOT_FOUND                         -0x002E  /**< OID is not found. */
+#define POLARSSL_ERR_OID_BUF_TOO_SMALL                     -0x000B  /**< output buffer is too small */
 
 /*
  * Top level OID tuples
@@ -58,7 +63,7 @@
  */
 #define OID_COUNTRY_US                  "\x86\x48"      /* {us(840)} */
 #define OID_ORG_RSA_DATA_SECURITY       "\x86\xf7\x0d"  /* {rsadsi(113549)} */
-#define OID_RSA_COMPANY                 OID_ISO_MEMBER_BODIES OID_COUNTRY_US    \
+#define OID_RSA_COMPANY                 OID_ISO_MEMBER_BODIES OID_COUNTRY_US \
                                         OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */
 #define OID_ORG_ANSI_X9_62              "\xce\x3d" /* ansi-X9-62(10045) */
 #define OID_ANSI_X9_62                  OID_ISO_MEMBER_BODIES OID_COUNTRY_US \
  */
 #define OID_AT                          OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */
 #define OID_AT_CN                       OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */
+#define OID_AT_SUR_NAME                 OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */
 #define OID_AT_SERIAL_NUMBER            OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */
 #define OID_AT_COUNTRY                  OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */
 #define OID_AT_LOCALITY                 OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */
 #define OID_AT_STATE                    OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */
 #define OID_AT_ORGANIZATION             OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */
 #define OID_AT_ORG_UNIT                 OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */
+#define OID_AT_TITLE                    OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */
 #define OID_AT_POSTAL_ADDRESS           OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */
 #define OID_AT_POSTAL_CODE              OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */
+#define OID_AT_GIVEN_NAME               OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */
+#define OID_AT_INITIALS                 OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */
+#define OID_AT_GENERATION_QUALIFIER     OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */
+#define OID_AT_DN_QUALIFIER             OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */
+#define OID_AT_PSEUDONYM                OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */
+
+#define OID_DOMAIN_COMPONENT            "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */
 
 /*
  * OIDs for standard certificate extensions
 
 #define OID_PKCS9_EMAIL         OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */
 
+/* RFC 4055 */
+#define OID_RSASSA_PSS          OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */
+#define OID_MGF1                OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */
+
 /*
  * Digest algorithms
  */
 #define OID_EC_ALG_ECDH                 OID_CERTICOM "\x01\x0c"
 
 /*
- * ECParameters namedCurve identifiers, from RFC 5480 and RFC 5639
+ * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2
  */
 
 /* secp192r1 OBJECT IDENTIFIER ::= {
  *   iso(1) identified-organization(3) certicom(132) curve(0) 35 } */
 #define OID_EC_GRP_SECP521R1        OID_CERTICOM "\x00\x23"
 
+/* secp192k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 31 } */
+#define OID_EC_GRP_SECP192K1        OID_CERTICOM "\x00\x1f"
+
+/* secp224k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 32 } */
+#define OID_EC_GRP_SECP224K1        OID_CERTICOM "\x00\x20"
+
+/* secp256k1 OBJECT IDENTIFIER ::= {
+ *   iso(1) identified-organization(3) certicom(132) curve(0) 10 } */
+#define OID_EC_GRP_SECP256K1        OID_CERTICOM "\x00\x0a"
+
 /* RFC 5639 4.1
  * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1)
  * identified-organization(3) teletrust(36) algorithm(3) signature-
 #define OID_EC_GRP_BP512R1          OID_EC_BRAINPOOL_V1 "\x0D"
 
 /*
- * ECDSA signature identifers, from RFC 5480
+ * SEC1 C.1
+ *
+ * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
+ * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)}
+ */
+#define OID_ANSI_X9_62_FIELD_TYPE   OID_ANSI_X9_62 "\x01"
+#define OID_ANSI_X9_62_PRIME_FIELD  OID_ANSI_X9_62_FIELD_TYPE "\x01"
+
+/*
+ * ECDSA signature identifiers, from RFC 5480
  */
 #define OID_ANSI_X9_62_SIG          OID_ANSI_X9_62 "\x04" /* signatures(4) */
 #define OID_ANSI_X9_62_SIG_SHA2     OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */
@@ -355,7 +394,8 @@ typedef struct {
  * \param size      size of the buffer
  * \param oid       OID to translate
  *
- * \return          POLARSSL_ERR_DEBUG_BUF_TOO_SMALL or actual length used
+ * \return          Length of the string written (excluding final NULL) or
+ *                  POLARSSL_ERR_OID_BUF_TO_SMALL in case of error
  */
 int oid_get_numeric_string( char *buf, size_t size, const asn1_buf *oid );
 
index 0e9de221cecf4078c9bc3437e63898c78c559cf8..b77e7dacb72809696913e03aa30d937cdc5d80ed 100644 (file)
@@ -98,7 +98,7 @@ inline rsa_context* d2i_RSA_PUBKEY( void *ignore, unsigned char **bufptr,
 
     memset( rsa, 0, sizeof( rsa_context ) );
 
-    if( ( len ==  94 && 
+    if( ( len ==  94 &&
           mpi_read_binary( &rsa->N, &buffer[ 25],  64 ) == 0 &&
           mpi_read_binary( &rsa->E, &buffer[ 91],   3 ) == 0 ) ||
         ( len == 162 &&
index 8df93c034c083c9ae46ba588c7b956452cadf8f1..3c5f7258b4f6e2d2e2aebd1501e64ba5d3353b0f 100644 (file)
@@ -1,9 +1,10 @@
 /**
  * \file padlock.h
  *
- * \brief VIA PadLock ACE for HW encryption/decryption supported by some processors
+ * \brief VIA PadLock ACE for HW encryption/decryption supported by some
+ *        processors
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -59,7 +60,7 @@ extern "C" {
 /**
  * \brief          PadLock detection routine
  *
- * \param          The feature to detect
+ * \param feature  The feature to detect
  *
  * \return         1 if CPU has support for the feature, 0 otherwise
  */
index 251c690e5744a0cacce8c11b999b8462bee0690b..754dda2190bca7683452208bc34314e4e35e296e 100644 (file)
 #ifndef POLARSSL_PK_H
 #define POLARSSL_PK_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include "md.h"
 
@@ -57,6 +61,7 @@
 #define POLARSSL_ERR_PK_INVALID_ALG         -0x2A80  /**< The algorithm tag or value is invalid. */
 #define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE -0x2A00  /**< Elliptic curve is unsupported (only NIST curves are supported). */
 #define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE -0x2980  /**< Unavailable feature, e.g. RSA disabled for RSA key. */
+#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH    -0x2000  /**< The signature is valid but its length is less than expected. */
 
 
 #if defined(POLARSSL_RSA_C)
@@ -94,8 +99,20 @@ typedef enum {
     POLARSSL_PK_ECKEY_DH,
     POLARSSL_PK_ECDSA,
     POLARSSL_PK_RSA_ALT,
+    POLARSSL_PK_RSASSA_PSS,
 } pk_type_t;
 
+/**
+ * \brief           Options for RSASSA-PSS signature verification.
+ *                  See \c rsa_rsassa_pss_verify_ext()
+ */
+typedef struct
+{
+    md_type_t mgf1_hash_id;
+    int expected_salt_len;
+
+} pk_rsassa_pss_options;
+
 /**
  * \brief           Types for interfacing with the debug module
  */
@@ -188,7 +205,7 @@ typedef int (*pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen,
                     size_t output_max_len );
 typedef int (*pk_rsa_alt_sign_func)( void *ctx,
                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                    int mode, int hash_id, unsigned int hashlen,
+                    int mode, md_type_t md_alg, unsigned int hashlen,
                     const unsigned char *hash, unsigned char *sig );
 typedef size_t (*pk_rsa_alt_key_len_func)( void *ctx );
 
@@ -234,7 +251,7 @@ int pk_init_ctx( pk_context *ctx, const pk_info_t *info );
  * \param key       RSA key pointer
  * \param decrypt_func  Decryption function
  * \param sign_func     Signing function
- * \param key_len_func  Function returning key length
+ * \param key_len_func  Function returning key length in bytes
  *
  * \return          0 on success, or POLARSSL_ERR_PK_BAD_INPUT_DATA if the
  *                  context wasn't already initialized as RSA_ALT.
@@ -278,7 +295,7 @@ static inline size_t pk_get_len( const pk_context *ctx )
 int pk_can_do( pk_context *ctx, pk_type_t type );
 
 /**
- * \brief           Verify signature
+ * \brief           Verify signature (including padding if relevant).
  *
  * \param ctx       PK context to use
  * \param md_alg    Hash algorithm used (see notes)
@@ -288,8 +305,14 @@ int pk_can_do( pk_context *ctx, pk_type_t type );
  * \param sig_len   Signature length
  *
  * \return          0 on success (signature is valid),
+ *                  POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is
+ *                  valid but its actual length is less than sig_len,
  *                  or a specific error code.
  *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *                  Use \c pk_verify_ext( POLARSSL_PK_RSASSA_PSS, ... )
+ *                  to verify RSASSA_PSS signatures.
+ *
  * \note            If hash_len is 0, then the length associated with md_alg
  *                  is used instead, or an error returned if it is invalid.
  *
@@ -300,7 +323,41 @@ int pk_verify( pk_context *ctx, md_type_t md_alg,
                const unsigned char *sig, size_t sig_len );
 
 /**
- * \brief           Make signature
+ * \brief           Verify signature, with options.
+ *                  (Includes verification of the padding depending on type.)
+ *
+ * \param type      Signature type (inc. possible padding type) to verify
+ * \param options   Pointer to type-specific options, or NULL
+ * \param ctx       PK context to use
+ * \param md_alg    Hash algorithm used (see notes)
+ * \param hash      Hash of the message to sign
+ * \param hash_len  Hash length or 0 (see notes)
+ * \param sig       Signature to verify
+ * \param sig_len   Signature length
+ *
+ * \return          0 on success (signature is valid),
+ *                  POLARSSL_ERR_PK_TYPE_MISMATCH if the PK context can't be
+ *                  used for this type of signatures,
+ *                  POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is
+ *                  valid but its actual length is less than sig_len,
+ *                  or a specific error code.
+ *
+ * \note            If hash_len is 0, then the length associated with md_alg
+ *                  is used instead, or an error returned if it is invalid.
+ *
+ * \note            md_alg may be POLARSSL_MD_NONE, only if hash_len != 0
+ *
+ * \note            If type is POLARSSL_PK_RSASSA_PSS, then options must point
+ *                  to a pk_rsassa_pss_options structure,
+ *                  otherwise it must be NULL.
+ */
+int pk_verify_ext( pk_type_t type, const void *options,
+                   pk_context *ctx, md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   const unsigned char *sig, size_t sig_len );
+
+/**
+ * \brief           Make signature, including padding if relevant.
  *
  * \param ctx       PK context to use
  * \param md_alg    Hash algorithm used (see notes)
@@ -313,6 +370,10 @@ int pk_verify( pk_context *ctx, md_type_t md_alg,
  *
  * \return          0 on success, or a specific error code.
  *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *                  There is no interface in the PK module to make RSASSA-PSS
+ *                  signatures yet.
+ *
  * \note            If hash_len is 0, then the length associated with md_alg
  *                  is used instead, or an error returned if it is invalid.
  *
@@ -324,7 +385,7 @@ int pk_sign( pk_context *ctx, md_type_t md_alg,
              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
 
 /**
- * \brief           Decrypt message
+ * \brief           Decrypt message (including padding if relevant).
  *
  * \param ctx       PK context to use
  * \param input     Input to decrypt
@@ -335,6 +396,8 @@ int pk_sign( pk_context *ctx, md_type_t md_alg,
  * \param f_rng     RNG function
  * \param p_rng     RNG parameter
  *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *
  * \return          0 on success, or a specific error code.
  */
 int pk_decrypt( pk_context *ctx,
@@ -343,7 +406,7 @@ int pk_decrypt( pk_context *ctx,
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
 
 /**
- * \brief           Encrypt message
+ * \brief           Encrypt message (including padding if relevant).
  *
  * \param ctx       PK context to use
  * \param input     Message to encrypt
@@ -354,6 +417,8 @@ int pk_decrypt( pk_context *ctx,
  * \param f_rng     RNG function
  * \param p_rng     RNG parameter
  *
+ * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ *
  * \return          0 on success, or a specific error code.
  */
 int pk_encrypt( pk_context *ctx,
@@ -400,6 +465,12 @@ pk_type_t pk_get_type( const pk_context *ctx );
  * \param pwd       password for decryption (optional)
  * \param pwdlen    size of the password
  *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with pk_init() or reset with pk_free(). If you need a
+ *                  specific key type, check the result with pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
  * \return          0 if successful, or a specific PK or PEM error code
  */
 int pk_parse_key( pk_context *ctx,
@@ -414,6 +485,12 @@ int pk_parse_key( pk_context *ctx,
  * \param key       input buffer
  * \param keylen    size of the buffer
  *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with pk_init() or reset with pk_free(). If you need a
+ *                  specific key type, check the result with pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
  * \return          0 if successful, or a specific PK or PEM error code
  */
 int pk_parse_public_key( pk_context *ctx,
@@ -428,6 +505,12 @@ int pk_parse_public_key( pk_context *ctx,
  * \param path      filename to read the private key from
  * \param password  password to decrypt the file (can be NULL)
  *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with pk_init() or reset with pk_free(). If you need a
+ *                  specific key type, check the result with pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
  * \return          0 if successful, or a specific PK or PEM error code
  */
 int pk_parse_keyfile( pk_context *ctx,
@@ -440,6 +523,12 @@ int pk_parse_keyfile( pk_context *ctx,
  * \param ctx       key to be initialized
  * \param path      filename to read the private key from
  *
+ * \note            On entry, ctx must be empty, either freshly initialised
+ *                  with pk_init() or reset with pk_free(). If you need a
+ *                  specific key type, check the result with pk_can_do().
+ *
+ * \note            The key is also checked for correctness.
+ *
  * \return          0 if successful, or a specific PK or PEM error code
  */
 int pk_parse_public_keyfile( pk_context *ctx, const char *path );
@@ -453,14 +542,14 @@ int pk_parse_public_keyfile( pk_context *ctx, const char *path );
  *                        return value to determine where you should start
  *                        using the buffer
  *
- * \param key       private to write away
+ * \param ctx       private to write away
  * \param buf       buffer to write to
  * \param size      size of the buffer
  *
  * \return          length of data written if successful, or a specific
  *                  error code
  */
-int pk_write_key_der( pk_context *pk, unsigned char *buf, size_t size );
+int pk_write_key_der( pk_context *ctx, unsigned char *buf, size_t size );
 
 /**
  * \brief           Write a public key to a SubjectPublicKeyInfo DER structure
@@ -468,37 +557,37 @@ int pk_write_key_der( pk_context *pk, unsigned char *buf, size_t size );
  *                        return value to determine where you should start
  *                        using the buffer
  *
- * \param key       public key to write away
+ * \param ctx       public key to write away
  * \param buf       buffer to write to
  * \param size      size of the buffer
  *
  * \return          length of data written if successful, or a specific
  *                  error code
  */
-int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size );
+int pk_write_pubkey_der( pk_context *ctx, unsigned char *buf, size_t size );
 
 #if defined(POLARSSL_PEM_WRITE_C)
 /**
  * \brief           Write a public key to a PEM string
  *
- * \param key       public key to write away
+ * \param ctx       public key to write away
  * \param buf       buffer to write to
  * \param size      size of the buffer
  *
  * \return          0 successful, or a specific error code
  */
-int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size );
+int pk_write_pubkey_pem( pk_context *ctx, unsigned char *buf, size_t size );
 
 /**
  * \brief           Write a private key to a PKCS#1 or SEC1 PEM string
  *
- * \param key       private to write away
+ * \param ctx       private to write away
  * \param buf       buffer to write to
  * \param size      size of the buffer
  *
  * \return          0 successful, or a specific error code
  */
-int pk_write_key_pem( pk_context *key, unsigned char *buf, size_t size );
+int pk_write_key_pem( pk_context *ctx, unsigned char *buf, size_t size );
 #endif /* POLARSSL_PEM_WRITE_C */
 #endif /* POLARSSL_PK_WRITE_C */
 
index 91a671e0296cadfab61b7f8367677fe841eb7ea8..7baafb95da2be18f382317f82a483b67d81fd733 100644 (file)
 #ifndef POLARSSL_PK_WRAP_H
 #define POLARSSL_PK_WRAP_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include "pk.h"
 
index c0515e67c446227c2afed9c316ad537f6fce8cb3..84f862dd90fbf926dd9acbc86a2b4ecccac26c83 100644 (file)
@@ -5,7 +5,7 @@
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_PKCS11_H
 #define POLARSSL_PKCS11_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PKCS11_C)
 
@@ -89,7 +93,8 @@ int pkcs11_priv_key_init( pkcs11_context *priv_key,
 void pkcs11_priv_key_free( pkcs11_context *priv_key );
 
 /**
- * \brief          Do an RSA private key decrypt, then remove the message padding
+ * \brief          Do an RSA private key decrypt, then remove the message
+ *                 padding
  *
  * \param ctx      PKCS #11 context
  * \param mode     must be RSA_PRIVATE, for compatibility with rsa.c's signature
@@ -115,8 +120,8 @@ int pkcs11_decrypt( pkcs11_context *ctx,
  *
  * \param ctx      PKCS #11 context
  * \param mode     must be RSA_PRIVATE, for compatibility with rsa.c's signature
- * \param hash_id  SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
- * \param hashlen  message digest length (for SIG_RSA_RAW only)
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_MD_NONE only)
  * \param hash     buffer holding the message digest
  * \param sig      buffer that will hold the ciphertext
  *
@@ -128,7 +133,7 @@ int pkcs11_decrypt( pkcs11_context *ctx,
  */
 int pkcs11_sign( pkcs11_context *ctx,
                     int mode,
-                    int hash_id,
+                    md_type_t md_alg,
                     unsigned int hashlen,
                     const unsigned char *hash,
                     unsigned char *sig );
@@ -144,14 +149,14 @@ static inline int ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen,
                            output_max_len );
 }
 
-static inline int ssl_pkcs11_sign( void *ctx, 
+static inline int ssl_pkcs11_sign( void *ctx,
                      int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                     int mode, int hash_id, unsigned int hashlen,
+                     int mode, md_type_t md_alg, unsigned int hashlen,
                      const unsigned char *hash, unsigned char *sig )
 {
     ((void) f_rng);
     ((void) p_rng);
-    return pkcs11_sign( (pkcs11_context *) ctx, mode, hash_id,
+    return pkcs11_sign( (pkcs11_context *) ctx, mode, md_alg,
                         hashlen, hash, sig );
 }
 
index 51bea3da1ed4823331d06418d9981054bbb3fc8d..4bd5018af539eb54ce1ed0c2c105dac165ebe436 100644 (file)
@@ -38,9 +38,9 @@
 #define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT             -0x1E80  /**< PBE ASN.1 data not as expected. */
 #define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH              -0x1E00  /**< Given private key password does not allow for correct decryption. */
 
-#define PKCS12_DERIVE_KEY       1   /*< encryption/decryption key */
-#define PKCS12_DERIVE_IV        2   /*< initialization vector     */
-#define PKCS12_DERIVE_MAC_KEY   3   /*< integrity / MAC key       */
+#define PKCS12_DERIVE_KEY       1   /**< encryption/decryption key */
+#define PKCS12_DERIVE_IV        2   /**< initialization vector     */
+#define PKCS12_DERIVE_MAC_KEY   3   /**< integrity / MAC key       */
 
 #define PKCS12_PBE_DECRYPT      0
 #define PKCS12_PBE_ENCRYPT      1
diff --git a/pdns/ext/polarssl/include/polarssl/platform.h b/pdns/ext/polarssl/include/polarssl/platform.h
new file mode 100644 (file)
index 0000000..eae887a
--- /dev/null
@@ -0,0 +1,128 @@
+/**
+ * \file platform.h
+ *
+ * \brief PolarSSL Platform abstraction layer
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_PLATFORM_H
+#define POLARSSL_PLATFORM_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS)
+#include <stdlib.h>
+#if !defined(POLARSSL_PLATFORM_STD_PRINTF)
+#define POLARSSL_PLATFORM_STD_PRINTF   printf /**< Default printf to use  */
+#endif
+#if !defined(POLARSSL_PLATFORM_STD_FPRINTF)
+#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */
+#endif
+#if !defined(POLARSSL_PLATFORM_STD_MALLOC)
+#define POLARSSL_PLATFORM_STD_MALLOC   malloc /**< Default allocator to use */
+#endif
+#if !defined(POLARSSL_PLATFORM_STD_FREE)
+#define POLARSSL_PLATFORM_STD_FREE       free /**< Default free to use */
+#endif
+#else /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */
+#if defined(POLARSSL_PLATFORM_STD_MEM_HDR)
+#include POLARSSL_PLATFORM_STD_MEM_HDR
+#endif
+#endif /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */
+
+/* \} name SECTION: Module settings */
+
+/*
+ * The function pointers for malloc and free
+ */
+#if defined(POLARSSL_PLATFORM_MEMORY)
+extern void * (*polarssl_malloc)( size_t len );
+extern void (*polarssl_free)( void *ptr );
+
+/**
+ * \brief   Set your own memory implementation function pointers
+ *
+ * \param malloc_func   the malloc function implementation
+ * \param free_func     the free function implementation
+ *
+ * \return              0 if successful
+ */
+int platform_set_malloc_free( void * (*malloc_func)( size_t ),
+                              void (*free_func)( void * ) );
+#else /* POLARSSL_PLATFORM_ENTROPY */
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif /* POLARSSL_PLATFORM_ENTROPY */
+
+/*
+ * The function pointers for printf
+ */
+#if defined(POLARSSL_PLATFORM_PRINTF_ALT)
+extern int (*polarssl_printf)( const char *format, ... );
+
+/**
+ * \brief   Set your own printf function pointer
+ *
+ * \param printf_func   the printf function implementation
+ *
+ * \return              0
+ */
+int platform_set_printf( int (*printf_func)( const char *, ... ) );
+#else /* POLARSSL_PLATFORM_PRINTF_ALT */
+#define polarssl_printf     printf
+#endif /* POLARSSL_PLATFORM_PRINTF_ALT */
+
+/*
+ * The function pointers for fprintf
+ */
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+extern int (*polarssl_fprintf)( FILE *stream, const char *format, ... );
+
+int platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *,
+                                               ... ) );
+#else
+#define polarssl_fprintf    fprintf
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* platform.h */
diff --git a/pdns/ext/polarssl/include/polarssl/ripemd160.h b/pdns/ext/polarssl/include/polarssl/ripemd160.h
new file mode 100644 (file)
index 0000000..e3b66c9
--- /dev/null
@@ -0,0 +1,204 @@
+/**
+ * \file ripemd160.h
+ *
+ * \brief RIPE MD-160 message digest
+ *
+ *  Copyright (C) 2014-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_RIPEMD160_H
+#define POLARSSL_RIPEMD160_H
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#else
+#include <inttypes.h>
+#endif
+
+#define POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR              -0x007E  /**< Read/write error in file. */
+
+#if !defined(POLARSSL_RIPEMD160_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          RIPEMD-160 context structure
+ */
+typedef struct
+{
+    uint32_t total[2];          /*!< number of bytes processed  */
+    uint32_t state[5];          /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+}
+ripemd160_context;
+
+/**
+ * \brief          Initialize RIPEMD-160 context
+ *
+ * \param ctx      RIPEMD-160 context to be initialized
+ */
+void ripemd160_init( ripemd160_context *ctx );
+
+/**
+ * \brief          Clear RIPEMD-160 context
+ *
+ * \param ctx      RIPEMD-160 context to be cleared
+ */
+void ripemd160_free( ripemd160_context *ctx );
+
+/**
+ * \brief          RIPEMD-160 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void ripemd160_starts( ripemd160_context *ctx );
+
+/**
+ * \brief          RIPEMD-160 process buffer
+ *
+ * \param ctx      RIPEMD-160 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void ripemd160_update( ripemd160_context *ctx,
+                       const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          RIPEMD-160 final digest
+ *
+ * \param ctx      RIPEMD-160 context
+ * \param output   RIPEMD-160 checksum result
+ */
+void ripemd160_finish( ripemd160_context *ctx, unsigned char output[20] );
+
+/* Internal use */
+void ripemd160_process( ripemd160_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* POLARSSL_RIPEMD160_ALT */
+#include "ripemd160.h"
+#endif /* POLARSSL_RIPEMD160_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Output = RIPEMD-160( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   RIPEMD-160 checksum result
+ */
+void ripemd160( const unsigned char *input, size_t ilen,
+                unsigned char output[20] );
+
+#if defined(POLARSSL_FS_IO)
+/**
+ * \brief          Output = RIPEMD-160( file contents )
+ *
+ * \param path     input file name
+ * \param output   RIPEMD-160 checksum result
+ *
+ * \return         0 if successful, or POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR
+ */
+int ripemd160_file( const char *path, unsigned char output[20] );
+#endif /* POLARSSL_FS_IO */
+
+/**
+ * \brief          RIPEMD-160 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void ripemd160_hmac_starts( ripemd160_context *ctx,
+                            const unsigned char *key, size_t keylen );
+
+/**
+ * \brief          RIPEMD-160 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void ripemd160_hmac_update( ripemd160_context *ctx,
+                            const unsigned char *input, size_t ilen );
+
+/**
+ * \brief          RIPEMD-160 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   RIPEMD-160 HMAC checksum result
+ */
+void ripemd160_hmac_finish( ripemd160_context *ctx, unsigned char output[20] );
+
+/**
+ * \brief          RIPEMD-160 HMAC context reset
+ *
+ * \param ctx      HMAC context to be reset
+ */
+void ripemd160_hmac_reset( ripemd160_context *ctx );
+
+/**
+ * \brief          Output = HMAC-RIPEMD-160( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-RIPEMD-160 result
+ */
+void ripemd160_hmac( const unsigned char *key, size_t keylen,
+                     const unsigned char *input, size_t ilen,
+                     unsigned char output[20] );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int ripemd160_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ripemd160.h */
index e7b61915986314ee069a4951bc06ed915317fa5a..c06c7d5050c49f6cbe9ed7ea42248d4e904f6d91 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief The RSA public-key cryptosystem
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_RSA_H
 #define POLARSSL_RSA_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include "bignum.h"
 #include "md.h"
@@ -61,6 +65,8 @@
 #define RSA_SIGN        1
 #define RSA_CRYPT       2
 
+#define RSA_SALT_LEN_ANY    -1
+
 /*
  * The above constants may be used even if the RSA module is compile out,
  * eg for alternative (PKCS#11) RSA implemenations in the PK layers.
@@ -122,11 +128,32 @@ rsa_context;
  *
  * \note           The hash_id parameter is actually ignored
  *                 when using RSA_PKCS_V15 padding.
+ *
+ * \note           Choice of padding mode is strictly enforced for private key
+ *                 operations, since there might be security concerns in
+ *                 mixing padding modes. For public key operations it's merely
+ *                 a default value, which can be overriden by calling specific
+ *                 rsa_rsaes_xxx or rsa_rsassa_xxx functions.
+ *
+ * \note           The chosen hash is always used for OEAP encryption.
+ *                 For PSS signatures, it's always used for making signatures,
+ *                 but can be overriden (and always is, if set to
+ *                 POLARSSL_MD_NONE) for verifying them.
  */
 void rsa_init( rsa_context *ctx,
                int padding,
                int hash_id);
 
+/**
+ * \brief          Set padding for an already initialized RSA context
+ *                 See \c rsa_init() for details.
+ *
+ * \param ctx      RSA context to be set
+ * \param padding  RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id  RSA_PKCS_V21 hash identifier
+ */
+void rsa_set_padding( rsa_context *ctx, int padding, int hash_id);
+
 /**
  * \brief          Generate an RSA keypair
  *
@@ -386,11 +413,8 @@ int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
  * \note           The "sig" buffer must be as large as the size
  *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
  *
- * \note           In case of PKCS#1 v2.1 encoding keep in mind that
- *                 the hash_id in the RSA context is the one used for the
- *                 encoding. hash_id in the function call is the type of hash
- *                 that is encoded. According to RFC 3447 it is advised to
- *                 keep both hashes the same.
+ * \note           In case of PKCS#1 v2.1 encoding, see comments on
+ * \note           \c rsa_rsassa_pss_sign() for details on md_alg and hash_id.
  */
 int rsa_pkcs1_sign( rsa_context *ctx,
                     int (*f_rng)(void *, unsigned char *, size_t),
@@ -447,9 +471,8 @@ int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
  * \note           The "sig" buffer must be as large as the size
  *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
  *
- * \note           In case of PKCS#1 v2.1 encoding keep in mind that
- *                 the hash_id in the RSA context is the one used for the
- *                 encoding. hash_id in the function call is the type of hash
+ * \note           The hash_id in the RSA context is the one used for the
+ *                 encoding. md_alg in the function call is the type of hash
  *                 that is encoded. According to RFC 3447 it is advised to
  *                 keep both hashes the same.
  */
@@ -482,11 +505,8 @@ int rsa_rsassa_pss_sign( rsa_context *ctx,
  * \note           The "sig" buffer must be as large as the size
  *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
  *
- * \note           In case of PKCS#1 v2.1 encoding keep in mind that
- *                 the hash_id in the RSA context is the one used for the
- *                 verification. hash_id in the function call is the type of hash
- *                 that is verified. According to RFC 3447 it is advised to
- *                 keep both hashes the same.
+ * \note           In case of PKCS#1 v2.1 encoding, see comments on
+ *                 \c rsa_rsassa_pss_verify() about md_alg and hash_id.
  */
 int rsa_pkcs1_verify( rsa_context *ctx,
                       int (*f_rng)(void *, unsigned char *, size_t),
@@ -526,7 +546,7 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
 
 /**
  * \brief          Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY)
- * \brief          Do a public RSA and check the message digest
+ *                 (This is the "simple" version.)
  *
  * \param ctx      points to an RSA public key
  * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
@@ -543,11 +563,11 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
  * \note           The "sig" buffer must be as large as the size
  *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
  *
- * \note           In case of PKCS#1 v2.1 encoding keep in mind that
- *                 the hash_id in the RSA context is the one used for the
- *                 verification. hash_id in the function call is the type of hash
- *                 that is verified. According to RFC 3447 it is advised to
- *                 keep both hashes the same.
+ * \note           The hash_id in the RSA context is the one used for the
+ *                 verification. md_alg in the function call is the type of
+ *                 hash that is verified. According to RFC 3447 it is advised to
+ *                 keep both hashes the same. If hash_id in the RSA context is
+ *                 unset, the md_alg from the function call is used.
  */
 int rsa_rsassa_pss_verify( rsa_context *ctx,
                            int (*f_rng)(void *, unsigned char *, size_t),
@@ -558,6 +578,41 @@ int rsa_rsassa_pss_verify( rsa_context *ctx,
                            const unsigned char *hash,
                            const unsigned char *sig );
 
+/**
+ * \brief          Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY)
+ *                 (This is the version with "full" options.)
+ *
+ * \param ctx      points to an RSA public key
+ * \param f_rng    RNG function (Only needed for RSA_PRIVATE)
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param md_alg   a POLARSSL_MD_* (use POLARSSL_MD_NONE for signing raw data)
+ * \param hashlen  message digest length (for POLARSSL_MD_NONE only)
+ * \param hash     buffer holding the message digest
+ * \param mgf1_hash_id message digest used for mask generation
+ * \param expected_salt_len Length of the salt used in padding, use
+ *                 RSA_SALT_LEN_ANY to accept any salt length
+ * \param sig      buffer holding the ciphertext
+ *
+ * \return         0 if the verify operation was successful,
+ *                 or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The "sig" buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ *
+ * \note           The hash_id in the RSA context is ignored.
+ */
+int rsa_rsassa_pss_verify_ext( rsa_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng,
+                               int mode,
+                               md_type_t md_alg,
+                               unsigned int hashlen,
+                               const unsigned char *hash,
+                               md_type_t mgf1_hash_id,
+                               int expected_salt_len,
+                               const unsigned char *sig );
+
 /**
  * \brief          Copy the components of an RSA context
  *
index e1d8e27ca1cb02a59850845cbd421f2038b190b1..cb0c4367f931c404ee797fde9b6bce85d3745de6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief SHA-1 cryptographic hash function
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_SHA1_H
 #define POLARSSL_SHA1_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -62,6 +66,20 @@ typedef struct
 }
 sha1_context;
 
+/**
+ * \brief          Initialize SHA-1 context
+ *
+ * \param ctx      SHA-1 context to be initialized
+ */
+void sha1_init( sha1_context *ctx );
+
+/**
+ * \brief          Clear SHA-1 context
+ *
+ * \param ctx      SHA-1 context to be cleared
+ */
+void sha1_free( sha1_context *ctx );
+
 /**
  * \brief          SHA-1 context setup
  *
@@ -127,7 +145,8 @@ int sha1_file( const char *path, unsigned char output[20] );
  * \param key      HMAC secret key
  * \param keylen   length of the HMAC key
  */
-void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen );
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key,
+                       size_t keylen );
 
 /**
  * \brief          SHA-1 HMAC process buffer
@@ -136,7 +155,8 @@ void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keyle
  * \param input    buffer holding the  data
  * \param ilen     length of the input data
  */
-void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen );
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input,
+                       size_t ilen );
 
 /**
  * \brief          SHA-1 HMAC final digest
index 89df578e91bb5cd6a0ff8f5987c3a6d0acf3cc11..b143674100f56003a3106350018c0c9b3a6f4a59 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief SHA-224 and SHA-256 cryptographic hash function
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_SHA256_H
 #define POLARSSL_SHA256_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -63,6 +67,20 @@ typedef struct
 }
 sha256_context;
 
+/**
+ * \brief          Initialize SHA-256 context
+ *
+ * \param ctx      SHA-256 context to be initialized
+ */
+void sha256_init( sha256_context *ctx );
+
+/**
+ * \brief          Clear SHA-256 context
+ *
+ * \param ctx      SHA-256 context to be cleared
+ */
+void sha256_free( sha256_context *ctx );
+
 /**
  * \brief          SHA-256 context setup
  *
@@ -78,7 +96,8 @@ void sha256_starts( sha256_context *ctx, int is224 );
  * \param input    buffer holding the  data
  * \param ilen     length of the input data
  */
-void sha256_update( sha256_context *ctx, const unsigned char *input, size_t ilen );
+void sha256_update( sha256_context *ctx, const unsigned char *input,
+                    size_t ilen );
 
 /**
  * \brief          SHA-256 final digest
@@ -143,7 +162,8 @@ void sha256_hmac_starts( sha256_context *ctx, const unsigned char *key,
  * \param input    buffer holding the  data
  * \param ilen     length of the input data
  */
-void sha256_hmac_update( sha256_context *ctx, const unsigned char *input, size_t ilen );
+void sha256_hmac_update( sha256_context *ctx, const unsigned char *input,
+                         size_t ilen );
 
 /**
  * \brief          SHA-256 HMAC final digest
index 2c61637ee7d1997a9b60efdf3e80a447117ee8cf..dfbae4a734e9468406050e126c4c5fbfe1b14950 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief SHA-384 and SHA-512 cryptographic hash function
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_SHA512_H
 #define POLARSSL_SHA512_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -64,6 +68,20 @@ typedef struct
 }
 sha512_context;
 
+/**
+ * \brief          Initialize SHA-512 context
+ *
+ * \param ctx      SHA-512 context to be initialized
+ */
+void sha512_init( sha512_context *ctx );
+
+/**
+ * \brief          Clear SHA-512 context
+ *
+ * \param ctx      SHA-512 context to be cleared
+ */
+void sha512_free( sha512_context *ctx );
+
 /**
  * \brief          SHA-512 context setup
  *
@@ -79,7 +97,8 @@ void sha512_starts( sha512_context *ctx, int is384 );
  * \param input    buffer holding the  data
  * \param ilen     length of the input data
  */
-void sha512_update( sha512_context *ctx, const unsigned char *input, size_t ilen );
+void sha512_update( sha512_context *ctx, const unsigned char *input,
+                    size_t ilen );
 
 /**
  * \brief          SHA-512 final digest
@@ -141,7 +160,8 @@ void sha512_hmac_starts( sha512_context *ctx, const unsigned char *key,
  * \param input    buffer holding the  data
  * \param ilen     length of the input data
  */
-void sha512_hmac_update( sha512_context *ctx, const unsigned char *input, size_t ilen );
+void sha512_hmac_update( sha512_context *ctx, const unsigned char *input,
+                         size_t ilen );
 
 /**
  * \brief          SHA-512 HMAC final digest
index e51e5078d6c2cc6eae45f8417f4249ccc1807dcf..bd7f1f775bef8f919afd263a84ccdb1382239d71 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief SSL/TLS functions.
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_SSL_H
 #define POLARSSL_SSL_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 #include "net.h"
 #include "bignum.h"
+#include "ecp.h"
 
 #include "ssl_ciphersuites.h"
 
 #define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED
 #endif
 
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED
+#endif
+
 #if defined(_MSC_VER) && !defined(inline)
 #define inline _inline
 #else
 #define POLARSSL_ERR_SSL_CONN_EOF                          -0x7280  /**< The connection indicated an EOF. */
 #define POLARSSL_ERR_SSL_UNKNOWN_CIPHER                    -0x7300  /**< An unknown cipher was received. */
 #define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN                  -0x7380  /**< The server has no ciphersuites in common with the client. */
-#define POLARSSL_ERR_SSL_NO_SESSION_FOUND                  -0x7400  /**< No session to recover was found. */
+#define POLARSSL_ERR_SSL_NO_RNG                            -0x7400  /**< No RNG was provided to the SSL module. */
 #define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE             -0x7480  /**< No client certification received from the client, but required by the authentication mode. */
 #define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE             -0x7500  /**< Our own certificate(s) is/are too large to send in an SSL message.*/
 #define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED              -0x7580  /**< The own certificate is not set, but needed by the server. */
 #define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET         -0x6E00  /**< Processing of the NewSessionTicket handshake message failed. */
 #define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED            -0x6D80  /**< Session ticket has expired. */
 #define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH                  -0x6D00  /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */
-#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY                  -0x6C80  /**< Unkown identity received (eg, PSK identity) */
+#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY                  -0x6C80  /**< Unknown identity received (eg, PSK identity) */
 #define POLARSSL_ERR_SSL_INTERNAL_ERROR                    -0x6C00  /**< Internal error (eg, unexpected failure in lower-level module) */
+#define POLARSSL_ERR_SSL_COUNTER_WRAPPING                  -0x6B80  /**< A counter would wrap (eg, too many messages exchanged). */
 
 /*
  * Various constants
 #else
 #if defined(POLARSSL_SSL_PROTO_TLS1_2)
 #define SSL_MIN_MINOR_VERSION           SSL_MINOR_VERSION_3
-#endif
-#endif
-#endif
-#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 */
+#endif /* POLARSSL_SSL_PROTO_TLS1   */
+#endif /* POLARSSL_SSL_PROTO_SSL3   */
 
 /* Determine maximum supported version */
 #define SSL_MAX_MAJOR_VERSION           SSL_MAJOR_VERSION_3
 #else
 #if defined(POLARSSL_SSL_PROTO_SSL3)
 #define SSL_MAX_MINOR_VERSION           SSL_MINOR_VERSION_0
-#endif
-#endif
-#endif
-#endif
+#endif /* POLARSSL_SSL_PROTO_SSL3   */
+#endif /* POLARSSL_SSL_PROTO_TLS1   */
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 */
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
 /* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c
  * NONE must be zero so that memset()ing structure to zero works */
 #define SSL_RENEGOTIATION_DISABLED      0
 #define SSL_RENEGOTIATION_ENABLED       1
 
+#define SSL_RENEGOTIATION_NOT_ENFORCED  -1
+#define SSL_RENEGO_MAX_RECORDS_DEFAULT  16
+
 #define SSL_LEGACY_NO_RENEGOTIATION     0
 #define SSL_LEGACY_ALLOW_RENEGOTIATION  1
 #define SSL_LEGACY_BREAK_HANDSHAKE      2
 #define SSL_SESSION_TICKETS_DISABLED     0
 #define SSL_SESSION_TICKETS_ENABLED      1
 
-#if !defined(POLARSSL_CONFIG_OPTIONS)
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(SSL_DEFAULT_TICKET_LIFETIME)
 #define SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
-#endif /* !POLARSSL_CONFIG_OPTIONS */
+#endif
 
 /*
  * Size of the input / output buffer.
  * Note: the RFC defines the default size of SSL / TLS messages. If you
  * change the value here, other clients / servers may not be able to
  * communicate with you anymore. Only change this value if you control
- * both sides of the connection and have it reduced at both sides!
+ * both sides of the connection and have it reduced at both sides, or
+ * if you're using the Max Fragment Length extension and you know all your
+ * peers are using it too!
  */
-#if !defined(POLARSSL_CONFIG_OPTIONS)
+#if !defined(SSL_MAX_CONTENT_LEN)
 #define SSL_MAX_CONTENT_LEN         16384   /**< Size of the input / output buffer */
-#endif /* !POLARSSL_CONFIG_OPTIONS */
+#endif
+
+/* \} name SECTION: Module settings */
 
 /*
- * Allow an extra 512 bytes for the record header
- * and encryption overhead (counter + MAC + padding)
+ * Allow extra bytes for record, authentication and encryption overhead:
+ * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256)
  * and allow for a maximum of 1024 of compression expansion if
  * enabled.
  */
 #define SSL_COMPRESSION_ADD             0
 #endif
 
-#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + SSL_COMPRESSION_ADD + 512)
+#if defined(POLARSSL_RC4_C) || defined(POLARSSL_CIPHER_MODE_CBC)
+/* Ciphersuites using HMAC */
+#if defined(POLARSSL_SHA512_C)
+#define SSL_MAC_ADD                 48  /* SHA-384 used for HMAC */
+#elif defined(POLARSSL_SHA256_C)
+#define SSL_MAC_ADD                 32  /* SHA-256 used for HMAC */
+#else
+#define SSL_MAC_ADD                 20  /* SHA-1   used for HMAC */
+#endif
+#else
+/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */
+#define SSL_MAC_ADD                 16
+#endif
 
-#define SSL_EMPTY_RENEGOTIATION_INFO    0xFF   /**< renegotiation info ext */ 
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#define SSL_PADDING_ADD            256
+#else
+#define SSL_PADDING_ADD              0
+#endif
+
+#define SSL_BUFFER_LEN  ( SSL_MAX_CONTENT_LEN               \
+                        + SSL_COMPRESSION_ADD               \
+                        + 29 /* counter + header + IV */    \
+                        + SSL_MAC_ADD                       \
+                        + SSL_PADDING_ADD                   \
+                        )
+
+/*
+ * Signaling ciphersuite values (SCSV)
+ */
+#define SSL_EMPTY_RENEGOTIATION_INFO    0xFF   /**< renegotiation info ext */
 
 /*
  * Supported Signature and Hash algorithms (For TLS 1.2)
 #define SSL_ALERT_MSG_UNSUPPORTED_EXT      110  /* 0x6E */
 #define SSL_ALERT_MSG_UNRECOGNIZED_NAME    112  /* 0x70 */
 #define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115  /* 0x73 */
+#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */
 
 #define SSL_HS_HELLO_REQUEST            0
 #define SSL_HS_CLIENT_HELLO             1
 
 #define TLS_EXT_SIG_ALG                     13
 
+#define TLS_EXT_ALPN                        16
+
 #define TLS_EXT_SESSION_TICKET              35
 
 #define TLS_EXT_RENEGOTIATION_INFO      0xFF01
 /*
  * Size defines
  */
-#if !defined(POLARSSL_MPI_MAX_SIZE)
-#define POLARSSL_PREMASTER_SIZE             512
-#else
-#define POLARSSL_PREMASTER_SIZE             POLARSSL_MPI_MAX_SIZE
+#if !defined(POLARSSL_PSK_MAX_LEN)
+#define POLARSSL_PSK_MAX_LEN            32 /* 256 bits */
 #endif
 
+/* Dummy type used only for its size */
+union _ssl_premaster_secret
+{
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+    unsigned char _pms_rsa[48];                         /* RFC 5246 8.1.1 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    unsigned char _pms_dhm[POLARSSL_MPI_MAX_SIZE];      /* RFC 5246 8.1.2 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)    || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)  || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED)     || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    unsigned char _pms_ecdh[POLARSSL_ECP_MAX_BYTES];    /* RFC 4492 5.10 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+    unsigned char _pms_psk[4 + 2 * POLARSSL_PSK_MAX_LEN];       /* RFC 4279 2 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    unsigned char _pms_dhe_psk[4 + POLARSSL_MPI_MAX_SIZE
+                                 + POLARSSL_PSK_MAX_LEN];       /* RFC 4279 3 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    unsigned char _pms_rsa_psk[52 + POLARSSL_PSK_MAX_LEN];      /* RFC 4279 4 */
+#endif
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    unsigned char _pms_ecdhe_psk[4 + POLARSSL_ECP_MAX_BYTES
+                                   + POLARSSL_PSK_MAX_LEN];     /* RFC 5489 2 */
+#endif
+};
+
+#define POLARSSL_PREMASTER_SIZE     sizeof( union _ssl_premaster_secret )
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -371,10 +460,10 @@ extern "C" {
  */
 typedef int (*rsa_decrypt_func)( void *ctx, int mode, size_t *olen,
                         const unsigned char *input, unsigned char *output,
-                        size_t output_max_len ); 
+                        size_t output_max_len );
 typedef int (*rsa_sign_func)( void *ctx,
                      int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                     int mode, int hash_id, unsigned int hashlen,
+                     int mode, md_type_t md_alg, unsigned int hashlen,
                      const unsigned char *hash, unsigned char *sig );
 typedef size_t (*rsa_key_len_func)( void *ctx );
 
@@ -471,8 +560,8 @@ struct _ssl_transform
 
 #if defined(POLARSSL_SSL_PROTO_SSL3)
     /* Needed only for SSL v3.0 secret */
-    unsigned char mac_enc[32];          /*!<  SSL v3.0 secret (enc)   */
-    unsigned char mac_dec[32];          /*!<  SSL v3.0 secret (dec)   */
+    unsigned char mac_enc[48];          /*!<  SSL v3.0 secret (enc)   */
+    unsigned char mac_dec[48];          /*!<  SSL v3.0 secret (dec)   */
 #endif /* POLARSSL_SSL_PROTO_SSL3 */
 
     md_context_t md_ctx_enc;            /*!<  MAC (encryption)        */
@@ -498,8 +587,8 @@ struct _ssl_handshake_params
     /*
      * Handshake specific crypto variables
      */
-    int sig_alg;                        /*!<  Signature algorithm     */
-    int cert_type;                      /*!<  Requested cert type     */
+    int sig_alg;                        /*!<  Hash algorithm for signature   */
+    int cert_type;                      /*!<  Requested cert type            */
     int verify_sig_alg;                 /*!<  Signature algorithm for verify */
 #if defined(POLARSSL_DHM_C)
     dhm_context dhm_ctx;                /*!<  DHM key exchange        */
@@ -521,7 +610,7 @@ struct _ssl_handshake_params
 #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
     ssl_key_cert *sni_key_cert;         /*!<  key/cert list from SNI  */
 #endif
-#endif
+#endif /* POLARSSL_X509_CRT_PARSE_C */
 
     /*
      * Checksum contexts
@@ -596,6 +685,7 @@ struct _ssl_context
      */
     int state;                  /*!< SSL handshake: current state     */
     int renegotiation;          /*!< Initial or renegotiation         */
+    int renego_records_seen;    /*!< Records since renego request     */
 
     int major_ver;              /*!< equal to  SSL_MAJOR_VERSION_3    */
     int minor_ver;              /*!< either 0 (SSL3) or 1 (TLS1.0)    */
@@ -720,7 +810,11 @@ struct _ssl_context
     int verify_result;                  /*!<  verification result     */
     int disable_renegotiation;          /*!<  enable/disable renegotiation   */
     int allow_legacy_renegotiation;     /*!<  allow legacy renegotiation     */
+    int renego_max_records;             /*!<  grace period for renegotiation */
     const int *ciphersuite_list[4];     /*!<  allowed ciphersuites / version */
+#if defined(POLARSSL_SSL_SET_CURVES)
+    const ecp_group_id *curve_list;     /*!<  allowed curves                 */
+#endif
 #if defined(POLARSSL_SSL_TRUNCATED_HMAC)
     int trunc_hmac;                     /*!<  negotiate truncated hmac?      */
 #endif
@@ -752,6 +846,14 @@ struct _ssl_context
     size_t         hostname_len;
 #endif
 
+#if defined(POLARSSL_SSL_ALPN)
+    /*
+     * ALPN extension
+     */
+    const char **alpn_list;     /*!<  ordered list of supported protocols   */
+    const char *alpn_chosen;    /*!<  negotiated protocol                   */
+#endif
+
     /*
      * Secure renegotiation
      */
@@ -779,7 +881,7 @@ extern int (*ssl_hw_record_reset)(ssl_context *ssl);
 extern int (*ssl_hw_record_write)(ssl_context *ssl);
 extern int (*ssl_hw_record_read)(ssl_context *ssl);
 extern int (*ssl_hw_record_finish)(ssl_context *ssl);
-#endif
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
 
 /**
  * \brief Returns the list of ciphersuites supported by the SSL/TLS module.
@@ -790,8 +892,8 @@ extern int (*ssl_hw_record_finish)(ssl_context *ssl);
 const int *ssl_list_ciphersuites( void );
 
 /**
- * \brief               Return the name of the ciphersuite associated with the given
- *                      ID
+ * \brief               Return the name of the ciphersuite associated with the
+ *                      given ID
  *
  * \param ciphersuite_id SSL ciphersuite ID
  *
@@ -800,8 +902,8 @@ const int *ssl_list_ciphersuites( void );
 const char *ssl_get_ciphersuite_name( const int ciphersuite_id );
 
 /**
- * \brief               Return the ID of the ciphersuite associated with the given
- *                      name
+ * \brief               Return the ID of the ciphersuite associated with the
+ *                      given name
  *
  * \param ciphersuite_name SSL ciphersuite name
  *
@@ -859,6 +961,12 @@ void ssl_set_endpoint( ssl_context *ssl, int endpoint );
  *
  *  SSL_VERIFY_REQUIRED:  peer *must* present a valid certificate,
  *                        handshake is aborted if verification failed.
+ *
+ * \note On client, SSL_VERIFY_REQUIRED is the recommended mode.
+ * With SSL_VERIFY_OPTIONAL, the user needs to call ssl_get_verify_result() at
+ * the right time(s), which may not be obvious, while REQUIRED always perform
+ * the verification as soon as possible. For example, REQUIRED was protecting
+ * against the "triple handshake" attack even before it was found.
  */
 void ssl_set_authmode( ssl_context *ssl, int authmode );
 
@@ -972,17 +1080,22 @@ void ssl_set_session_cache( ssl_context *ssl,
 int ssl_set_session( ssl_context *ssl, const ssl_session *session );
 
 /**
- * \brief               Set the list of allowed ciphersuites
+ * \brief               Set the list of allowed ciphersuites and the preference
+ *                      order. First in the list has the highest preference.
  *                      (Overrides all version specific lists)
  *
+ *                      Note: The PolarSSL SSL server uses its own preferences
+ *                      over the preference of the connection SSL client unless
+ *                      POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined!
+ *
  * \param ssl           SSL context
  * \param ciphersuites  0-terminated list of allowed ciphersuites
  */
 void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites );
 
 /**
- * \brief               Set the list of allowed ciphersuites for a specific
- *                      version of the protocol.
+ * \brief               Set the list of allowed ciphersuites and the
+ *                      preference order for a specific version of the protocol.
  *                      (Only useful on the server side)
  *
  * \param ssl           SSL context
@@ -1038,6 +1151,9 @@ int ssl_set_own_cert( ssl_context *ssl, x509_crt *own_cert,
  *                 up your certificate chain. The top certificate (self-signed)
  *                 can be omitted.
  *
+ * \warning        This backwards-compatibility function is deprecated!
+ *                 Please use \c ssl_set_own_cert() instead.
+ *
  * \param ssl      SSL context
  * \param own_cert own public certificate chain
  * \param rsa_key  own private RSA key
@@ -1060,6 +1176,10 @@ int ssl_set_own_cert_rsa( ssl_context *ssl, x509_crt *own_cert,
  *                 up your certificate chain. The top certificate (self-signed)
  *                 can be omitted.
  *
+ * \warning        This backwards-compatibility function is deprecated!
+ *                 Please use \c pk_init_ctx_rsa_alt()
+ *                 and \c ssl_set_own_cert() instead.
+ *
  * \param ssl      SSL context
  * \param own_cert own public certificate chain
  * \param rsa_key  alternate implementation private RSA key
@@ -1097,7 +1217,7 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
  *
  *                 If set, the PSK callback is called for each
  *                 handshake where a PSK ciphersuite was negotiated.
- *                 The callback provides the identity received and wants to
+ *                 The caller provides the identity received and wants to
  *                 receive the actual PSK data and length.
  *
  *                 The callback has the following parameters: (void *parameter,
@@ -1142,7 +1262,29 @@ int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G );
  * \return         0 if successful
  */
 int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
-#endif
+#endif /* POLARSSL_DHM_C */
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+/**
+ * \brief          Set the allowed curves in order of preference.
+ *                 (Default: all defined curves.)
+ *
+ *                 On server: this only affects selection of the ECDHE curve;
+ *                 the curves used for ECDH and ECDSA are determined by the
+ *                 list of available certificates instead.
+ *
+ *                 On client: this affects the list of curves offered for any
+ *                 use. The server can override our preference order.
+ *
+ *                 Both sides: limits the set of curves used by peer to the
+ *                 listed curves for any use (ECDH(E), certificates).
+ *
+ * \param ssl      SSL context
+ * \param curves   Ordered list of allowed curves,
+ *                 terminated by POLARSSL_ECP_DP_NONE.
+ */
+void ssl_set_curves( ssl_context *ssl, const ecp_group_id *curves );
+#endif /* POLARSSL_SSL_SET_CURVES */
 
 #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
 /**
@@ -1182,6 +1324,30 @@ void ssl_set_sni( ssl_context *ssl,
                   void *p_sni );
 #endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
 
+#if defined(POLARSSL_SSL_ALPN)
+/**
+ * \brief          Set the supported Application Layer Protocols.
+ *
+ * \param ssl      SSL context
+ * \param protos   NULL-terminated list of supported protocols,
+ *                 in decreasing preference order.
+ *
+ * \return         0 on success, or POLARSSL_ERR_SSL_BAD_INPUT_DATA.
+ */
+int ssl_set_alpn_protocols( ssl_context *ssl, const char **protos );
+
+/**
+ * \brief          Get the name of the negotiated Application Layer Protocol.
+ *                 This function should be called after the handshake is
+ *                 completed.
+ *
+ * \param ssl      SSL context
+ *
+ * \return         Protcol name, or NULL if no protocol was negotiated.
+ */
+const char *ssl_get_alpn_protocol( const ssl_context *ssl );
+#endif /* POLARSSL_SSL_ALPN */
+
 /**
  * \brief          Set the maximum supported version sent from the client side
  *                 and/or accepted at the server side
@@ -1296,7 +1462,7 @@ void ssl_set_renegotiation( ssl_context *ssl, int renegotiation );
 /**
  * \brief          Prevent or allow legacy renegotiation.
  *                 (Default: SSL_LEGACY_NO_RENEGOTIATION)
- *                 
+ *
  *                 SSL_LEGACY_NO_RENEGOTIATION allows connections to
  *                 be established even if the peer does not support
  *                 secure renegotiation, but does not allow renegotiation
@@ -1322,6 +1488,33 @@ void ssl_set_renegotiation( ssl_context *ssl, int renegotiation );
  */
 void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy );
 
+/**
+ * \brief          Enforce server-requested renegotiation.
+ *                 (Default: enforced, max_records = 16)
+ *                 (No effect on client.)
+ *
+ *                 When a server requests a renegotiation, the client can
+ *                 comply or ignore the request. This function allows the
+ *                 server to decide if it should enforce its renegotiation
+ *                 requests by closing the connection if the client doesn't
+ *                 initiate a renegotiation.
+ *
+ *                 However, records could already be in transit from the
+ *                 client to the server when the request is emitted. In order
+ *                 to increase reliability, the server can accept a number of
+ *                 records containing application data before the ClientHello
+ *                 that was requested.
+ *
+ *                 The optimal value is highly dependent on the specific usage
+ *                 scenario.
+ *
+ * \param ssl      SSL context
+ * \param max_records Use SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to
+ *                 enforce renegotiation, or a non-negative value to enforce
+ *                 it but allow for a grace period of max_records records.
+ */
+void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records );
+
 /**
  * \brief          Return the number of data bytes available to read
  *
@@ -1489,6 +1682,13 @@ int ssl_close_notify( ssl_context *ssl );
  */
 void ssl_free( ssl_context *ssl );
 
+/**
+ * \brief          Initialize SSL session structure
+ *
+ * \param session  SSL session
+ */
+void ssl_session_init( ssl_session *session );
+
 /**
  * \brief          Free referenced items in an SSL session including the
  *                 peer certificate and clear memory
@@ -1543,7 +1743,8 @@ int ssl_write_change_cipher_spec( ssl_context *ssl );
 int ssl_parse_finished( ssl_context *ssl );
 int ssl_write_finished( ssl_context *ssl );
 
-void ssl_optimize_checksum( ssl_context *ssl, const ssl_ciphersuite_t *ciphersuite_info );
+void ssl_optimize_checksum( ssl_context *ssl,
+                            const ssl_ciphersuite_t *ciphersuite_info );
 
 #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
 int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex );
@@ -1556,6 +1757,10 @@ pk_type_t ssl_pk_alg_from_sig( unsigned char sig );
 
 md_type_t ssl_md_alg_from_hash( unsigned char hash );
 
+#if defined(POLARSSL_SSL_SET_CURVES)
+int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id );
+#endif
+
 #if defined(POLARSSL_X509_CRT_PARSE_C)
 static inline pk_context *ssl_own_key( ssl_context *ssl )
 {
@@ -1568,6 +1773,19 @@ static inline x509_crt *ssl_own_cert( ssl_context *ssl )
     return( ssl->handshake->key_cert == NULL ? NULL
             : ssl->handshake->key_cert->cert );
 }
+
+/*
+ * Check usage of a certificate wrt extensions:
+ * keyUsage, extendedKeyUsage (later), and nSCertType (later).
+ *
+ * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we
+ * check a cert we received from them)!
+ *
+ * Return 0 if everything is OK, -1 if not.
+ */
+int ssl_check_cert_usage( const x509_crt *cert,
+                          const ssl_ciphersuite_t *ciphersuite,
+                          int cert_endpoint );
 #endif /* POLARSSL_X509_CRT_PARSE_C */
 
 /* constant-time buffer comparison */
index daa07acb633007d6dd0b6bca27ce7250e8e0d36b..918fb608eb76924c0d3bfb49cc1cd35c75ad4c83 100644 (file)
 #include "threading.h"
 #endif
 
-#if !defined(POLARSSL_CONFIG_OPTIONS)
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(SSL_CACHE_DEFAULT_TIMEOUT)
 #define SSL_CACHE_DEFAULT_TIMEOUT       86400   /*!< 1 day  */
+#endif
+
+#if !defined(SSL_CACHE_DEFAULT_MAX_ENTRIES)
 #define SSL_CACHE_DEFAULT_MAX_ENTRIES      50   /*!< Maximum entries in cache */
-#endif /* !POLARSSL_CONFIG_OPTIONS */
+#endif
+
+/* \} name SECTION: Module settings */
 
 #ifdef __cplusplus
 extern "C" {
@@ -106,7 +119,7 @@ int ssl_cache_set( void *data, const ssl_session *session );
  *                 A timeout of 0 indicates no timeout.
  *
  * \param cache    SSL cache context
- * \param timeout  cache entry timeout
+ * \param timeout  cache entry timeout in seconds
  */
 void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout );
 #endif /* POLARSSL_HAVE_TIME */
index 3a8f697d8c136f36f1c13d170085a312a1547347..c4f1ffe6449eeb41a2580db320f9a9ebfa1aa778 100644 (file)
@@ -99,20 +99,20 @@ extern "C" {
 #define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256      0xAC   /**< TLS 1.2 */
 #define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384      0xAD   /**< TLS 1.2 */
 
-#define TLS_PSK_WITH_AES_128_CBC_SHA256          0xAE   /**< TLS 1.2 */
-#define TLS_PSK_WITH_AES_256_CBC_SHA384          0xAF   /**< TLS 1.2 */
-#define TLS_PSK_WITH_NULL_SHA256                 0xB0   /**< Weak! TLS 1.2 */
-#define TLS_PSK_WITH_NULL_SHA384                 0xB1   /**< Weak! TLS 1.2 */
+#define TLS_PSK_WITH_AES_128_CBC_SHA256          0xAE
+#define TLS_PSK_WITH_AES_256_CBC_SHA384          0xAF
+#define TLS_PSK_WITH_NULL_SHA256                 0xB0   /**< Weak! */
+#define TLS_PSK_WITH_NULL_SHA384                 0xB1   /**< Weak! */
 
-#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256      0xB2   /**< TLS 1.2 */
-#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384      0xB3   /**< TLS 1.2 */
-#define TLS_DHE_PSK_WITH_NULL_SHA256             0xB4   /**< Weak! TLS 1.2 */
-#define TLS_DHE_PSK_WITH_NULL_SHA384             0xB5   /**< Weak! TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256      0xB2
+#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384      0xB3
+#define TLS_DHE_PSK_WITH_NULL_SHA256             0xB4   /**< Weak! */
+#define TLS_DHE_PSK_WITH_NULL_SHA384             0xB5   /**< Weak! */
 
-#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256      0xB6   /**< TLS 1.2 */
-#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384      0xB7   /**< TLS 1.2 */
-#define TLS_RSA_PSK_WITH_NULL_SHA256             0xB8   /**< Weak! TLS 1.2 */
-#define TLS_RSA_PSK_WITH_NULL_SHA384             0xB9   /**< Weak! TLS 1.2 */
+#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256      0xB6
+#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384      0xB7
+#define TLS_RSA_PSK_WITH_NULL_SHA256             0xB8   /**< Weak! */
+#define TLS_RSA_PSK_WITH_NULL_SHA384             0xB9   /**< Weak! */
 
 #define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256     0xBA   /**< TLS 1.2 */
 #define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE   /**< TLS 1.2 */
@@ -120,12 +120,24 @@ extern "C" {
 #define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256     0xC0   /**< TLS 1.2 */
 #define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4   /**< TLS 1.2 */
 
+#define TLS_ECDH_ECDSA_WITH_NULL_SHA             0xC001 /**< Weak! */
+#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA          0xC002 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA     0xC003 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA      0xC004 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA      0xC005 /**< Not in SSL3! */
+
 #define TLS_ECDHE_ECDSA_WITH_NULL_SHA            0xC006 /**< Weak! */
 #define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA         0xC007 /**< Not in SSL3! */
 #define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA    0xC008 /**< Not in SSL3! */
 #define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA     0xC009 /**< Not in SSL3! */
 #define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA     0xC00A /**< Not in SSL3! */
 
+#define TLS_ECDH_RSA_WITH_NULL_SHA               0xC00B /**< Weak! */
+#define TLS_ECDH_RSA_WITH_RC4_128_SHA            0xC00C /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA       0xC00D /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA        0xC00E /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA        0xC00F /**< Not in SSL3! */
+
 #define TLS_ECDHE_RSA_WITH_NULL_SHA              0xC010 /**< Weak! */
 #define TLS_ECDHE_RSA_WITH_RC4_128_SHA           0xC011 /**< Not in SSL3! */
 #define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA      0xC012 /**< Not in SSL3! */
@@ -134,30 +146,40 @@ extern "C" {
 
 #define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256  0xC023 /**< TLS 1.2 */
 #define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384  0xC024 /**< TLS 1.2 */
-
+#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256   0xC025 /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384   0xC026 /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256    0xC027 /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384    0xC028 /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256     0xC029 /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384     0xC02A /**< TLS 1.2 */
 
 #define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256  0xC02B /**< TLS 1.2 */
 #define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384  0xC02C /**< TLS 1.2 */
-
+#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256   0xC02D /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384   0xC02E /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256    0xC02F /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384    0xC030 /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256     0xC031 /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384     0xC032 /**< TLS 1.2 */
 
 #define TLS_ECDHE_PSK_WITH_RC4_128_SHA           0xC033 /**< Not in SSL3! */
 #define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA      0xC034 /**< Not in SSL3! */
 #define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA       0xC035 /**< Not in SSL3! */
 #define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA       0xC036 /**< Not in SSL3! */
-#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256    0xC037 /**< TLS 1.2 */
-#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384    0xC038 /**< TLS 1.2 */
+#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256    0xC037 /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384    0xC038 /**< Not in SSL3! */
 #define TLS_ECDHE_PSK_WITH_NULL_SHA              0xC039 /**< Weak! No SSL3! */
-#define TLS_ECDHE_PSK_WITH_NULL_SHA256           0xC03A /**< Weak! TLS 1.2 */
-#define TLS_ECDHE_PSK_WITH_NULL_SHA384           0xC03B /**< Weak! TLS 1.2 */
-
-#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< TLS 1.2 */
-#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< TLS 1.2 */
-#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256   0xC076 /**< TLS 1.2 */
-#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384   0xC077 /**< TLS 1.2 */
+#define TLS_ECDHE_PSK_WITH_NULL_SHA256           0xC03A /**< Weak! No SSL3! */
+#define TLS_ECDHE_PSK_WITH_NULL_SHA384           0xC03B /**< Weak! No SSL3! */
+
+#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */
+#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256  0xC074 /**< Not in SSL3! */
+#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384  0xC075 /**< Not in SSL3! */
+#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256   0xC076 /**< Not in SSL3! */
+#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384   0xC077 /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256    0xC078 /**< Not in SSL3! */
+#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384    0xC079 /**< Not in SSL3! */
 
 #define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256         0xC07A /**< TLS 1.2 */
 #define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384         0xC07B /**< TLS 1.2 */
@@ -165,25 +187,53 @@ extern "C" {
 #define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384     0xC07D /**< TLS 1.2 */
 #define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */
 #define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256  0xC088 /**< TLS 1.2 */
+#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384  0xC089 /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256   0xC08A /**< TLS 1.2 */
 #define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384   0xC08B /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256    0xC08C /**< TLS 1.2 */
+#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384    0xC08D /**< TLS 1.2 */
 
-#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256       0xC08D /**< TLS 1.2 */
+#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256       0xC08E /**< TLS 1.2 */
 #define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384       0xC08F /**< TLS 1.2 */
 #define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256   0xC090 /**< TLS 1.2 */
 #define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384   0xC091 /**< TLS 1.2 */
 #define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256   0xC092 /**< TLS 1.2 */
 #define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384   0xC093 /**< TLS 1.2 */
 
-#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256       0xC094 /**< TLS 1.2 */
-#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384       0xC095 /**< TLS 1.2 */
-#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256   0xC096 /**< TLS 1.2 */
-#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384   0xC097 /**< TLS 1.2 */
-#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256   0xC098 /**< TLS 1.2 */
-#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384   0xC099 /**< TLS 1.2 */
-#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< TLS 1.2 */
-#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< TLS 1.2 */
-
+#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256       0xC094
+#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384       0xC095
+#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256   0xC096
+#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384   0xC097
+#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256   0xC098
+#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384   0xC099
+#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */
+#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */
+
+#define TLS_RSA_WITH_AES_128_CCM                0xC09C  /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_256_CCM                0xC09D  /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_128_CCM            0xC09E  /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_256_CCM            0xC09F  /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_128_CCM_8              0xC0A0  /**< TLS 1.2 */
+#define TLS_RSA_WITH_AES_256_CCM_8              0xC0A1  /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_128_CCM_8          0xC0A2  /**< TLS 1.2 */
+#define TLS_DHE_RSA_WITH_AES_256_CCM_8          0xC0A3  /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_128_CCM                0xC0A4  /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_256_CCM                0xC0A5  /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_128_CCM            0xC0A6  /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_256_CCM            0xC0A7  /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_128_CCM_8              0xC0A8  /**< TLS 1.2 */
+#define TLS_PSK_WITH_AES_256_CCM_8              0xC0A9  /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_128_CCM_8          0xC0AA  /**< TLS 1.2 */
+#define TLS_DHE_PSK_WITH_AES_256_CCM_8          0xC0AB  /**< TLS 1.2 */
+/* The last two are named with PSK_DHE in the RFC, which looks like a typo */
+
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM        0xC0AC  /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM        0xC0AD  /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8      0xC0AE  /**< TLS 1.2 */
+#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8      0xC0AF  /**< TLS 1.2 */
+
+/* Reminder: update _ssl_premaster_secret when adding a new key exchange */
 typedef enum {
     POLARSSL_KEY_EXCHANGE_NONE = 0,
     POLARSSL_KEY_EXCHANGE_RSA,
@@ -194,11 +244,15 @@ typedef enum {
     POLARSSL_KEY_EXCHANGE_DHE_PSK,
     POLARSSL_KEY_EXCHANGE_RSA_PSK,
     POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
+    POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+    POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
 } key_exchange_type_t;
 
 typedef struct _ssl_ciphersuite_t ssl_ciphersuite_t;
 
-#define POLARSSL_CIPHERSUITE_WEAK   0x01    /*<! Weak ciphersuite flag      */
+#define POLARSSL_CIPHERSUITE_WEAK       0x01    /**< Weak ciphersuite flag  */
+#define POLARSSL_CIPHERSUITE_SHORT_TAG  0x02    /**< Short authentication tag,
+                                                     eg for CCM_8 */
 
 /**
  * \brief   This structure is used for storing ciphersuite information
index ceb1277981b9d4c9b0aa9ae9332f0d8f162b121f..1fc9f9826d420ca7346eeb2fae8ec9246f2d876c 100644 (file)
 #ifndef POLARSSL_THREADING_H
 #define POLARSSL_THREADING_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <stdlib.h>
 
@@ -39,10 +43,6 @@ extern "C" {
 #define POLARSSL_ERR_THREADING_BAD_INPUT_DATA              -0x001C  /**< Bad input parameters to function. */
 #define POLARSSL_ERR_THREADING_MUTEX_ERROR                 -0x001E  /**< Locking / unlocking / free failed with error code. */
 
-#if defined(POLARSSL_THREADING_DUMMY)
-typedef void threading_mutex_t;
-#endif
-
 #if defined(POLARSSL_THREADING_PTHREAD)
 #include <pthread.h>
 typedef pthread_mutex_t threading_mutex_t;
index 5ab000e10c19a99983e3cdd5b9bc08332bbdb4b0..383120efea991a6d62e0584b18f25a5ab25a6f06 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief Portable interface to the CPU cycle counter
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_TIMING_H
 #define POLARSSL_TIMING_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if !defined(POLARSSL_TIMING_ALT)
+// Regular implementation
+//
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -68,8 +78,21 @@ void set_alarm( int seconds );
  */
 void m_sleep( int milliseconds );
 
+#if defined(POLARSSL_SELF_TEST)
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if a test failed
+ */
+int timing_self_test( int verbose );
+#endif
+
 #ifdef __cplusplus
 }
 #endif
 
+#else  /* POLARSSL_TIMING_ALT */
+#include "timing_alt.h"
+#endif /* POLARSSL_TIMING_ALT */
+
 #endif /* timing.h */
index 8e2ae7e678a8ed2515aa0a98241b376f74c2ec82..1ee2a3b5ac4108fdbc56b73db45d2e350022fef8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief Run-time version information
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_VERSION_H
 #define POLARSSL_VERSION_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 /**
  * The version number x.y.z is split into three parts.
  */
 #define POLARSSL_VERSION_MAJOR  1
 #define POLARSSL_VERSION_MINOR  3
-#define POLARSSL_VERSION_PATCH  2
+#define POLARSSL_VERSION_PATCH  8
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define POLARSSL_VERSION_NUMBER         0x01030200
-#define POLARSSL_VERSION_STRING         "1.3.2"
-#define POLARSSL_VERSION_STRING_FULL    "PolarSSL 1.3.2"
+#define POLARSSL_VERSION_NUMBER         0x01030800
+#define POLARSSL_VERSION_STRING         "1.3.8"
+#define POLARSSL_VERSION_STRING_FULL    "PolarSSL 1.3.8"
 
 #if defined(POLARSSL_VERSION_C)
 
@@ -75,11 +79,32 @@ void version_get_string( char *string );
 /**
  * Get the full version string ("PolarSSL x.y.z").
  *
- * \param string    The string that will receive the value.
- *                  (Should be at least 18 bytes in size)
+ * \param string    The string that will receive the value. The PolarSSL version
+ *                  string will use 18 bytes AT MOST including a terminating
+ *                  null byte.
+ *                  (So the buffer should be at least 18 bytes to receive this
+ *                  version string).
  */
 void version_get_string_full( char *string );
 
+/**
+ * \brief           Check if support for a feature was compiled into this
+ *                  PolarSSL binary. This allows you to see at runtime if the
+ *                  library was for instance compiled with or without
+ *                  Multi-threading support.
+ *
+ *                  Note: only checks against defines in the sections "System
+ *                        support", "PolarSSL modules" and "PolarSSL feature
+ *                        support" in config.h
+ *
+ * \param feature   The string for the define to check (e.g. "POLARSSL_AES_C")
+ *
+ * \return          0 if the feature is present, -1 if the feature is not
+ *                  present and -2 if support for feature checking as a whole
+ *                  was not compiled in.
+ */
+int version_check_feature( const char *feature );
+
 #ifdef __cplusplus
 }
 #endif
index a4565377082cfc3c7f411ac9b7dd601ebbf7f361..583cb83205a85729a55192e6372f568ddc353ba1 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief X.509 generic defines and structures
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_X509_H
 #define POLARSSL_X509_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include "asn1.h"
 #include "pk.h"
@@ -78,6 +82,8 @@
 #define BADCERT_MISSING             0x40  /**< Certificate was missing. */
 #define BADCERT_SKIP_VERIFY         0x80  /**< Certificate verification was skipped. */
 #define BADCERT_OTHER             0x0100  /**< Other reason (can be used by verify callback) */
+#define BADCERT_FUTURE            0x0200  /**< The certificate validity starts in the future. */
+#define BADCRL_FUTURE             0x0400  /**< The CRL is from the future */
 /* \} name */
 /* \} addtogroup x509_module */
 
 
 /*
  * X.509 extension types
+ *
+ * Comments refer to the status for using certificates. Status can be
+ * different for writing certificates or reading CRLs or CSRs.
  */
 #define EXT_AUTHORITY_KEY_IDENTIFIER    (1 << 0)
 #define EXT_SUBJECT_KEY_IDENTIFIER      (1 << 1)
-#define EXT_KEY_USAGE                   (1 << 2)
+#define EXT_KEY_USAGE                   (1 << 2)    /* Parsed but not used */
 #define EXT_CERTIFICATE_POLICIES        (1 << 3)
 #define EXT_POLICY_MAPPINGS             (1 << 4)
-#define EXT_SUBJECT_ALT_NAME            (1 << 5)
+#define EXT_SUBJECT_ALT_NAME            (1 << 5)    /* Supported (DNS) */
 #define EXT_ISSUER_ALT_NAME             (1 << 6)
 #define EXT_SUBJECT_DIRECTORY_ATTRS     (1 << 7)
-#define EXT_BASIC_CONSTRAINTS           (1 << 8)
+#define EXT_BASIC_CONSTRAINTS           (1 << 8)    /* Supported */
 #define EXT_NAME_CONSTRAINTS            (1 << 9)
 #define EXT_POLICY_CONSTRAINTS          (1 << 10)
-#define EXT_EXTENDED_KEY_USAGE          (1 << 11)
+#define EXT_EXTENDED_KEY_USAGE          (1 << 11)   /* Parsed but not used */
 #define EXT_CRL_DISTRIBUTION_POINTS     (1 << 12)
 #define EXT_INIHIBIT_ANYPOLICY          (1 << 13)
 #define EXT_FRESHEST_CRL                (1 << 14)
 
-#define EXT_NS_CERT_TYPE                (1 << 16)
+#define EXT_NS_CERT_TYPE                (1 << 16)   /* Parsed (and then ?) */
 
 /*
  * Storage format identifiers
@@ -207,6 +216,8 @@ int x509_serial_gets( char *buf, size_t size, const x509_buf *serial );
 
 /**
  * \brief          Give an known OID, return its descriptive string.
+ *                 (Deprecated. Use oid_get_extended_key_usage() instead.)
+ *                 Warning: only works for extended_key_usage OIDs!
  *
  * \param oid      buffer containing the oid
  *
@@ -223,22 +234,33 @@ const char *x509_oid_get_description( x509_buf *oid );
  * \param size     Maximum size of buffer
  * \param oid      Buffer containing the OID
  *
- * \return         The amount of data written to the buffer, or -1 in
- *                 case of an error.
+ * \return         Length of the string written (excluding final NULL) or
+ *                 POLARSSL_ERR_OID_BUF_TO_SMALL in case of error
  */
 int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid );
 
 /**
  * \brief          Check a given x509_time against the system time and check
- *                 if it is valid.
+ *                 if it is not expired.
  *
  * \param time     x509_time to check
  *
- * \return         Return 0 if the x509_time is still valid,
- *                 or 1 otherwise.
+ * \return         0 if the x509_time is still valid,
+ *                 1 otherwise.
  */
 int x509_time_expired( const x509_time *time );
 
+/**
+ * \brief          Check a given x509_time against the system time and check
+ *                 if it is not from the future.
+ *
+ * \param time     x509_time to check
+ *
+ * \return         0 if the x509_time is already valid,
+ *                 1 otherwise.
+ */
+int x509_time_future( const x509_time *time );
+
 /**
  * \brief          Checkup routine
  *
@@ -254,9 +276,17 @@ int x509_get_name( unsigned char **p, const unsigned char *end,
                    x509_name *cur );
 int x509_get_alg_null( unsigned char **p, const unsigned char *end,
                        x509_buf *alg );
+int x509_get_alg( unsigned char **p, const unsigned char *end,
+                  x509_buf *alg, x509_buf *params );
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+int x509_get_rsassa_pss_params( const x509_buf *params,
+                                md_type_t *md_alg, md_type_t *mgf_md,
+                                int *salt_len );
+#endif
 int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig );
-int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
-                      pk_type_t *pk_alg );
+int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params,
+                      md_type_t *md_alg, pk_type_t *pk_alg,
+                      void **sig_opts );
 int x509_get_time( unsigned char **p, const unsigned char *end,
                    x509_time *time );
 int x509_get_serial( unsigned char **p, const unsigned char *end,
@@ -264,9 +294,14 @@ int x509_get_serial( unsigned char **p, const unsigned char *end,
 int x509_get_ext( unsigned char **p, const unsigned char *end,
                   x509_buf *ext, int tag );
 int x509_load_file( const char *path, unsigned char **buf, size_t *n );
+int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid,
+                       pk_type_t pk_alg, md_type_t md_alg,
+                       const void *sig_opts );
 int x509_key_size_helper( char *buf, size_t size, const char *name );
 int x509_string_to_names( asn1_named_data **head, const char *name );
-int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,                       int critical, const unsigned char *val, size_t val_len );
+int x509_set_extension( asn1_named_data **head, const char *oid, size_t oid_len,
+                        int critical, const unsigned char *val,
+                        size_t val_len );
 int x509_write_extensions( unsigned char **p, unsigned char *start,
                            asn1_named_data *first );
 int x509_write_names( unsigned char **p, unsigned char *start,
index 0c79916affa0931580fa40a8f950417b7ea9cc05..9f597a855ac8c61e940547c7d08b2da15a82e747 100644 (file)
 #ifndef POLARSSL_X509_CRL_H
 #define POLARSSL_X509_CRL_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include "x509.h"
 
@@ -71,7 +75,7 @@ typedef struct _x509_crl
     x509_buf raw;           /**< The raw certificate data (DER). */
     x509_buf tbs;           /**< The raw certificate body (DER). The part that is To Be Signed. */
 
-    int version;
+    int version;            /**< CRL version (1=v1, 2=v2) */
     x509_buf sig_oid1;
 
     x509_buf issuer_raw;    /**< The raw issuer data (DER). */
@@ -88,7 +92,8 @@ typedef struct _x509_crl
     x509_buf sig_oid2;
     x509_buf sig;
     md_type_t sig_md;           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
-    pk_type_t sig_pk            /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
+    pk_type_t sig_pk;           /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */
+    void *sig_opts;             /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */
 
     struct _x509_crl *next;
 }
index a5ab1789aee34f7c9189da6275a9f2b51d649839..4bf8e568f1122a7a199b1869be1442d214b87215 100644 (file)
 #ifndef POLARSSL_X509_CRT_H
 #define POLARSSL_X509_CRT_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include "x509.h"
 
@@ -55,7 +59,7 @@ typedef struct _x509_crt
     x509_buf raw;               /**< The raw certificate data (DER). */
     x509_buf tbs;               /**< The raw certificate body (DER). The part that is To Be Signed. */
 
-    int version;                /**< The X.509 version. (0=v1, 1=v2, 2=v3) */
+    int version;                /**< The X.509 version. (1=v1, 2=v2, 3=v3) */
     x509_buf serial;            /**< Unique id for certificate issued by a specific CA. */
     x509_buf sig_oid1;          /**< Signature algorithm, e.g. sha1RSA */
 
@@ -72,23 +76,24 @@ typedef struct _x509_crt
 
     x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
     x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
-    x509_buf v3_ext;            /**< Optional X.509 v3 extensions. Only Basic Contraints are supported at this time. */
+    x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */
     x509_sequence subject_alt_names;    /**< Optional list of Subject Alternative Names (Only dNSName supported). */
 
     int ext_types;              /**< Bit string containing detected and parsed extensions */
     int ca_istrue;              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
     int max_pathlen;            /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */
 
-    unsigned char key_usage;    /**< Optional key usage extension value: See the values below */
+    unsigned char key_usage;    /**< Optional key usage extension value: See the values in x509.h */
 
     x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
 
-    unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values below */
+    unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */
 
     x509_buf sig_oid2;          /**< Signature algorithm. Must match sig_oid1. */
     x509_buf sig;               /**< Signature: hash of the tbs part signed with the private key. */
     md_type_t sig_md;           /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
-    pk_type_t sig_pk            /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
+    pk_type_t sig_pk;           /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */
+    void *sig_opts;             /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */
 
     struct _x509_crt *next;     /**< Next certificate in the CA-chain. */
 }
@@ -172,6 +177,11 @@ int x509_crt_parse_file( x509_crt *chain, const char *path );
  *                 of failed certificates it encountered. If none complete
  *                 correctly, the first error is returned.
  *
+ * \warning        This function is NOT thread-safe unless
+ *                 POLARSSL_THREADING_PTHREADS is defined. If you're using an
+ *                 alternative threading implementation, you should either use
+ *                 this function only in the main thread, or mutex it.
+ *
  * \param chain    points to the start of the chain
  * \param path     directory / folder to read the certificate files from
  *
@@ -239,6 +249,44 @@ int x509_crt_verify( x509_crt *crt,
                      int (*f_vrfy)(void *, x509_crt *, int, int *),
                      void *p_vrfy );
 
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+/**
+ * \brief          Check usage of certificate against keyUsage extension.
+ *
+ * \param crt      Leaf certificate used.
+ * \param usage    Intended usage(s) (eg KU_KEY_ENCIPHERMENT before using the
+ *                 certificate to perform an RSA key exchange).
+ *
+ * \return         0 is these uses of the certificate are allowed,
+ *                 POLARSSL_ERR_X509_BAD_INPUT_DATA if the keyUsage extension
+ *                 is present but does not contain all the bits set in the
+ *                 usage argument.
+ *
+ * \note           You should only call this function on leaf certificates, on
+ *                 (intermediate) CAs the keyUsage extension is automatically
+ *                 checked by \c x509_crt_verify().
+ */
+int x509_crt_check_key_usage( const x509_crt *crt, int usage );
+#endif /* POLARSSL_X509_CHECK_KEY_USAGE) */
+
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+/**
+ * \brief          Check usage of certificate against extentedJeyUsage.
+ *
+ * \param crt      Leaf certificate used.
+ * \param usage_oid Intended usage (eg OID_SERVER_AUTH or OID_CLIENT_AUTH).
+ * \param usage_len Length of usage_oid (eg given by OID_SIZE()).
+ *
+ * \return         0 is this use of the certificate is allowed,
+ *                 POLARSSL_ERR_X509_BAD_INPUT_DATA if not.
+ *
+ * \note           Usually only makes sense on leaf certificates.
+ */
+int x509_crt_check_extended_key_usage( const x509_crt *crt,
+                                       const char *usage_oid,
+                                       size_t usage_len );
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) */
+
 #if defined(POLARSSL_X509_CRL_PARSE_C)
 /**
  * \brief          Verify the certificate revocation status
@@ -366,7 +414,7 @@ void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key );
  *                  (e.g. POLARSSL_MD_SHA1)
  *
  * \param ctx       CRT context to use
- * \param md_ald    MD algorithm to use
+ * \param md_alg    MD algorithm to use
  */
 void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg );
 
@@ -462,7 +510,7 @@ void x509write_crt_free( x509write_cert *ctx );
  *                        return value to determine where you should start
  *                        using the buffer
  *
- * \param crt       certificate to write away
+ * \param ctx       certificate to write away
  * \param buf       buffer to write to
  * \param size      size of the buffer
  * \param f_rng     RNG function (for signature, see note)
@@ -484,7 +532,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
 /**
  * \brief           Write a built up certificate to a X509 PEM string
  *
- * \param crt       certificate to write away
+ * \param ctx       certificate to write away
  * \param buf       buffer to write to
  * \param size      size of the buffer
  * \param f_rng     RNG function (for signature, see note)
index 7e3830087404df710d426755c5d19073ea7fd3ce..6591e382ebc1b94a1c32565831fbe3a1816381f5 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief X.509 certificate signing request parsing and writing
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #ifndef POLARSSL_X509_CSR_H
 #define POLARSSL_X509_CSR_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include "x509.h"
 
@@ -52,7 +56,7 @@ typedef struct _x509_csr
     x509_buf raw;           /**< The raw CSR data (DER). */
     x509_buf cri;           /**< The raw CertificateRequestInfo body (DER). */
 
-    int version;
+    int version;            /**< CSR version (1=v1). */
 
     x509_buf  subject_raw;  /**< The raw subject data (DER). */
     x509_name subject;      /**< The parsed subject data (named information object). */
@@ -62,7 +66,8 @@ typedef struct _x509_csr
     x509_buf sig_oid;
     x509_buf sig;
     md_type_t sig_md;       /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
-    pk_type_t sig_pk        /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
+    pk_type_t sig_pk;       /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */
+    void *sig_opts;         /**< Signature options to be passed to pk_verify_ext(), e.g. for RSASSA-PSS */
 }
 x509_csr;
 
@@ -80,7 +85,19 @@ x509write_csr;
 
 #if defined(POLARSSL_X509_CSR_PARSE_C)
 /**
- * \brief          Load a Certificate Signing Request (CSR)
+ * \brief          Load a Certificate Signing Request (CSR) in DER format
+ *
+ * \param csr      CSR context to fill
+ * \param buf      buffer holding the CRL data
+ * \param buflen   size of the buffer
+ *
+ * \return         0 if successful, or a specific X509 error code
+ */
+int x509_csr_parse_der( x509_csr *csr,
+                        const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief          Load a Certificate Signing Request (CSR), DER or PEM format
  *
  * \param csr      CSR context to fill
  * \param buf      buffer holding the CRL data
@@ -111,8 +128,8 @@ int x509_csr_parse_file( x509_csr *csr, const char *path );
  * \param prefix   A line prefix
  * \param csr      The X509 CSR to represent
  *
- * \return         The amount of data written to the buffer, or -1 in
- *                 case of an error.
+ * \return         The length of the string written (exluding the terminating
+ *                 null byte), or a negative value in case of an error.
  */
 int x509_csr_info( char *buf, size_t size, const char *prefix,
                    const x509_csr *csr );
@@ -200,7 +217,8 @@ int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
                                     unsigned char ns_cert_type );
 
 /**
- * \brief           Generic function to add to or replace an extension in the CSR
+ * \brief           Generic function to add to or replace an extension in the
+ *                  CSR
  *
  * \param ctx       CSR context to use
  * \param oid       OID of the extension
index 95854d12204d17f85a1fff3e1bcb60270a9c0e59..794c5efa31e13ec6fca1dd9a69b506f5ecab9327 100644 (file)
 #ifndef POLARSSL_XTEA_H
 #define POLARSSL_XTEA_H
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #include <string.h>
 
@@ -60,6 +64,20 @@ typedef struct
 }
 xtea_context;
 
+/**
+ * \brief          Initialize XTEA context
+ *
+ * \param ctx      XTEA context to be initialized
+ */
+void xtea_init( xtea_context *ctx );
+
+/**
+ * \brief          Clear XTEA context
+ *
+ * \param ctx      XTEA context to be cleared
+ */
+void xtea_free( xtea_context *ctx );
+
 /**
  * \brief          XTEA key schedule
  *
index 25fbd436227453a13f4044747bd2ec9308f31e81..74968dedf40feb0dc562d46553367bd17056e547 100644 (file)
@@ -1,4 +1,4 @@
 noinst_LTLIBRARIES=libpolarssl.la
-libpolarssl_la_SOURCES=aes.c arc4.c asn1parse.c asn1write.c base64.c bignum.c blowfish.c camellia.c certs.c cipher.c cipher_wrap.c ctr_drbg.c debug.c des.c dhm.c ecdh.c ecdsa.c ecp.c entropy.c entropy_poll.c error.c gcm.c havege.c md2.c md4.c md5.c md.c md_wrap.c memory_buffer_alloc.c memory.c net.c oid.c padlock.c pbkdf2.c pem.c pk.c pkcs11.c pkcs12.c pkcs5.c pkparse.c pk_wrap.c pkwrite.c rsa.c sha1.c sha256.c sha512.c ssl_cache.c ssl_ciphersuites.c ssl_cli.c ssl_srv.c ssl_tls.c threading.c timing.c version.c x509.c x509_create.c x509_crl.c x509_crt.c x509_csr.c x509write_crt.c x509write_csr.c xtea.c
+libpolarssl_la_SOURCES=aes.c aesni.c arc4.c asn1parse.c asn1write.c base64.c bignum.c blowfish.c camellia.c ccm.c certs.c cipher.c cipher_wrap.c ctr_drbg.c debug.c des.c dhm.c ecdh.c ecdsa.c ecp.c ecp_curves.c entropy.c entropy_poll.c error.c gcm.c havege.c hmac_drbg.c md2.c md4.c md5.c md.c md_wrap.c memory_buffer_alloc.c memory.c net.c oid.c padlock.c pbkdf2.c pem.c pk.c pkcs11.c pkcs12.c pkcs5.c pkparse.c pk_wrap.c pkwrite.c platform.c ripemd160.c rsa.c sha1.c sha256.c sha512.c ssl_cache.c ssl_ciphersuites.c ssl_cli.c ssl_srv.c ssl_tls.c threading.c timing.c version.c version_features.c x509.c x509_create.c x509_crl.c x509_crt.c x509_csr.c x509write_crt.c x509write_csr.c xtea.c
 
 libpolarssl_la_CPPFLAGS=-I$(srcdir)/../include -D_FILE_OFFSET_BITS=64 -Wall -W -Wdeclaration-after-statement
index a3835cead6df1a4050546b09fd9740fa3e496ff0..f295747c590df7ddb41079858004eca039febfad 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  FIPS-197 compliant AES implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_AES_C)
 
 #if defined(POLARSSL_PADLOCK_C)
 #include "polarssl/padlock.h"
 #endif
+#if defined(POLARSSL_AESNI_C)
+#include "polarssl/aesni.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
 
 #if !defined(POLARSSL_AES_ALT)
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * 32-bit integer manipulation macros (little endian)
  */
@@ -333,16 +351,16 @@ static const uint32_t RCON[10] =
     0x0000001B, 0x00000036
 };
 
-#else
+#else /* POLARSSL_AES_ROM_TABLES */
 
 /*
  * Forward S-box & tables
  */
 static unsigned char FSb[256];
-static uint32_t FT0[256]; 
-static uint32_t FT1[256]; 
-static uint32_t FT2[256]; 
-static uint32_t FT3[256]; 
+static uint32_t FT0[256];
+static uint32_t FT1[256];
+static uint32_t FT2[256];
+static uint32_t FT3[256];
 
 /*
  * Reverse S-box & tables
@@ -402,10 +420,10 @@ static void aes_gen_tables( void )
     {
         x = pow[255 - log[i]];
 
-        y  = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
-        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
-        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
-        x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
+        y  = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
         x ^= y ^ 0x63;
 
         FSb[i] = (unsigned char) x;
@@ -443,12 +461,26 @@ static void aes_gen_tables( void )
     }
 }
 
-#endif
+#endif /* POLARSSL_AES_ROM_TABLES */
+
+void aes_init( aes_context *ctx )
+{
+    memset( ctx, 0, sizeof( aes_context ) );
+}
+
+void aes_free( aes_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( aes_context ) );
+}
 
 /*
  * AES key schedule (encryption)
  */
-int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+int aes_setkey_enc( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize )
 {
     unsigned int i;
     uint32_t *RK;
@@ -480,7 +512,12 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
 #endif
     ctx->rk = RK = ctx->buf;
 
-    for( i = 0; i < (keysize >> 5); i++ )
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    if( aesni_supports( POLARSSL_AESNI_AES ) )
+        return( aesni_setkey_enc( (unsigned char *) ctx->rk, key, keysize ) );
+#endif
+
+    for( i = 0; i < ( keysize >> 5 ); i++ )
     {
         GET_UINT32_LE( RK[i], key, i << 2 );
     }
@@ -546,10 +583,6 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
                 RK[15] = RK[7] ^ RK[14];
             }
             break;
-
-        default:
-
-            break;
     }
 
     return( 0 );
@@ -558,21 +591,15 @@ int aes_setkey_enc( aes_context *ctx, const unsigned char *key, unsigned int key
 /*
  * AES key schedule (decryption)
  */
-int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int keysize )
+int aes_setkey_dec( aes_context *ctx, const unsigned char *key,
+                    unsigned int keysize )
 {
-    int i, j;
+    int i, j, ret;
     aes_context cty;
     uint32_t *RK;
     uint32_t *SK;
-    int ret;
 
-    switch( keysize )
-    {
-        case 128: ctx->nr = 10; break;
-        case 192: ctx->nr = 12; break;
-        case 256: ctx->nr = 14; break;
-        default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
-    }
+    aes_init( &cty );
 
 #if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16)
     if( aes_padlock_ace == -1 )
@@ -584,9 +611,20 @@ int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int key
 #endif
     ctx->rk = RK = ctx->buf;
 
-    ret = aes_setkey_enc( &cty, key, keysize );
-    if( ret != 0 )
-        return( ret );
+    /* Also checks keysize */
+    if( ( ret = aes_setkey_enc( &cty, key, keysize ) ) != 0 )
+        goto exit;
+
+    ctx->nr = cty.nr;
+
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    if( aesni_supports( POLARSSL_AESNI_AES ) )
+    {
+        aesni_inverse_key( (unsigned char *) ctx->rk,
+                           (const unsigned char *) cty.rk, ctx->nr );
+        goto exit;
+    }
+#endif
 
     SK = cty.rk + cty.nr * 4;
 
@@ -611,9 +649,10 @@ int aes_setkey_dec( aes_context *ctx, const unsigned char *key, unsigned int key
     *RK++ = *SK++;
     *RK++ = *SK++;
 
-    memset( &cty, 0, sizeof( aes_context ) );
+exit:
+    aes_free( &cty );
 
-    return( 0 );
+    return( ret );
 }
 
 #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
@@ -673,6 +712,11 @@ int aes_crypt_ecb( aes_context *ctx,
     int i;
     uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
 
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    if( aesni_supports( POLARSSL_AESNI_AES ) )
+        return( aesni_crypt_ecb( ctx, mode, input, output ) );
+#endif
+
 #if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86)
     if( aes_padlock_ace )
     {
@@ -694,7 +738,7 @@ int aes_crypt_ecb( aes_context *ctx,
 
     if( mode == AES_DECRYPT )
     {
-        for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+        for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
         {
             AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
             AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
@@ -728,7 +772,7 @@ int aes_crypt_ecb( aes_context *ctx,
     }
     else /* AES_ENCRYPT */
     {
-        for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
+        for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
         {
             AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
             AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
@@ -791,7 +835,7 @@ int aes_crypt_cbc( aes_context *ctx,
     {
         if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
             return( 0 );
-        
+
         // If padlock data misaligned, we just fall back to
         // unaccelerated mode
         //
@@ -861,7 +905,7 @@ int aes_crypt_cfb128( aes_context *ctx,
             *output++ = (unsigned char)( c ^ iv[n] );
             iv[n] = (unsigned char) c;
 
-            n = (n + 1) & 0x0F;
+            n = ( n + 1 ) & 0x0F;
         }
     }
     else
@@ -873,7 +917,7 @@ int aes_crypt_cfb128( aes_context *ctx,
 
             iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
 
-            n = (n + 1) & 0x0F;
+            n = ( n + 1 ) & 0x0F;
         }
     }
 
@@ -881,6 +925,39 @@ int aes_crypt_cfb128( aes_context *ctx,
 
     return( 0 );
 }
+
+/*
+ * AES-CFB8 buffer encryption/decryption
+ */
+#include <stdio.h>
+int aes_crypt_cfb8( aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    unsigned char c;
+    unsigned char ov[17];
+
+    while( length-- )
+    {
+        memcpy( ov, iv, 16 );
+        aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
+
+        if( mode == AES_DECRYPT )
+            ov[16] = *input;
+
+        c = *output++ = (unsigned char)( iv[0] ^ *input++ );
+
+        if( mode == AES_ENCRYPT )
+            ov[16] = c;
+
+        memcpy( iv, ov + 1, 16 );
+    }
+
+    return( 0 );
+}
 #endif /*POLARSSL_CIPHER_MODE_CFB */
 
 #if defined(POLARSSL_CIPHER_MODE_CTR)
@@ -910,7 +987,7 @@ int aes_crypt_ctr( aes_context *ctx,
         c = *input++;
         *output++ = (unsigned char)( c ^ stream_block[n] );
 
-        n = (n + 1) & 0x0F;
+        n = ( n + 1 ) & 0x0F;
     }
 
     *nc_off = n;
@@ -918,6 +995,7 @@ int aes_crypt_ctr( aes_context *ctx,
     return( 0 );
 }
 #endif /* POLARSSL_CIPHER_MODE_CTR */
+
 #endif /* !POLARSSL_AES_ALT */
 
 #if defined(POLARSSL_SELF_TEST)
@@ -1105,7 +1183,7 @@ static const int aes_test_ctr_len[3] =
  */
 int aes_self_test( int verbose )
 {
-    int i, j, u, v;
+    int ret = 0, i, j, u, v;
     unsigned char key[32];
     unsigned char buf[64];
     unsigned char iv[16];
@@ -1123,6 +1201,7 @@ int aes_self_test( int verbose )
     aes_context ctx;
 
     memset( key, 0, 32 );
+    aes_init( &ctx );
 
     /*
      * ECB mode
@@ -1133,8 +1212,8 @@ int aes_self_test( int verbose )
         v = i  & 1;
 
         if( verbose != 0 )
-            printf( "  AES-ECB-%3d (%s): ", 128 + u * 64,
-                    ( v == AES_DECRYPT ) ? "dec" : "enc" );
+            polarssl_printf( "  AES-ECB-%3d (%s): ", 128 + u * 64,
+                             ( v == AES_DECRYPT ) ? "dec" : "enc" );
 
         memset( buf, 0, 16 );
 
@@ -1148,9 +1227,10 @@ int aes_self_test( int verbose )
             if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
-                return( 1 );
+                ret = 1;
+                goto exit;
             }
         }
         else
@@ -1163,18 +1243,19 @@ int aes_self_test( int verbose )
             if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
-                return( 1 );
+                ret = 1;
+                goto exit;
             }
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
 #if defined(POLARSSL_CIPHER_MODE_CBC)
     /*
@@ -1186,8 +1267,8 @@ int aes_self_test( int verbose )
         v = i  & 1;
 
         if( verbose != 0 )
-            printf( "  AES-CBC-%3d (%s): ", 128 + u * 64,
-                    ( v == AES_DECRYPT ) ? "dec" : "enc" );
+            polarssl_printf( "  AES-CBC-%3d (%s): ", 128 + u * 64,
+                             ( v == AES_DECRYPT ) ? "dec" : "enc" );
 
         memset( iv , 0, 16 );
         memset( prv, 0, 16 );
@@ -1203,9 +1284,10 @@ int aes_self_test( int verbose )
             if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
-                return( 1 );
+                ret = 1;
+                goto exit;
             }
         }
         else
@@ -1226,18 +1308,19 @@ int aes_self_test( int verbose )
             if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
-                return( 1 );
+                ret = 1;
+                goto exit;
             }
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 
 #if defined(POLARSSL_CIPHER_MODE_CFB)
@@ -1250,8 +1333,8 @@ int aes_self_test( int verbose )
         v = i  & 1;
 
         if( verbose != 0 )
-            printf( "  AES-CFB128-%3d (%s): ", 128 + u * 64,
-                    ( v == AES_DECRYPT ) ? "dec" : "enc" );
+            polarssl_printf( "  AES-CFB128-%3d (%s): ", 128 + u * 64,
+                             ( v == AES_DECRYPT ) ? "dec" : "enc" );
 
         memcpy( iv,  aes_test_cfb128_iv, 16 );
         memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
@@ -1267,9 +1350,10 @@ int aes_self_test( int verbose )
             if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
-                return( 1 );
+                ret = 1;
+                goto exit;
             }
         }
         else
@@ -1280,18 +1364,19 @@ int aes_self_test( int verbose )
             if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
-                return( 1 );
+                ret = 1;
+                goto exit;
             }
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 #endif /* POLARSSL_CIPHER_MODE_CFB */
 
 #if defined(POLARSSL_CIPHER_MODE_CTR)
@@ -1304,8 +1389,8 @@ int aes_self_test( int verbose )
         v = i  & 1;
 
         if( verbose != 0 )
-            printf( "  AES-CTR-128 (%s): ",
-                    ( v == AES_DECRYPT ) ? "dec" : "enc" );
+            polarssl_printf( "  AES-CTR-128 (%s): ",
+                             ( v == AES_DECRYPT ) ? "dec" : "enc" );
 
         memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
         memcpy( key, aes_test_ctr_key[u], 16 );
@@ -1318,14 +1403,16 @@ int aes_self_test( int verbose )
             len = aes_test_ctr_len[u];
             memcpy( buf, aes_test_ctr_ct[u], len );
 
-            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                           buf, buf );
 
             if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
-                return( 1 );
+                ret = 1;
+                goto exit;
             }
         }
         else
@@ -1333,28 +1420,35 @@ int aes_self_test( int verbose )
             len = aes_test_ctr_len[u];
             memcpy( buf, aes_test_ctr_pt[u], len );
 
-            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+            aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                           buf, buf );
 
             if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
-                return( 1 );
+                ret = 1;
+                goto exit;
             }
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 
-    return( 0 );
+    ret = 0;
+
+exit:
+    aes_free( &ctx );
+
+    return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_AES_C */
diff --git a/pdns/ext/polarssl/library/aesni.c b/pdns/ext/polarssl/library/aesni.c
new file mode 100644 (file)
index 0000000..97f646e
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ *  AES-NI support functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
+ * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_AESNI_C)
+
+#include "polarssl/aesni.h"
+#include <stdio.h>
+
+#if defined(POLARSSL_HAVE_X86_64)
+
+/*
+ * AES-NI support detection routine
+ */
+int aesni_supports( unsigned int what )
+{
+    static int done = 0;
+    static unsigned int c = 0;
+
+    if( ! done )
+    {
+        asm( "movl  $1, %%eax   \n\t"
+             "cpuid             \n\t"
+             : "=c" (c)
+             :
+             : "eax", "ebx", "edx" );
+        done = 1;
+    }
+
+    return( ( c & what ) != 0 );
+}
+
+/*
+ * Binutils needs to be at least 2.19 to support AES-NI instructions.
+ * Unfortunately, a lot of users have a lower version now (2014-04).
+ * Emit bytecode directly in order to support "old" version of gas.
+ *
+ * Opcodes from the Intel architecture reference manual, vol. 3.
+ * We always use registers, so we don't need prefixes for memory operands.
+ * Operand macros are in gas order (src, dst) as opposed to Intel order
+ * (dst, src) in order to blend better into the surrounding assembly code.
+ */
+#define AESDEC      ".byte 0x66,0x0F,0x38,0xDE,"
+#define AESDECLAST  ".byte 0x66,0x0F,0x38,0xDF,"
+#define AESENC      ".byte 0x66,0x0F,0x38,0xDC,"
+#define AESENCLAST  ".byte 0x66,0x0F,0x38,0xDD,"
+#define AESIMC      ".byte 0x66,0x0F,0x38,0xDB,"
+#define AESKEYGENA  ".byte 0x66,0x0F,0x3A,0xDF,"
+#define PCLMULQDQ   ".byte 0x66,0x0F,0x3A,0x44,"
+
+#define xmm0_xmm0   "0xC0"
+#define xmm0_xmm1   "0xC8"
+#define xmm0_xmm2   "0xD0"
+#define xmm0_xmm3   "0xD8"
+#define xmm0_xmm4   "0xE0"
+#define xmm1_xmm0   "0xC1"
+#define xmm1_xmm2   "0xD1"
+
+/*
+ * AES-NI AES-ECB block en(de)cryption
+ */
+int aesni_crypt_ecb( aes_context *ctx,
+                     int mode,
+                     const unsigned char input[16],
+                     unsigned char output[16] )
+{
+    asm( "movdqu    (%3), %%xmm0    \n\t" // load input
+         "movdqu    (%1), %%xmm1    \n\t" // load round key 0
+         "pxor      %%xmm1, %%xmm0  \n\t" // round 0
+         "addq      $16, %1         \n\t" // point to next round key
+         "subl      $1, %0          \n\t" // normal rounds = nr - 1
+         "test      %2, %2          \n\t" // mode?
+         "jz        2f              \n\t" // 0 = decrypt
+
+         "1:                        \n\t" // encryption loop
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESENC     xmm1_xmm0      "\n\t" // do round
+         "addq      $16, %1         \n\t" // point to next round key
+         "subl      $1, %0          \n\t" // loop
+         "jnz       1b              \n\t"
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESENCLAST xmm1_xmm0      "\n\t" // last round
+         "jmp       3f              \n\t"
+
+         "2:                        \n\t" // decryption loop
+         "movdqu    (%1), %%xmm1    \n\t"
+         AESDEC     xmm1_xmm0      "\n\t" // do round
+         "addq      $16, %1         \n\t"
+         "subl      $1, %0          \n\t"
+         "jnz       2b              \n\t"
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESDECLAST xmm1_xmm0      "\n\t" // last round
+
+         "3:                        \n\t"
+         "movdqu    %%xmm0, (%4)    \n\t" // export output
+         :
+         : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
+         : "memory", "cc", "xmm0", "xmm1" );
+
+
+    return( 0 );
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
+ */
+void aesni_gcm_mult( unsigned char c[16],
+                     const unsigned char a[16],
+                     const unsigned char b[16] )
+{
+    unsigned char aa[16], bb[16], cc[16];
+    size_t i;
+
+    /* The inputs are in big-endian order, so byte-reverse them */
+    for( i = 0; i < 16; i++ )
+    {
+        aa[i] = a[15 - i];
+        bb[i] = b[15 - i];
+    }
+
+    asm( "movdqu (%0), %%xmm0               \n\t" // a1:a0
+         "movdqu (%1), %%xmm1               \n\t" // b1:b0
+
+         /*
+          * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
+          * using [CLMUL-WP] algorithm 1 (p. 13).
+          */
+         "movdqa %%xmm1, %%xmm2             \n\t" // copy of b1:b0
+         "movdqa %%xmm1, %%xmm3             \n\t" // same
+         "movdqa %%xmm1, %%xmm4             \n\t" // same
+         PCLMULQDQ xmm0_xmm1 ",0x00         \n\t" // a0*b0 = c1:c0
+         PCLMULQDQ xmm0_xmm2 ",0x11         \n\t" // a1*b1 = d1:d0
+         PCLMULQDQ xmm0_xmm3 ",0x10         \n\t" // a0*b1 = e1:e0
+         PCLMULQDQ xmm0_xmm4 ",0x01         \n\t" // a1*b0 = f1:f0
+         "pxor %%xmm3, %%xmm4               \n\t" // e1+f1:e0+f0
+         "movdqa %%xmm4, %%xmm3             \n\t" // same
+         "psrldq $8, %%xmm4                 \n\t" // 0:e1+f1
+         "pslldq $8, %%xmm3                 \n\t" // e0+f0:0
+         "pxor %%xmm4, %%xmm2               \n\t" // d1:d0+e1+f1
+         "pxor %%xmm3, %%xmm1               \n\t" // c1+e0+f1:c0
+
+         /*
+          * Now shift the result one bit to the left,
+          * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+          */
+         "movdqa %%xmm1, %%xmm3             \n\t" // r1:r0
+         "movdqa %%xmm2, %%xmm4             \n\t" // r3:r2
+         "psllq $1, %%xmm1                  \n\t" // r1<<1:r0<<1
+         "psllq $1, %%xmm2                  \n\t" // r3<<1:r2<<1
+         "psrlq $63, %%xmm3                 \n\t" // r1>>63:r0>>63
+         "psrlq $63, %%xmm4                 \n\t" // r3>>63:r2>>63
+         "movdqa %%xmm3, %%xmm5             \n\t" // r1>>63:r0>>63
+         "pslldq $8, %%xmm3                 \n\t" // r0>>63:0
+         "pslldq $8, %%xmm4                 \n\t" // r2>>63:0
+         "psrldq $8, %%xmm5                 \n\t" // 0:r1>>63
+         "por %%xmm3, %%xmm1                \n\t" // r1<<1|r0>>63:r0<<1
+         "por %%xmm4, %%xmm2                \n\t" // r3<<1|r2>>62:r2<<1
+         "por %%xmm5, %%xmm2                \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
+
+         /*
+          * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+          * using [CLMUL-WP] algorithm 5 (p. 20).
+          * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
+          */
+         /* Step 2 (1) */
+         "movdqa %%xmm1, %%xmm3             \n\t" // x1:x0
+         "movdqa %%xmm1, %%xmm4             \n\t" // same
+         "movdqa %%xmm1, %%xmm5             \n\t" // same
+         "psllq $63, %%xmm3                 \n\t" // x1<<63:x0<<63 = stuff:a
+         "psllq $62, %%xmm4                 \n\t" // x1<<62:x0<<62 = stuff:b
+         "psllq $57, %%xmm5                 \n\t" // x1<<57:x0<<57 = stuff:c
+
+         /* Step 2 (2) */
+         "pxor %%xmm4, %%xmm3               \n\t" // stuff:a+b
+         "pxor %%xmm5, %%xmm3               \n\t" // stuff:a+b+c
+         "pslldq $8, %%xmm3                 \n\t" // a+b+c:0
+         "pxor %%xmm3, %%xmm1               \n\t" // x1+a+b+c:x0 = d:x0
+
+         /* Steps 3 and 4 */
+         "movdqa %%xmm1,%%xmm0              \n\t" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n\t" // same
+         "movdqa %%xmm1,%%xmm5              \n\t" // same
+         "psrlq $1, %%xmm0                  \n\t" // e1:x0>>1 = e1:e0'
+         "psrlq $2, %%xmm4                  \n\t" // f1:x0>>2 = f1:f0'
+         "psrlq $7, %%xmm5                  \n\t" // g1:x0>>7 = g1:g0'
+         "pxor %%xmm4, %%xmm0               \n\t" // e1+f1:e0'+f0'
+         "pxor %%xmm5, %%xmm0               \n\t" // e1+f1+g1:e0'+f0'+g0'
+         // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing
+         // bits carried from d. Now get those\t bits back in.
+         "movdqa %%xmm1,%%xmm3              \n\t" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n\t" // same
+         "movdqa %%xmm1,%%xmm5              \n\t" // same
+         "psllq $63, %%xmm3                 \n\t" // d<<63:stuff
+         "psllq $62, %%xmm4                 \n\t" // d<<62:stuff
+         "psllq $57, %%xmm5                 \n\t" // d<<57:stuff
+         "pxor %%xmm4, %%xmm3               \n\t" // d<<63+d<<62:stuff
+         "pxor %%xmm5, %%xmm3               \n\t" // missing bits of d:stuff
+         "psrldq $8, %%xmm3                 \n\t" // 0:missing bits of d
+         "pxor %%xmm3, %%xmm0               \n\t" // e1+f1+g1:e0+f0+g0
+         "pxor %%xmm1, %%xmm0               \n\t" // h1:h0
+         "pxor %%xmm2, %%xmm0               \n\t" // x3+h1:x2+h0
+
+         "movdqu %%xmm0, (%2)               \n\t" // done
+         :
+         : "r" (aa), "r" (bb), "r" (cc)
+         : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" );
+
+    /* Now byte-reverse the outputs */
+    for( i = 0; i < 16; i++ )
+        c[i] = cc[15 - i];
+
+    return;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void aesni_inverse_key( unsigned char *invkey,
+                        const unsigned char *fwdkey, int nr )
+{
+    unsigned char *ik = invkey;
+    const unsigned char *fk = fwdkey + 16 * nr;
+
+    memcpy( ik, fk, 16 );
+
+    for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 )
+        asm( "movdqu (%0), %%xmm0       \n\t"
+             AESIMC  xmm0_xmm0         "\n\t"
+             "movdqu %%xmm0, (%1)       \n\t"
+             :
+             : "r" (fk), "r" (ik)
+             : "memory", "xmm0" );
+
+    memcpy( ik, fk, 16 );
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static void aesni_setkey_enc_128( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0               \n\t" // copy the original key
+         "movdqu %%xmm0, (%0)               \n\t" // as round key 0
+         "jmp 2f                            \n\t" // skip auxiliary routine
+
+         /*
+          * Finish generating the next round key.
+          *
+          * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
+          * with X = rot( sub( r3 ) ) ^ RCON.
+          *
+          * On exit, xmm0 is r7:r6:r5:r4
+          * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+          * and those are written to the round key buffer.
+          */
+         "1:                                \n\t"
+         "pshufd $0xff, %%xmm1, %%xmm1      \n\t" // X:X:X:X
+         "pxor %%xmm0, %%xmm1               \n\t" // X+r3:X+r2:X+r1:r4
+         "pslldq $4, %%xmm0                 \n\t" // r2:r1:r0:0
+         "pxor %%xmm0, %%xmm1               \n\t" // X+r3+r2:X+r2+r1:r5:r4
+         "pslldq $4, %%xmm0                 \n\t" // etc
+         "pxor %%xmm0, %%xmm1               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm1, %%xmm0               \n\t" // update xmm0 for next time!
+         "add $16, %0                       \n\t" // point to next round key
+         "movdqu %%xmm0, (%0)               \n\t" // write it
+         "ret                               \n\t"
+
+         /* Main "loop" */
+         "2:                                \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x01        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x02        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x04        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x08        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x10        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x20        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x40        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x80        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x1B        \n\tcall 1b \n\t"
+         AESKEYGENA xmm0_xmm1 ",0x36        \n\tcall 1b \n\t"
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_setkey_enc_192( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0   \n\t" // copy original round key
+         "movdqu %%xmm0, (%0)   \n\t"
+         "add $16, %0           \n\t"
+         "movq 16(%1), %%xmm1   \n\t"
+         "movq %%xmm1, (%0)     \n\t"
+         "add $8, %0            \n\t"
+         "jmp 2f                \n\t" // skip auxiliary routine
+
+         /*
+          * Finish generating the next 6 quarter-keys.
+          *
+          * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
+          * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
+          *
+          * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
+          * and those are written to the round key buffer.
+          */
+         "1:                            \n\t"
+         "pshufd $0x55, %%xmm2, %%xmm2  \n\t" // X:X:X:X
+         "pxor %%xmm0, %%xmm2           \n\t" // X+r3:X+r2:X+r1:r4
+         "pslldq $4, %%xmm0             \n\t" // etc
+         "pxor %%xmm0, %%xmm2           \n\t"
+         "pslldq $4, %%xmm0             \n\t"
+         "pxor %%xmm0, %%xmm2           \n\t"
+         "pslldq $4, %%xmm0             \n\t"
+         "pxor %%xmm2, %%xmm0           \n\t" // update xmm0 = r9:r8:r7:r6
+         "movdqu %%xmm0, (%0)           \n\t"
+         "add $16, %0                   \n\t"
+         "pshufd $0xff, %%xmm0, %%xmm2  \n\t" // r9:r9:r9:r9
+         "pxor %%xmm1, %%xmm2           \n\t" // stuff:stuff:r9+r5:r10
+         "pslldq $4, %%xmm1             \n\t" // r2:r1:r0:0
+         "pxor %%xmm2, %%xmm1           \n\t" // xmm1 = stuff:stuff:r11:r10
+         "movq %%xmm1, (%0)             \n\t"
+         "add $8, %0                    \n\t"
+         "ret                           \n\t"
+
+         "2:                            \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x01    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x02    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x04    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x08    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x10    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x20    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x40    \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x80    \n\tcall 1b \n\t"
+
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_setkey_enc_256( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0           \n\t"
+         "movdqu %%xmm0, (%0)           \n\t"
+         "add $16, %0                   \n\t"
+         "movdqu 16(%1), %%xmm1         \n\t"
+         "movdqu %%xmm1, (%0)           \n\t"
+         "jmp 2f                        \n\t" // skip auxiliary routine
+
+         /*
+          * Finish generating the next two round keys.
+          *
+          * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
+          * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+          *
+          * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
+          * and those have been written to the output buffer.
+          */
+         "1:                                \n\t"
+         "pshufd $0xff, %%xmm2, %%xmm2      \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm2, %%xmm0               \n\t"
+         "add $16, %0                       \n\t"
+         "movdqu %%xmm0, (%0)               \n\t"
+
+         /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
+          * and proceed to generate next round key from there */
+         AESKEYGENA xmm0_xmm2 ",0x00        \n\t"
+         "pshufd $0xaa, %%xmm2, %%xmm2      \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm2, %%xmm1               \n\t"
+         "add $16, %0                       \n\t"
+         "movdqu %%xmm1, (%0)               \n\t"
+         "ret                               \n\t"
+
+         /*
+          * Main "loop" - Generating one more key than necessary,
+          * see definition of aes_context.buf
+          */
+         "2:                                \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x01        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x02        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x04        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x08        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x10        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x20        \n\tcall 1b \n\t"
+         AESKEYGENA xmm1_xmm2 ",0x40        \n\tcall 1b \n\t"
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, wrapper
+ */
+int aesni_setkey_enc( unsigned char *rk,
+                      const unsigned char *key,
+                      size_t bits )
+{
+    switch( bits )
+    {
+        case 128: aesni_setkey_enc_128( rk, key ); break;
+        case 192: aesni_setkey_enc_192( rk, key ); break;
+        case 256: aesni_setkey_enc_256( rk, key ); break;
+        default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH );
+    }
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_HAVE_X86_64 */
+
+#endif /* POLARSSL_AESNI_C */
index 85b78f5ba5d3fcd3a83086c14fd1a02bd47f9d3d..54e89ea888129f44dac93039b40c526391dcfc99 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  An implementation of the ARCFOUR algorithm
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_ARC4_C)
 
 #include "polarssl/arc4.h"
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
 #if !defined(POLARSSL_ARC4_ALT)
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+void arc4_init( arc4_context *ctx )
+{
+    memset( ctx, 0, sizeof( arc4_context ) );
+}
+
+void arc4_free( arc4_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( arc4_context ) );
+}
+
 /*
  * ARC4 key schedule
  */
-void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen )
+void arc4_setup( arc4_context *ctx, const unsigned char *key,
+                 unsigned int keylen )
 {
     int i, j, a;
     unsigned int k;
@@ -135,15 +164,17 @@ static const unsigned char arc4_test_ct[3][8] =
  */
 int arc4_self_test( int verbose )
 {
-    int i;
+    int i, ret = 0;
     unsigned char ibuf[8];
     unsigned char obuf[8];
     arc4_context ctx;
 
+    arc4_init( &ctx );
+
     for( i = 0; i < 3; i++ )
     {
         if( verbose != 0 )
-            printf( "  ARC4 test #%d: ", i + 1 );
+            polarssl_printf( "  ARC4 test #%d: ", i + 1 );
 
         memcpy( ibuf, arc4_test_pt[i], 8 );
 
@@ -153,21 +184,25 @@ int arc4_self_test( int verbose )
         if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
-    return( 0 );
+exit:
+    arc4_free( &ctx );
+
+    return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_ARC4_C */
index 957359917f59424a21661fd595ac3ffc1c5b0d87..97443529a8e599fcc47846fdd298ea89fa04f6b4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Generic ASN.1 parsing
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_ASN1_PARSE_C)
 
@@ -33,8 +37,8 @@
 #include "polarssl/bignum.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
@@ -87,7 +91,8 @@ int asn1_get_len( unsigned char **p,
             if( ( end - *p ) < 5 )
                 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
 
-            *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) | (*p)[4];
+            *len = ( (*p)[1] << 24 ) | ( (*p)[2] << 16 ) | ( (*p)[3] << 8 ) |
+                   (*p)[4];
             (*p) += 5;
             break;
 
@@ -189,7 +194,7 @@ int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
         return( ret );
 
     /* Check length, subtract one for actual bit string length */
-    if ( bs->len < 1 )
+    if( bs->len < 1 )
         return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
     bs->len -= 1;
 
@@ -206,7 +211,7 @@ int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
     if( *p != end )
         return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
 
-    return 0;
+    return( 0 );
 }
 
 /*
@@ -260,7 +265,7 @@ int asn1_get_sequence_of( unsigned char **p,
         *p += buf->len;
 
         /* Allocate and assign next pointer */
-        if (*p < end)
+        if( *p < end )
         {
             cur->next = (asn1_sequence *) polarssl_malloc(
                  sizeof( asn1_sequence ) );
@@ -383,4 +388,4 @@ asn1_named_data *asn1_find_named_data( asn1_named_data *list,
     return( list );
 }
 
-#endif
+#endif /* POLARSSL_ASN1_PARSE_C */
index 32d1c736fcd18fe3f99b1e3a836e078ddca0666e..ebc0e97660366bd88b9fb12c504ca7dadaea67bf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ASN.1 buffer writing functionality
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_ASN1_WRITE_C)
 
 #include "polarssl/asn1write.h"
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #include <stdlib.h>
 #define polarssl_malloc     malloc
@@ -109,12 +113,12 @@ int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X )
         return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
 
     (*p) -= len;
-    mpi_write_binary( X, *p, len );
+    MPI_CHK( mpi_write_binary( X, *p, len ) );
 
     // DER format assumes 2s complement for numbers, so the leftmost bit
     // should be 0 for positive numbers and 1 for negative numbers.
     //
-    if ( X->s ==1 && **p & 0x80 )
+    if( X->s ==1 && **p & 0x80 )
     {
         if( *p - start < 1 )
             return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
@@ -126,7 +130,10 @@ int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X )
     ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
     ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) );
 
-    return( (int) len );
+    ret = (int) len;
+
+cleanup:
+    return( ret );
 }
 #endif /* POLARSSL_BIGNUM_C */
 
@@ -210,7 +217,7 @@ int asn1_write_int( unsigned char **p, unsigned char *start, int val )
     len += 1;
     *--(*p) = val;
 
-    if ( val > 0 && **p & 0x80 )
+    if( val > 0 && **p & 0x80 )
     {
         if( *p - start < 1 )
             return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
@@ -356,4 +363,4 @@ asn1_named_data *asn1_store_named_data( asn1_named_data **head,
 
     return( cur );
 }
-#endif
+#endif /* POLARSSL_ASN1_WRITE_C */
index 3b4376dac58ba908fa3f594f7b901452082fb5ac..39a8323e8391e6c435bd0bd6150068b03c85f23e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  RFC 1521 base64 encoding/decoding
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_BASE64_C)
 
@@ -36,6 +40,12 @@ typedef UINT32 uint32_t;
 #include <inttypes.h>
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
 static const unsigned char base64_enc_map[64] =
 {
     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
@@ -77,9 +87,9 @@ int base64_encode( unsigned char *dst, size_t *dlen,
     if( slen == 0 )
         return( 0 );
 
-    n = (slen << 3) / 6;
+    n = ( slen << 3 ) / 6;
 
-    switch( (slen << 3) - (n * 6) )
+    switch( ( slen << 3 ) - ( n * 6 ) )
     {
         case  2: n += 3; break;
         case  4: n += 2; break;
@@ -92,7 +102,7 @@ int base64_encode( unsigned char *dst, size_t *dlen,
         return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
     }
 
-    n = (slen / 3) * 3;
+    n = ( slen / 3 ) * 3;
 
     for( i = 0, p = dst; i < n; i += 3 )
     {
@@ -109,12 +119,12 @@ int base64_encode( unsigned char *dst, size_t *dlen,
     if( i < slen )
     {
         C1 = *src++;
-        C2 = ((i + 1) < slen) ? *src++ : 0;
+        C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
 
         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
         *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
 
-        if( (i + 1) < slen )
+        if( ( i + 1 ) < slen )
              *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
         else *p++ = '=';
 
@@ -161,7 +171,8 @@ int base64_decode( unsigned char *dst, size_t *dlen,
     if( n == 0 )
         return( 0 );
 
-    n = ((n * 6) + 7) >> 3;
+    n = ( ( n * 6 ) + 7 ) >> 3;
+    n -= j;
 
     if( dst == NULL || *dlen < n )
     {
@@ -175,7 +186,7 @@ int base64_decode( unsigned char *dst, size_t *dlen,
             continue;
 
         j -= ( base64_dec_map[*src] == 64 );
-        x  = (x << 6) | ( base64_dec_map[*src] & 0x3F );
+        x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
 
         if( ++n == 4 )
         {
@@ -222,7 +233,7 @@ int base64_self_test( int verbose )
     unsigned char buffer[128];
 
     if( verbose != 0 )
-        printf( "  Base64 encoding test: " );
+        polarssl_printf( "  Base64 encoding test: " );
 
     len = sizeof( buffer );
     src = base64_test_dec;
@@ -231,13 +242,13 @@ int base64_self_test( int verbose )
          memcmp( base64_test_enc, buffer, 88 ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( 1 );
     }
 
     if( verbose != 0 )
-        printf( "passed\n  Base64 decoding test: " );
+        polarssl_printf( "passed\n  Base64 decoding test: " );
 
     len = sizeof( buffer );
     src = base64_test_enc;
@@ -246,17 +257,17 @@ int base64_self_test( int verbose )
          memcmp( base64_test_dec, buffer, 64 ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( 1 );
     }
 
     if( verbose != 0 )
-        printf( "passed\n\n" );
+        polarssl_printf( "passed\n\n" );
 
     return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_BASE64_C */
index 2a97a590266fa892354ab919b86640a26d5635ea..80cf0f800825d41a1bffcbeb8505b0b6a5f19890 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Multi-precision integer library
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://math.libtomcrypt.com/files/tommath.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_BIGNUM_C)
 
 #include "polarssl/bignum.h"
 #include "polarssl/bn_mul.h"
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
+#define polarssl_printf     printf
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #endif
 
 #include <stdlib.h>
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #define ciL    (sizeof(t_uint))         /* chars in limb  */
 #define biL    (ciL << 3)               /* bits  in limb  */
 #define biH    (ciL << 2)               /* half limb size */
@@ -79,7 +89,7 @@ void mpi_free( mpi *X )
 
     if( X->p != NULL )
     {
-        memset( X->p, 0, X->n * ciL );
+        polarssl_zeroize( X->p, X->n * ciL );
         polarssl_free( X->p );
     }
 
@@ -108,7 +118,7 @@ int mpi_grow( mpi *X, size_t nblimbs )
         if( X->p != NULL )
         {
             memcpy( p, X->p, X->n * ciL );
-            memset( X->p, 0, X->n * ciL );
+            polarssl_zeroize( X->p, X->n * ciL );
             polarssl_free( X->p );
         }
 
@@ -119,6 +129,45 @@ int mpi_grow( mpi *X, size_t nblimbs )
     return( 0 );
 }
 
+/*
+ * Resize down as much as possible,
+ * while keeping at least the specified number of limbs
+ */
+int mpi_shrink( mpi *X, size_t nblimbs )
+{
+    t_uint *p;
+    size_t i;
+
+    /* Actually resize up in this case */
+    if( X->n <= nblimbs )
+        return( mpi_grow( X, nblimbs ) );
+
+    for( i = X->n - 1; i > 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+    i++;
+
+    if( i < nblimbs )
+        i = nblimbs;
+
+    if( ( p = (t_uint *) polarssl_malloc( i * ciL ) ) == NULL )
+        return( POLARSSL_ERR_MPI_MALLOC_FAILED );
+
+    memset( p, 0, i * ciL );
+
+    if( X->p != NULL )
+    {
+        memcpy( p, X->p, i * ciL );
+        polarssl_zeroize( X->p, X->n * ciL );
+        polarssl_free( X->p );
+    }
+
+    X->n = i;
+    X->p = p;
+
+    return( 0 );
+}
+
 /*
  * Copy the contents of Y into X
  */
@@ -165,6 +214,70 @@ void mpi_swap( mpi *X, mpi *Y )
     memcpy(  Y, &T, sizeof( mpi ) );
 }
 
+/*
+ * Conditionally assign X = Y, without leaking information
+ * about whether the assignment was made or not.
+ * (Leaking information about the respective sizes of X and Y is ok however.)
+ */
+int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign )
+{
+    int ret = 0;
+    size_t i;
+
+    /* make sure assign is 0 or 1 */
+    assign = ( assign != 0 );
+
+    MPI_CHK( mpi_grow( X, Y->n ) );
+
+    X->s = X->s * ( 1 - assign ) + Y->s * assign;
+
+    for( i = 0; i < Y->n; i++ )
+        X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
+
+    for( ; i < X->n; i++ )
+        X->p[i] *= ( 1 - assign );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Conditionally swap X and Y, without leaking information
+ * about whether the swap was made or not.
+ * Here it is not ok to simply swap the pointers, which whould lead to
+ * different memory access patterns when X and Y are used afterwards.
+ */
+int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap )
+{
+    int ret, s;
+    size_t i;
+    t_uint tmp;
+
+    if( X == Y )
+        return( 0 );
+
+    /* make sure swap is 0 or 1 */
+    swap = ( swap != 0 );
+
+    MPI_CHK( mpi_grow( X, Y->n ) );
+    MPI_CHK( mpi_grow( Y, X->n ) );
+
+    s = X->s;
+    X->s = X->s * ( 1 - swap ) + Y->s * swap;
+    Y->s = Y->s * ( 1 - swap ) +    s * swap;
+
+
+    for( i = 0; i < X->n; i++ )
+    {
+        tmp = X->p[i];
+        X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
+        Y->p[i] = Y->p[i] * ( 1 - swap ) +     tmp * swap;
+    }
+
+cleanup:
+    return( ret );
+}
+
 /*
  * Set value from integer
  */
@@ -191,7 +304,7 @@ int mpi_get_bit( const mpi *X, size_t pos )
     if( X->n * biL <= pos )
         return( 0 );
 
-    return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01;
+    return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
 }
 
 /*
@@ -204,20 +317,21 @@ int mpi_set_bit( mpi *X, size_t pos, unsigned char val )
     size_t idx = pos % biL;
 
     if( val != 0 && val != 1 )
-        return POLARSSL_ERR_MPI_BAD_INPUT_DATA;
-        
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
     if( X->n * biL <= pos )
     {
         if( val == 0 )
-            return ( 0 );
+            return( 0 );
 
         MPI_CHK( mpi_grow( X, off + 1 ) );
     }
 
-    X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx );
+    X->p[off] &= ~( (t_uint) 0x01 << idx );
+    X->p[off] |= (t_uint) val << idx;
 
 cleanup:
-    
+
     return( ret );
 }
 
@@ -312,7 +426,7 @@ int mpi_read_string( mpi *X, int radix, const char *s )
             }
 
             MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
-            X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
+            X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
         }
     }
     else
@@ -416,7 +530,7 @@ int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen )
             {
                 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
 
-                if( c == 0 && k == 0 && ( i + j + 3 ) != 0 )
+                if( c == 0 && k == 0 && ( i + j ) != 2 )
                     continue;
 
                 *(p++) = "0123456789ABCDEF" [c / 16];
@@ -512,7 +626,7 @@ int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
             return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
     }
     else
-        printf( "%s%s", p, s );
+        polarssl_printf( "%s%s", p, s );
 
 cleanup:
 
@@ -751,7 +865,7 @@ int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
 
     if( X != A )
         MPI_CHK( mpi_copy( X, A ) );
-   
+
     /*
      * X should always be positive as a result of unsigned additions.
      */
@@ -974,7 +1088,7 @@ void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
         MULADDC_CORE
         MULADDC_STOP
     }
-#else
+#else /* MULADDC_HUIT */
     for( ; i >= 16; i -= 16 )
     {
         MULADDC_INIT
@@ -1007,7 +1121,7 @@ void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b )
         MULADDC_CORE
         MULADDC_STOP
     }
-#endif
+#endif /* MULADDC_HUIT */
 
     t++;
 
@@ -1112,14 +1226,14 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
 
     n = X.n - 1;
     t = Y.n - 1;
-    MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) );
+    MPI_CHK( mpi_shift_l( &Y, biL * ( n - t ) ) );
 
     while( mpi_cmp_mpi( &X, &Y ) >= 0 )
     {
         Z.p[n - t]++;
-        mpi_sub_mpi( &X, &X, &Y );
+        MPI_CHK( mpi_sub_mpi( &X, &X, &Y ) );
     }
-    mpi_shift_r( &Y, biL * (n - t) );
+    MPI_CHK( mpi_shift_r( &Y, biL * ( n - t ) ) );
 
     for( i = n; i > t ; i-- )
     {
@@ -1127,14 +1241,24 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
             Z.p[i - t - 1] = ~0;
         else
         {
-#if defined(POLARSSL_HAVE_UDBL)
+            /*
+             * The version of Clang shipped by Apple with Mavericks around
+             * 2014-03 can't handle 128-bit division properly. Disable
+             * 128-bits division for this version. Let's be optimistic and
+             * assume it'll be fixed in the next minor version (next
+             * patchlevel is probably a bit too optimistic).
+             */
+#if defined(POLARSSL_HAVE_UDBL) &&                          \
+    ! ( defined(__x86_64__) && defined(__APPLE__) &&        \
+        defined(__clang_major__) && __clang_major__ == 5 && \
+        defined(__clang_minor__) && __clang_minor__ == 0 )
             t_udbl r;
 
             r  = (t_udbl) X.p[i] << biL;
             r |= (t_udbl) X.p[i - 1];
             r /= Y.p[t];
-            if( r > ((t_udbl) 1 << biL) - 1)
-                r = ((t_udbl) 1 << biL) - 1;
+            if( r > ( (t_udbl) 1 << biL ) - 1 )
+                r = ( (t_udbl) 1 << biL ) - 1;
 
             Z.p[i - t - 1] = (t_uint) r;
 #else
@@ -1177,7 +1301,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
             r0 -= m;
 
             Z.p[i - t - 1] = ( q1 << biH ) | q0;
-#endif
+#endif /* POLARSSL_HAVE_UDBL && !64-bit Apple with Clang 5.0 */
         }
 
         Z.p[i - t - 1]++;
@@ -1186,25 +1310,25 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
             Z.p[i - t - 1]--;
 
             MPI_CHK( mpi_lset( &T1, 0 ) );
-            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+            T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
             T1.p[1] = Y.p[t];
             MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
 
             MPI_CHK( mpi_lset( &T2, 0 ) );
-            T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
-            T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+            T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
+            T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
             T2.p[2] = X.p[i];
         }
         while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
 
         MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
-        MPI_CHK( mpi_shift_l( &T1,  biL * (i - t - 1) ) );
+        MPI_CHK( mpi_shift_l( &T1,  biL * ( i - t - 1 ) ) );
         MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
 
         if( mpi_cmp_int( &X, 0 ) < 0 )
         {
             MPI_CHK( mpi_copy( &T1, &Y ) );
-            MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+            MPI_CHK( mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
             MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
             Z.p[i - t - 1]--;
         }
@@ -1212,15 +1336,15 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
 
     if( Q != NULL )
     {
-        mpi_copy( Q, &Z );
+        MPI_CHK( mpi_copy( Q, &Z ) );
         Q->s = A->s * B->s;
     }
 
     if( R != NULL )
     {
-        mpi_shift_r( &X, k );
+        MPI_CHK( mpi_shift_r( &X, k ) );
         X.s = A->s;
-        mpi_copy( R, &X );
+        MPI_CHK( mpi_copy( R, &X ) );
 
         if( mpi_cmp_int( R, 0 ) == 0 )
             R->s = 1;
@@ -1258,7 +1382,7 @@ int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
     int ret;
 
     if( mpi_cmp_int( B, 0 ) < 0 )
-        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+        return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
 
     MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
 
@@ -1285,7 +1409,7 @@ int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
         return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
 
     if( b < 0 )
-        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+        return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
 
     /*
      * handle trivial cases
@@ -1336,14 +1460,13 @@ int mpi_mod_int( t_uint *r, const mpi *A, t_sint b )
 static void mpi_montg_init( t_uint *mm, const mpi *N )
 {
     t_uint x, m0 = N->p[0];
+    unsigned int i;
 
     x  = m0;
     x += ( ( m0 + 2 ) & 4 ) << 1;
-    x *= ( 2 - ( m0 * x ) );
 
-    if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
-    if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
-    if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
+    for( i = biL; i >= 8; i /= 2 )
+        x *= ( 2 - ( m0 * x ) );
 
     *mm = ~x + 1;
 }
@@ -1351,7 +1474,8 @@ static void mpi_montg_init( t_uint *mm, const mpi *N )
 /*
  * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
  */
-static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T )
+static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm,
+                         const mpi *T )
 {
     size_t i, n, m;
     t_uint u0, u1, *d;
@@ -1376,7 +1500,7 @@ static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mp
         *d++ = u0; d[n + 1] = 0;
     }
 
-    memcpy( A->p, d, (n + 1) * ciL );
+    memcpy( A->p, d, ( n + 1 ) * ciL );
 
     if( mpi_cmp_abs( A, N ) >= 0 )
         mpi_sub_hlp( n, N->p, A->p );
@@ -1423,6 +1547,7 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
      */
     mpi_montg_init( &mm, N );
     mpi_init( &RR ); mpi_init( &T );
+    mpi_init( &Apos );
     memset( W, 0, sizeof( W ) );
 
     i = mpi_msb( E );
@@ -1442,8 +1567,6 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
      * Compensate for negative A (and correct at the end)
      */
     neg = ( A->s == -1 );
-
-    mpi_init( &Apos );
     if( neg )
     {
         MPI_CHK( mpi_copy( &Apos, A ) );
@@ -1470,8 +1593,9 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
      */
     if( mpi_cmp_mpi( A, N ) >= 0 )
-        mpi_mod_mpi( &W[1], A, N );
-    else   mpi_copy( &W[1], A );
+        MPI_CHK( mpi_mod_mpi( &W[1], A, N ) );
+    else
+        MPI_CHK( mpi_copy( &W[1], A ) );
 
     mpi_montmul( &W[1], &RR, N, mm, &T );
 
@@ -1486,7 +1610,7 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
         /*
          * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
          */
-        j =  one << (wsize - 1);
+        j =  one << ( wsize - 1 );
 
         MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
         MPI_CHK( mpi_copy( &W[j], &W[1]    ) );
@@ -1497,7 +1621,7 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
         /*
          * W[i] = W[i - 1] * W[1]
          */
-        for( i = j + 1; i < (one << wsize); i++ )
+        for( i = j + 1; i < ( one << wsize ); i++ )
         {
             MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
             MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
@@ -1549,7 +1673,7 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
         state = 2;
 
         nbits++;
-        wbits |= (ei << (wsize - nbits));
+        wbits |= ( ei << ( wsize - nbits ) );
 
         if( nbits == wsize )
         {
@@ -1579,7 +1703,7 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
 
         wbits <<= 1;
 
-        if( (wbits & (one << wsize)) != 0 )
+        if( ( wbits & ( one << wsize ) ) != 0 )
             mpi_montmul( X, &W[1], N, mm, &T );
     }
 
@@ -1591,17 +1715,17 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
     if( neg )
     {
         X->s = -1;
-        mpi_add_mpi( X, N, X );
+        MPI_CHK( mpi_add_mpi( X, N, X ) );
     }
 
 cleanup:
 
-    for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
+    for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
         mpi_free( &W[i] );
 
     mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
 
-    if( _RR == NULL )
+    if( _RR == NULL || _RR->p == NULL )
         mpi_free( &RR );
 
     return( ret );
@@ -1624,7 +1748,7 @@ int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
     lz = mpi_lsb( &TA );
     lzt = mpi_lsb( &TB );
 
-    if ( lzt < lz )
+    if( lzt < lz )
         lz = lzt;
 
     MPI_CHK( mpi_shift_r( &TA, lz ) );
@@ -1659,16 +1783,25 @@ cleanup:
     return( ret );
 }
 
+/*
+ * Fill X with size bytes of random.
+ *
+ * Use a temporary bytes representation to make sure the result is the same
+ * regardless of the platform endianness (useful when f_rng is actually
+ * deterministic, eg for tests).
+ */
 int mpi_fill_random( mpi *X, size_t size,
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng )
 {
     int ret;
+    unsigned char buf[POLARSSL_MPI_MAX_SIZE];
 
-    MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
-    MPI_CHK( mpi_lset( X, 0 ) );
+    if( size > POLARSSL_MPI_MAX_SIZE )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
 
-    MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) );
+    MPI_CHK( f_rng( p_rng, buf, size ) );
+    MPI_CHK( mpi_read_binary( X, buf, size ) );
 
 cleanup:
     return( ret );
@@ -1797,40 +1930,27 @@ static const int small_prime[] =
 };
 
 /*
- * Miller-Rabin primality test  (HAC 4.24)
+ * Small divisors test (X must be positive)
+ *
+ * Return values:
+ * 0: no small factor (possible prime, more tests needed)
+ * 1: certain prime
+ * POLARSSL_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
+ * other negative: error
  */
-int mpi_is_prime( mpi *X,
-                  int (*f_rng)(void *, unsigned char *, size_t),
-                  void *p_rng )
+static int mpi_check_small_factors( const mpi *X )
 {
-    int ret, xs;
-    size_t i, j, n, s;
-    mpi W, R, T, A, RR;
-
-    if( mpi_cmp_int( X, 0 ) == 0 ||
-        mpi_cmp_int( X, 1 ) == 0 )
-        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
-
-    if( mpi_cmp_int( X, 2 ) == 0 )
-        return( 0 );
-
-    mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
-    mpi_init( &RR );
-
-    xs = X->s; X->s = 1;
+    int ret = 0;
+    size_t i;
+    t_uint r;
 
-    /*
-     * test trivial factors first
-     */
     if( ( X->p[0] & 1 ) == 0 )
         return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
 
     for( i = 0; small_prime[i] > 0; i++ )
     {
-        t_uint r;
-
         if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
-            return( 0 );
+            return( 1 );
 
         MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
 
@@ -1838,6 +1958,24 @@ int mpi_is_prime( mpi *X,
             return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
     }
 
+cleanup:
+    return( ret );
+}
+
+/*
+ * Miller-Rabin pseudo-primality test  (HAC 4.24)
+ */
+static int mpi_miller_rabin( const mpi *X,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng )
+{
+    int ret;
+    size_t i, j, n, s;
+    mpi W, R, T, A, RR;
+
+    mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A );
+    mpi_init( &RR );
+
     /*
      * W = |X| - 1
      * R = W >> lsb( W )
@@ -1905,15 +2043,40 @@ int mpi_is_prime( mpi *X,
     }
 
 cleanup:
-
-    X->s = xs;
-
     mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A );
     mpi_free( &RR );
 
     return( ret );
 }
 
+/*
+ * Pseudo-primality test: small factors, then Miller-Rabin
+ */
+int mpi_is_prime( mpi *X,
+                  int (*f_rng)(void *, unsigned char *, size_t),
+                  void *p_rng )
+{
+    int ret;
+    const mpi XX = { 1, X->n, X->p }; /* Abs(X) */
+
+    if( mpi_cmp_int( &XX, 0 ) == 0 ||
+        mpi_cmp_int( &XX, 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+    if( mpi_cmp_int( &XX, 2 ) == 0 )
+        return( 0 );
+
+    if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
+    {
+        if( ret == 1 )
+            return( 0 );
+
+        return( ret );
+    }
+
+    return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
+}
+
 /*
  * Prime number generation
  */
@@ -1923,6 +2086,7 @@ int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
 {
     int ret;
     size_t k, n;
+    t_uint r;
     mpi Y;
 
     if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS )
@@ -1952,26 +2116,45 @@ int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
     }
     else
     {
-        MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
+        /*
+         * An necessary condition for Y and X = 2Y + 1 to be prime
+         * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
+         * Make sure it is satisfied, while keeping X = 3 mod 4
+         */
+        MPI_CHK( mpi_mod_int( &r, X, 3 ) );
+        if( r == 0 )
+            MPI_CHK( mpi_add_int( X, X, 8 ) );
+        else if( r == 1 )
+            MPI_CHK( mpi_add_int( X, X, 4 ) );
+
+        /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
+        MPI_CHK( mpi_copy( &Y, X ) );
         MPI_CHK( mpi_shift_r( &Y, 1 ) );
 
         while( 1 )
         {
-            if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
+            /*
+             * First, check small factors for X and Y
+             * before doing Miller-Rabin on any of them
+             */
+            if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
+                ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
+                ( ret = mpi_miller_rabin(  X, f_rng, p_rng  ) ) == 0 &&
+                ( ret = mpi_miller_rabin( &Y, f_rng, p_rng  ) ) == 0 )
             {
-                if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
-                    break;
-
-                if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
-                    goto cleanup;
+                break;
             }
 
             if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
                 goto cleanup;
 
-            MPI_CHK( mpi_add_int( &Y, X, 1 ) );
-            MPI_CHK( mpi_add_int(  X, X, 2 ) );
-            MPI_CHK( mpi_shift_r( &Y, 1 ) );
+            /*
+             * Next candidates. We want to preserve Y = (X-1) / 2 and
+             * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
+             * so up Y by 6 and X by 12.
+             */
+            MPI_CHK( mpi_add_int(  X,  X, 12 ) );
+            MPI_CHK( mpi_add_int( &Y, &Y, 6  ) );
         }
     }
 
@@ -2035,18 +2218,19 @@ int mpi_self_test( int verbose )
         "30879B56C61DE584A0F53A2447A51E" ) );
 
     if( verbose != 0 )
-        printf( "  MPI test #1 (mul_mpi): " );
+        polarssl_printf( "  MPI test #1 (mul_mpi): " );
 
     if( mpi_cmp_mpi( &X, &U ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
-        return( 1 );
+        ret = 1;
+        goto cleanup;
     }
 
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
     MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
 
@@ -2059,19 +2243,20 @@ int mpi_self_test( int verbose )
         "9EE50D0657C77F374E903CDFA4C642" ) );
 
     if( verbose != 0 )
-        printf( "  MPI test #2 (div_mpi): " );
+        polarssl_printf( "  MPI test #2 (div_mpi): " );
 
     if( mpi_cmp_mpi( &X, &U ) != 0 ||
         mpi_cmp_mpi( &Y, &V ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
-        return( 1 );
+        ret = 1;
+        goto cleanup;
     }
 
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
     MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
 
@@ -2081,18 +2266,19 @@ int mpi_self_test( int verbose )
         "325D24D6A3C12710F10A09FA08AB87" ) );
 
     if( verbose != 0 )
-        printf( "  MPI test #3 (exp_mod): " );
+        polarssl_printf( "  MPI test #3 (exp_mod): " );
 
     if( mpi_cmp_mpi( &X, &U ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
-        return( 1 );
+        ret = 1;
+        goto cleanup;
     }
 
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
     MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
 
@@ -2102,55 +2288,57 @@ int mpi_self_test( int verbose )
         "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
 
     if( verbose != 0 )
-        printf( "  MPI test #4 (inv_mod): " );
+        polarssl_printf( "  MPI test #4 (inv_mod): " );
 
     if( mpi_cmp_mpi( &X, &U ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
-        return( 1 );
+        ret = 1;
+        goto cleanup;
     }
 
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
     if( verbose != 0 )
-        printf( "  MPI test #5 (simple gcd): " );
+        polarssl_printf( "  MPI test #5 (simple gcd): " );
 
-    for ( i = 0; i < GCD_PAIR_COUNT; i++)
+    for( i = 0; i < GCD_PAIR_COUNT; i++ )
     {
         MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
         MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
 
-           MPI_CHK( mpi_gcd( &A, &X, &Y ) );
+        MPI_CHK( mpi_gcd( &A, &X, &Y ) );
 
-           if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
-           {
-                   if( verbose != 0 )
-                           printf( "failed at %d\n", i );
+        if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed at %d\n", i );
 
-                   return( 1 );
-           }
+            ret = 1;
+            goto cleanup;
+        }
     }
 
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
 cleanup:
 
     if( ret != 0 && verbose != 0 )
-        printf( "Unexpected error, return code = %08X\n", ret );
+        polarssl_printf( "Unexpected error, return code = %08X\n", ret );
 
     mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X );
     mpi_free( &Y ); mpi_free( &U ); mpi_free( &V );
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_BIGNUM_C */
index 910d610d14524c7e9be64bccb82c92e3072fc317..87396dc22aa3cc53f57a1335bbb99e7e7522e59a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Blowfish implementation
  *
- *  Copyright (C) 2012-2013, Brainspark B.V.
+ *  Copyright (C) 2012-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_BLOWFISH_C)
 
 
 #if !defined(POLARSSL_BLOWFISH_ALT)
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -71,7 +80,7 @@ static const uint32_t P[BLOWFISH_ROUNDS + 2] = {
 /* declarations of data at the end of this file */
 static const uint32_t S[4][256];
 
-static uint32_t F(blowfish_context *ctx, uint32_t x) 
+static uint32_t F( blowfish_context *ctx, uint32_t x )
 {
    unsigned short a, b, c, d;
    uint32_t  y;
@@ -87,10 +96,10 @@ static uint32_t F(blowfish_context *ctx, uint32_t x)
    y = y ^ ctx->S[2][c];
    y = y + ctx->S[3][d];
 
-   return y;
+   return( y );
 }
 
-static void blowfish_enc(blowfish_context *ctx, uint32_t *xl, uint32_t *xr) 
+static void blowfish_enc( blowfish_context *ctx, uint32_t *xl, uint32_t *xr )
 {
     uint32_t  Xl, Xr, temp;
     short i;
@@ -98,10 +107,10 @@ static void blowfish_enc(blowfish_context *ctx, uint32_t *xl, uint32_t *xr)
     Xl = *xl;
     Xr = *xr;
 
-    for (i = 0; i < BLOWFISH_ROUNDS; ++i) 
+    for( i = 0; i < BLOWFISH_ROUNDS; ++i )
     {
         Xl = Xl ^ ctx->P[i];
-        Xr = F(ctx, Xl) ^ Xr;
+        Xr = F( ctx, Xl ) ^ Xr;
 
         temp = Xl;
         Xl = Xr;
@@ -119,7 +128,7 @@ static void blowfish_enc(blowfish_context *ctx, uint32_t *xl, uint32_t *xr)
     *xr = Xr;
 }
 
-static void blowfish_dec(blowfish_context *ctx, uint32_t *xl, uint32_t *xr) 
+static void blowfish_dec( blowfish_context *ctx, uint32_t *xl, uint32_t *xr )
 {
     uint32_t  Xl, Xr, temp;
     short i;
@@ -127,10 +136,10 @@ static void blowfish_dec(blowfish_context *ctx, uint32_t *xl, uint32_t *xr)
     Xl = *xl;
     Xr = *xr;
 
-    for (i = BLOWFISH_ROUNDS + 1; i > 1; --i) 
+    for( i = BLOWFISH_ROUNDS + 1; i > 1; --i )
     {
         Xl = Xl ^ ctx->P[i];
-        Xr = F(ctx, Xl) ^ Xr;
+        Xr = F( ctx, Xl ) ^ Xr;
 
         temp = Xl;
         Xl = Xr;
@@ -148,23 +157,37 @@ static void blowfish_dec(blowfish_context *ctx, uint32_t *xl, uint32_t *xr)
     *xr = Xr;
 }
 
+void blowfish_init( blowfish_context *ctx )
+{
+    memset( ctx, 0, sizeof( blowfish_context ) );
+}
+
+void blowfish_free( blowfish_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( blowfish_context ) );
+}
+
 /*
  * Blowfish key schedule
  */
-int blowfish_setkey( blowfish_context *ctx, const unsigned char *key, unsigned int keysize )
+int blowfish_setkey( blowfish_context *ctx, const unsigned char *key,
+                     unsigned int keysize )
 {
     unsigned int i, j, k;
     uint32_t data, datal, datar;
 
     if( keysize < BLOWFISH_MIN_KEY || keysize > BLOWFISH_MAX_KEY ||
-        ( keysize % 8 ) ) 
+        ( keysize % 8 ) )
     {
-        return POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH;
+        return( POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH );
     }
 
     keysize >>= 3;
 
-    for( i = 0; i < 4; i++ ) 
+    for( i = 0; i < 4; i++ )
     {
         for( j = 0; j < 256; j++ )
             ctx->S[i][j] = S[i][j];
@@ -215,16 +238,16 @@ int blowfish_crypt_ecb( blowfish_context *ctx,
 {
     uint32_t X0, X1;
 
-    GET_UINT32_BE( X0, input,  0 ); 
-    GET_UINT32_BE( X1, input,  4 ); 
+    GET_UINT32_BE( X0, input,  0 );
+    GET_UINT32_BE( X1, input,  4 );
 
     if( mode == BLOWFISH_DECRYPT )
     {
-        blowfish_dec(ctx, &X0, &X1);
+        blowfish_dec( ctx, &X0, &X1 );
     }
     else /* BLOWFISH_ENCRYPT */
     {
-        blowfish_enc(ctx, &X0, &X1);
+        blowfish_enc( ctx, &X0, &X1 );
     }
 
     PUT_UINT32_BE( X0, output,  0 );
@@ -313,7 +336,7 @@ int blowfish_crypt_cfb64( blowfish_context *ctx,
             *output++ = (unsigned char)( c ^ iv[n] );
             iv[n] = (unsigned char) c;
 
-            n = (n + 1) % BLOWFISH_BLOCKSIZE;
+            n = ( n + 1 ) % BLOWFISH_BLOCKSIZE;
         }
     }
     else
@@ -325,7 +348,7 @@ int blowfish_crypt_cfb64( blowfish_context *ctx,
 
             iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
 
-            n = (n + 1) % BLOWFISH_BLOCKSIZE;
+            n = ( n + 1 ) % BLOWFISH_BLOCKSIZE;
         }
     }
 
@@ -353,7 +376,8 @@ int blowfish_crypt_ctr( blowfish_context *ctx,
     while( length-- )
     {
         if( n == 0 ) {
-            blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, nonce_counter, stream_block );
+            blowfish_crypt_ecb( ctx, BLOWFISH_ENCRYPT, nonce_counter,
+                                stream_block );
 
             for( i = BLOWFISH_BLOCKSIZE; i > 0; i-- )
                 if( ++nonce_counter[i - 1] != 0 )
@@ -362,7 +386,7 @@ int blowfish_crypt_ctr( blowfish_context *ctx,
         c = *input++;
         *output++ = (unsigned char)( c ^ stream_block[n] );
 
-        n = (n + 1) % BLOWFISH_BLOCKSIZE;
+        n = ( n + 1 ) % BLOWFISH_BLOCKSIZE;
     }
 
     *nc_off = n;
index 2366caed6c548cac55be55bf7007a94496b147f9..a4968f411e075d63342dabb615c7f1a7e39a5e44 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Camellia implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_CAMELLIA_C)
 
 #include "polarssl/camellia.h"
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
 #if !defined(POLARSSL_CAMELLIA_ALT)
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -97,86 +112,86 @@ static const unsigned char FSb[256] =
 #define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
 #define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
 
-#else
+#else /* POLARSSL_CAMELLIA_SMALL_MEMORY */
 
 static const unsigned char FSb[256] =
 {
   112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,
-    35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,
   134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,
   166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,
   139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,
   223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,
-    20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,
   254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,
   170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,
-    16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,
   135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,
-    82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,
   233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,
   120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,
   114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,
   64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158
+ 112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,
+  35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,
+ 134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,
+ 166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,
+ 139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,
+ 223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,
+  20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,
+ 254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,
+ 170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,
+  16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,
+ 135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,
+  82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,
+ 233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,
+ 120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,
+ 114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,
+ 64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158
 };
 
 static const unsigned char FSb2[256] =
 {
   224,   5,  88, 217, 103,  78, 129, 203, 201,  11, 174, 106, 213,  24,  93, 130,
-    70, 223, 214,  39, 138,  50,  75,  66, 219,  28, 158, 156,  58, 202,  37, 123,
-    13, 113,  95,  31, 248, 215,  62, 157, 124,  96, 185, 190, 188, 139,  22,  52,
-    77, 195, 114, 149, 171, 142, 186, 122, 179,   2, 180, 173, 162, 172, 216, 154,
-    23,  26,  53, 204, 247, 153,  97,  90, 232,  36,  86,  64, 225,  99,   9,  51,
   191, 152, 151, 133, 104, 252, 236,  10, 218, 111,  83,  98, 163,  46,   8, 175,
-    40, 176, 116, 194, 189,  54,  34,  56, 100,  30,  57,  44, 166,  48, 229,  68,
   253, 136, 159, 101, 135, 107, 244,  35,  72,  16, 209,  81, 192, 249, 210, 160,
-    85, 161,  65, 250,  67,  19, 196,  47, 168, 182,  60,  43, 193, 255, 200, 165,
-    32, 137,   0, 144,  71, 239, 234, 183,  21,   6, 205, 181,  18, 126, 187,  41,
-    15, 184,   7,   4, 155, 148,  33, 102, 230, 206, 237, 231,  59, 254, 127, 197,
   164,  55, 177,  76, 145, 110, 141, 118,   3,  45, 222, 150,  38, 125, 198,  92,
   211, 242,  79,  25,  63, 220, 121,  29,  82, 235, 243, 109,  94, 251, 105, 178,
   240,  49,  12, 212, 207, 140, 226, 117, 169,  74,  87, 132,  17,  69,  27, 245,
   228,  14, 115, 170, 241, 221,  89,  20, 108, 146,  84, 208, 120, 112, 227,  73,
   128,  80, 167, 246, 119, 147, 134, 131,  42, 199,  91, 233, 238, 143,   1,  61
+ 224,   5,  88, 217, 103,  78, 129, 203, 201,  11, 174, 106, 213,  24,  93, 130,
+  70, 223, 214,  39, 138,  50,  75,  66, 219,  28, 158, 156,  58, 202,  37, 123,
+  13, 113,  95,  31, 248, 215,  62, 157, 124,  96, 185, 190, 188, 139,  22,  52,
+  77, 195, 114, 149, 171, 142, 186, 122, 179,   2, 180, 173, 162, 172, 216, 154,
+  23,  26,  53, 204, 247, 153,  97,  90, 232,  36,  86,  64, 225,  99,   9,  51,
+ 191, 152, 151, 133, 104, 252, 236,  10, 218, 111,  83,  98, 163,  46,   8, 175,
+  40, 176, 116, 194, 189,  54,  34,  56, 100,  30,  57,  44, 166,  48, 229,  68,
+ 253, 136, 159, 101, 135, 107, 244,  35,  72,  16, 209,  81, 192, 249, 210, 160,
+  85, 161,  65, 250,  67,  19, 196,  47, 168, 182,  60,  43, 193, 255, 200, 165,
+  32, 137,   0, 144,  71, 239, 234, 183,  21,   6, 205, 181,  18, 126, 187,  41,
+  15, 184,   7,   4, 155, 148,  33, 102, 230, 206, 237, 231,  59, 254, 127, 197,
+ 164,  55, 177,  76, 145, 110, 141, 118,   3,  45, 222, 150,  38, 125, 198,  92,
+ 211, 242,  79,  25,  63, 220, 121,  29,  82, 235, 243, 109,  94, 251, 105, 178,
+ 240,  49,  12, 212, 207, 140, 226, 117, 169,  74,  87, 132,  17,  69,  27, 245,
+ 228,  14, 115, 170, 241, 221,  89,  20, 108, 146,  84, 208, 120, 112, 227,  73,
+ 128,  80, 167, 246, 119, 147, 134, 131,  42, 199,  91, 233, 238, 143,   1,  61
 };
 
 static const unsigned char FSb3[256] =
 {
-    56,  65,  22, 118, 217, 147,  96, 242, 114, 194, 171, 154, 117,   6,  87, 160,
   145, 247, 181, 201, 162, 140, 210, 144, 246,   7, 167,  39, 142, 178,  73, 222,
-    67,  92, 215, 199,  62, 245, 143, 103,  31,  24, 110, 175,  47, 226, 133,  13,
-    83, 240, 156, 101, 234, 163, 174, 158, 236, 128,  45, 107, 168,  43,  54, 166,
   197, 134,  77,  51, 253, 102,  88, 150,  58,   9, 149,  16, 120, 216,  66, 204,
   239,  38, 229,  97,  26,  63,  59, 130, 182, 219, 212, 152, 232, 139,   2, 235,
-    10,  44,  29, 176, 111, 141, 136,  14,  25, 135,  78,  11, 169,  12, 121,  17,
   127,  34, 231,  89, 225, 218,  61, 200,  18,   4, 116,  84,  48, 126, 180,  40,
-    85, 104,  80, 190, 208, 196,  49, 203,  42, 173,  15, 202, 112, 255,  50, 105,
-    8,  98,   0,  36, 209, 251, 186, 237,  69, 129, 115, 109, 132, 159, 238,  74,
   195,  46, 193,   1, 230,  37,  72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
-    41, 205, 108,  19, 100, 155,  99, 157, 192,  75, 183, 165, 137,  95, 177,  23,
   244, 188, 211,  70, 207,  55,  94,  71, 148, 250, 252,  91, 151, 254,  90, 172,
-    60,  76,   3,  53, 243,  35, 184,  93, 106, 146, 213,  33,  68,  81, 198, 125,
-    57, 131, 220, 170, 124, 119,  86,   5,  27, 164,  21,  52,  30,  28, 248,  82,
-    32,  20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227,  64,  79
+  56,  65,  22, 118, 217, 147,  96, 242, 114, 194, 171, 154, 117,   6,  87, 160,
+ 145, 247, 181, 201, 162, 140, 210, 144, 246,   7, 167,  39, 142, 178,  73, 222,
+  67,  92, 215, 199,  62, 245, 143, 103,  31,  24, 110, 175,  47, 226, 133,  13,
+  83, 240, 156, 101, 234, 163, 174, 158, 236, 128,  45, 107, 168,  43,  54, 166,
+ 197, 134,  77,  51, 253, 102,  88, 150,  58,   9, 149,  16, 120, 216,  66, 204,
+ 239,  38, 229,  97,  26,  63,  59, 130, 182, 219, 212, 152, 232, 139,   2, 235,
+  10,  44,  29, 176, 111, 141, 136,  14,  25, 135,  78,  11, 169,  12, 121,  17,
+ 127,  34, 231,  89, 225, 218,  61, 200,  18,   4, 116,  84,  48, 126, 180,  40,
+  85, 104,  80, 190, 208, 196,  49, 203,  42, 173,  15, 202, 112, 255,  50, 105,
+   8,  98,   0,  36, 209, 251, 186, 237,  69, 129, 115, 109, 132, 159, 238,  74,
+ 195,  46, 193,   1, 230,  37,  72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
+  41, 205, 108,  19, 100, 155,  99, 157, 192,  75, 183, 165, 137,  95, 177,  23,
+ 244, 188, 211,  70, 207,  55,  94,  71, 148, 250, 252,  91, 151, 254,  90, 172,
+  60,  76,   3,  53, 243,  35, 184,  93, 106, 146, 213,  33,  68,  81, 198, 125,
+  57, 131, 220, 170, 124, 119,  86,   5,  27, 164,  21,  52,  30,  28, 248,  82,
+  32,  20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227,  64,  79
 };
 
 static const unsigned char FSb4[256] =
 {
   112,  44, 179, 192, 228,  87, 234, 174,  35, 107,  69, 165, 237,  79,  29, 146,
   134, 175, 124,  31,  62, 220,  94,  11, 166,  57, 213,  93, 217,  90,  81, 108,
   139, 154, 251, 176, 116,  43, 240, 132, 223, 203,  52, 118, 109, 169, 209,   4,
-    20,  58, 222,  17,  50, 156,  83, 242, 254, 207, 195, 122,  36, 232,  96, 105,
   170, 160, 161,  98,  84,  30, 224, 100,  16,   0, 163, 117, 138, 230,   9, 221,
   135, 131, 205, 144, 115, 246, 157, 191,  82, 216, 200, 198, 129, 111,  19,  99,
   233, 167, 159, 188,  41, 249,  47, 180, 120,   6, 231, 113, 212, 171, 136, 141,
   114, 185, 248, 172,  54,  42,  60, 241,  64, 211, 187,  67,  21, 173, 119, 128,
   130, 236,  39, 229, 133,  53,  12,  65, 239, 147,  25,  33,  14,  78, 101, 189,
   184, 143, 235, 206,  48,  95, 197,  26, 225, 202,  71,  61,   1, 214,  86,  77,
-    13, 102, 204,  45,  18,  32, 177, 153,  76, 194, 126,   5, 183,  49,  23, 215,
-    88,  97,  27,  28,  15,  22,  24,  34,  68, 178, 181, 145,   8, 168, 252,  80,
   208, 125, 137, 151,  91, 149, 255, 210, 196,  72, 247, 219,   3, 218,  63, 148,
-    92,   2,  74,  51, 103, 243, 127, 226, 155,  38,  55,  59, 150,  75, 190,  46,
   121, 140, 110, 142, 245, 182, 253,  89, 152, 106,  70, 186,  37,  66, 162, 250,
-    7,  85, 238,  10,  73, 104,  56, 164,  40, 123, 201, 193, 227, 244, 199, 158
+ 112,  44, 179, 192, 228,  87, 234, 174,  35, 107,  69, 165, 237,  79,  29, 146,
+ 134, 175, 124,  31,  62, 220,  94,  11, 166,  57, 213,  93, 217,  90,  81, 108,
+ 139, 154, 251, 176, 116,  43, 240, 132, 223, 203,  52, 118, 109, 169, 209,   4,
+  20,  58, 222,  17,  50, 156,  83, 242, 254, 207, 195, 122,  36, 232,  96, 105,
+ 170, 160, 161,  98,  84,  30, 224, 100,  16,   0, 163, 117, 138, 230,   9, 221,
+ 135, 131, 205, 144, 115, 246, 157, 191,  82, 216, 200, 198, 129, 111,  19,  99,
+ 233, 167, 159, 188,  41, 249,  47, 180, 120,   6, 231, 113, 212, 171, 136, 141,
+ 114, 185, 248, 172,  54,  42,  60, 241,  64, 211, 187,  67,  21, 173, 119, 128,
+ 130, 236,  39, 229, 133,  53,  12,  65, 239, 147,  25,  33,  14,  78, 101, 189,
+ 184, 143, 235, 206,  48,  95, 197,  26, 225, 202,  71,  61,   1, 214,  86,  77,
+  13, 102, 204,  45,  18,  32, 177, 153,  76, 194, 126,   5, 183,  49,  23, 215,
+  88,  97,  27,  28,  15,  22,  24,  34,  68, 178, 181, 145,   8, 168, 252,  80,
+ 208, 125, 137, 151,  91, 149, 255, 210, 196,  72, 247, 219,   3, 218,  63, 148,
+  92,   2,  74,  51, 103, 243, 127, 226, 155,  38,  55,  59, 150,  75, 190,  46,
+ 121, 140, 110, 142, 245, 182, 253,  89, 152, 106,  70, 186,  37,  66, 162, 250,
+  7,  85, 238,  10,  73, 104,  56, 164,  40, 123, 201, 193, 227, 244, 199, 158
 };
 
 #define SBOX1(n) FSb[(n)]
@@ -184,7 +199,7 @@ static const unsigned char FSb4[256] =
 #define SBOX3(n) FSb3[(n)]
 #define SBOX4(n) FSb4[(n)]
 
-#endif
+#endif /* POLARSSL_CAMELLIA_SMALL_MEMORY */
 
 static const unsigned char shifts[2][4][4] =
 {
@@ -258,13 +273,13 @@ static const signed char transposes[2][20] =
     (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR);   \
     (XL) = ((XR) | (KR)) ^ (XL);                                    \
 }
-    
+
 #define FLInv(YL, YR, KL, KR)                                       \
 {                                                                   \
     (YL) = ((YR) | (KR)) ^ (YL);                                    \
     (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR);   \
 }
-    
+
 #define SHIFT_AND_PLACE(INDEX, OFFSET)                      \
 {                                                           \
     TK[0] = KC[(OFFSET) * 4 + 0];                           \
@@ -272,17 +287,18 @@ static const signed char transposes[2][20] =
     TK[2] = KC[(OFFSET) * 4 + 2];                           \
     TK[3] = KC[(OFFSET) * 4 + 3];                           \
                                                             \
-    for ( i = 1; i <= 4; i++ )                              \
-        if (shifts[(INDEX)][(OFFSET)][i -1])                \
-            ROTL(TK + i * 4, TK, (15 * i) % 32);            \
+    for( i = 1; i <= 4; i++ )                               \
+        if( shifts[(INDEX)][(OFFSET)][i -1] )               \
+            ROTL(TK + i * 4, TK, ( 15 * i ) % 32);          \
                                                             \
-    for ( i = 0; i < 20; i++ )                              \
-        if (indexes[(INDEX)][(OFFSET)][i] != -1) {          \
-        RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ];        \
-    }                                                       \
+    for( i = 0; i < 20; i++ )                               \
+        if( indexes[(INDEX)][(OFFSET)][i] != -1 ) {         \
+            RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ];    \
+        }                                                   \
 }
 
-static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2])
+static void camellia_feistel( const uint32_t x[2], const uint32_t k[2],
+                              uint32_t z[2])
 {
     uint32_t I0, I1;
     I0 = x[0] ^ k[0];
@@ -306,10 +322,24 @@ static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t
     z[1] ^= I0;
 }
 
+void camellia_init( camellia_context *ctx )
+{
+    memset( ctx, 0, sizeof( camellia_context ) );
+}
+
+void camellia_free( camellia_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( camellia_context ) );
+}
+
 /*
  * Camellia key schedule (encryption)
  */
-int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
+int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key,
+                         unsigned int keysize )
 {
     int idx;
     size_t i;
@@ -321,8 +351,8 @@ int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsign
 
     RK = ctx->rk;
 
-    memset(t, 0, 64);
-    memset(RK, 0, sizeof(ctx->rk));
+    memset( t, 0, 64 );
+    memset( RK, 0, sizeof(ctx->rk) );
 
     switch( keysize )
     {
@@ -332,77 +362,77 @@ int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsign
         default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
     }
 
-    for( i = 0; i < keysize / 8; ++i)
+    for( i = 0; i < keysize / 8; ++i )
         t[i] = key[i];
 
-    if (keysize == 192) {
-        for (i = 0; i < 8; i++)
+    if( keysize == 192 ) {
+        for( i = 0; i < 8; i++ )
             t[24 + i] = ~t[16 + i];
     }
 
     /*
      * Prepare SIGMA values
      */
-    for (i = 0; i < 6; i++) {
-        GET_UINT32_BE(SIGMA[i][0], SIGMA_CHARS[i], 0);
-        GET_UINT32_BE(SIGMA[i][1], SIGMA_CHARS[i], 4);
+    for( i = 0; i < 6; i++ ) {
+        GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 );
+        GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 );
     }
 
     /*
      * Key storage in KC
      * Order: KL, KR, KA, KB
      */
-    memset(KC, 0, sizeof(KC));
+    memset( KC, 0, sizeof(KC) );
 
     /* Store KL, KR */
-    for (i = 0; i < 8; i++)
-        GET_UINT32_BE(KC[i], t, i * 4);
+    for( i = 0; i < 8; i++ )
+        GET_UINT32_BE( KC[i], t, i * 4 );
 
     /* Generate KA */
-    for( i = 0; i < 4; ++i)
+    for( i = 0; i < 4; ++i )
         KC[8 + i] = KC[i] ^ KC[4 + i];
 
-    camellia_feistel(KC + 8, SIGMA[0], KC + 10);
-    camellia_feistel(KC + 10, SIGMA[1], KC + 8);
+    camellia_feistel( KC + 8, SIGMA[0], KC + 10 );
+    camellia_feistel( KC + 10, SIGMA[1], KC + 8 );
 
-    for( i = 0; i < 4; ++i)
+    for( i = 0; i < 4; ++i )
         KC[8 + i] ^= KC[i];
 
-    camellia_feistel(KC + 8, SIGMA[2], KC + 10);
-    camellia_feistel(KC + 10, SIGMA[3], KC + 8);
+    camellia_feistel( KC + 8, SIGMA[2], KC + 10 );
+    camellia_feistel( KC + 10, SIGMA[3], KC + 8 );
 
-    if (keysize > 128) {
+    if( keysize > 128 ) {
         /* Generate KB */
-        for( i = 0; i < 4; ++i)
+        for( i = 0; i < 4; ++i )
             KC[12 + i] = KC[4 + i] ^ KC[8 + i];
 
-        camellia_feistel(KC + 12, SIGMA[4], KC + 14);
-        camellia_feistel(KC + 14, SIGMA[5], KC + 12);
+        camellia_feistel( KC + 12, SIGMA[4], KC + 14 );
+        camellia_feistel( KC + 14, SIGMA[5], KC + 12 );
     }
 
     /*
      * Generating subkeys
-     */ 
+     */
 
     /* Manipulating KL */
-    SHIFT_AND_PLACE(idx, 0);
+    SHIFT_AND_PLACE( idx, 0 );
 
     /* Manipulating KR */
-    if (keysize > 128) {
-        SHIFT_AND_PLACE(idx, 1);
+    if( keysize > 128 ) {
+        SHIFT_AND_PLACE( idx, 1 );
     }
 
     /* Manipulating KA */
-    SHIFT_AND_PLACE(idx, 2);
+    SHIFT_AND_PLACE( idx, 2 );
 
     /* Manipulating KB */
-    if (keysize > 128) {
-        SHIFT_AND_PLACE(idx, 3);
+    if( keysize > 128 ) {
+        SHIFT_AND_PLACE( idx, 3 );
     }
 
     /* Do transpositions */
-    for ( i = 0; i < 20; i++ ) {
-        if (transposes[idx][i] != -1) {
+    for( i = 0; i < 20; i++ ) {
+        if( transposes[idx][i] != -1 ) {
             RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
         }
     }
@@ -413,29 +443,25 @@ int camellia_setkey_enc( camellia_context *ctx, const unsigned char *key, unsign
 /*
  * Camellia key schedule (decryption)
  */
-int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsigned int keysize )
+int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key,
+                         unsigned int keysize )
 {
-    int idx;
+    int idx, ret;
     size_t i;
     camellia_context cty;
     uint32_t *RK;
     uint32_t *SK;
-    int ret;
 
-    switch( keysize )
-    {
-        case 128: ctx->nr = 3; idx = 0; break;
-        case 192:
-        case 256: ctx->nr = 4; idx = 1; break;
-        default : return( POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH );
-    }
+    camellia_init( &cty );
 
-    RK = ctx->rk;
+    /* Also checks keysize */
+    if( ( ret = camellia_setkey_enc( &cty, key, keysize ) ) )
+        goto exit;
 
-    ret = camellia_setkey_enc(&cty, key, keysize);
-    if( ret != 0 )
-        return( ret );
+    ctx->nr = cty.nr;
+    idx = ( ctx->nr == 4 );
 
+    RK = ctx->rk;
     SK = cty.rk + 24 * 2 + 8 * idx * 2;
 
     *RK++ = *SK++;
@@ -443,7 +469,7 @@ int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsign
     *RK++ = *SK++;
     *RK++ = *SK++;
 
-    for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4)
+    for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 )
     {
         *RK++ = *SK++;
         *RK++ = *SK++;
@@ -456,9 +482,10 @@ int camellia_setkey_dec( camellia_context *ctx, const unsigned char *key, unsign
     *RK++ = *SK++;
     *RK++ = *SK++;
 
-    memset( &cty, 0, sizeof( camellia_context ) );
+exit:
+    camellia_free( &cty );
 
-    return( 0 );
+    return( ret );
 }
 
 /*
@@ -487,22 +514,22 @@ int camellia_crypt_ecb( camellia_context *ctx,
     X[2] ^= *RK++;
     X[3] ^= *RK++;
 
-    while (NR) {
+    while( NR ) {
         --NR;
-        camellia_feistel(X, RK, X + 2);
+        camellia_feistel( X, RK, X + 2 );
         RK += 2;
-        camellia_feistel(X + 2, RK, X);
+        camellia_feistel( X + 2, RK, X );
         RK += 2;
-        camellia_feistel(X, RK, X + 2);
+        camellia_feistel( X, RK, X + 2 );
         RK += 2;
-        camellia_feistel(X + 2, RK, X);
+        camellia_feistel( X + 2, RK, X );
         RK += 2;
-        camellia_feistel(X, RK, X + 2);
+        camellia_feistel( X, RK, X + 2 );
         RK += 2;
-        camellia_feistel(X + 2, RK, X);
+        camellia_feistel( X + 2, RK, X );
         RK += 2;
 
-        if (NR) {
+        if( NR ) {
             FL(X[0], X[1], RK[0], RK[1]);
             RK += 2;
             FLInv(X[2], X[3], RK[0], RK[1]);
@@ -603,7 +630,7 @@ int camellia_crypt_cfb128( camellia_context *ctx,
             *output++ = (unsigned char)( c ^ iv[n] );
             iv[n] = (unsigned char) c;
 
-            n = (n + 1) & 0x0F;
+            n = ( n + 1 ) & 0x0F;
         }
     }
     else
@@ -615,7 +642,7 @@ int camellia_crypt_cfb128( camellia_context *ctx,
 
             iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
 
-            n = (n + 1) & 0x0F;
+            n = ( n + 1 ) & 0x0F;
         }
     }
 
@@ -643,7 +670,8 @@ int camellia_crypt_ctr( camellia_context *ctx,
     while( length-- )
     {
         if( n == 0 ) {
-            camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter, stream_block );
+            camellia_crypt_ecb( ctx, CAMELLIA_ENCRYPT, nonce_counter,
+                                stream_block );
 
             for( i = 16; i > 0; i-- )
                 if( ++nonce_counter[i - 1] != 0 )
@@ -652,7 +680,7 @@ int camellia_crypt_ctr( camellia_context *ctx,
         c = *input++;
         *output++ = (unsigned char)( c ^ stream_block[n] );
 
-        n = (n + 1) & 0x0F;
+        n = ( n + 1 ) & 0x0F;
     }
 
     *nc_off = n;
@@ -681,14 +709,14 @@ static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
     {
         { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
           0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
-        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
     },
     {
         { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
           0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
           0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
-        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
     },
@@ -697,7 +725,7 @@ static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
           0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
           0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
           0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
-        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
@@ -708,7 +736,7 @@ static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
 {
     { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
       0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
-    { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
+    { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
 };
 
@@ -884,44 +912,44 @@ int camellia_self_test( int verbose )
 
     memset( key, 0, 32 );
 
-    for (j = 0; j < 6; j++) {
+    for( j = 0; j < 6; j++ ) {
         u = j >> 1;
     v = j & 1;
 
     if( verbose != 0 )
-        printf( "  CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
-                (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
+        polarssl_printf( "  CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
+                         (v == CAMELLIA_DECRYPT) ? "dec" : "enc");
 
-    for (i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
-        memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u);
+    fori = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
+        memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u );
 
-        if (v == CAMELLIA_DECRYPT) {
-            camellia_setkey_dec(&ctx, key, 128 + u * 64);
-            memcpy(src, camellia_test_ecb_cipher[u][i], 16);
-            memcpy(dst, camellia_test_ecb_plain[i], 16);
+        if( v == CAMELLIA_DECRYPT ) {
+            camellia_setkey_dec( &ctx, key, 128 + u * 64 );
+            memcpy( src, camellia_test_ecb_cipher[u][i], 16 );
+            memcpy( dst, camellia_test_ecb_plain[i], 16 );
         } else { /* CAMELLIA_ENCRYPT */
-            camellia_setkey_enc(&ctx, key, 128 + u * 64);
-            memcpy(src, camellia_test_ecb_plain[i], 16);
-            memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
+            camellia_setkey_enc( &ctx, key, 128 + u * 64 );
+            memcpy( src, camellia_test_ecb_plain[i], 16 );
+            memcpy( dst, camellia_test_ecb_cipher[u][i], 16 );
         }
 
-        camellia_crypt_ecb(&ctx, v, src, buf);
+        camellia_crypt_ecb( &ctx, v, src, buf );
 
         if( memcmp( buf, dst, 16 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
             return( 1 );
         }
     }
 
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
 #if defined(POLARSSL_CIPHER_MODE_CBC)
     /*
@@ -933,49 +961,49 @@ int camellia_self_test( int verbose )
         v = j  & 1;
 
         if( verbose != 0 )
-            printf( "  CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
-                    ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+            polarssl_printf( "  CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
+                             ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
 
-    memcpy( src, camellia_test_cbc_iv, 16);
-    memcpy( dst, camellia_test_cbc_iv, 16);
-    memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u);
+    memcpy( src, camellia_test_cbc_iv, 16 );
+    memcpy( dst, camellia_test_cbc_iv, 16 );
+    memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u );
 
-    if (v == CAMELLIA_DECRYPT) {
-        camellia_setkey_dec(&ctx, key, 128 + u * 64);
+    if( v == CAMELLIA_DECRYPT ) {
+        camellia_setkey_dec( &ctx, key, 128 + u * 64 );
     } else {
-        camellia_setkey_enc(&ctx, key, 128 + u * 64);
+        camellia_setkey_enc( &ctx, key, 128 + u * 64 );
     }
 
-    for (i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
+    fori = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
 
-        if (v == CAMELLIA_DECRYPT) {
+        if( v == CAMELLIA_DECRYPT ) {
             memcpy( iv , src, 16 );
-            memcpy(src, camellia_test_cbc_cipher[u][i], 16);
-            memcpy(dst, camellia_test_cbc_plain[i], 16);
+            memcpy( src, camellia_test_cbc_cipher[u][i], 16 );
+            memcpy( dst, camellia_test_cbc_plain[i], 16 );
         } else { /* CAMELLIA_ENCRYPT */
             memcpy( iv , dst, 16 );
-            memcpy(src, camellia_test_cbc_plain[i], 16);
-            memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
+            memcpy( src, camellia_test_cbc_plain[i], 16 );
+            memcpy( dst, camellia_test_cbc_cipher[u][i], 16 );
         }
 
-        camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
+        camellia_crypt_cbc( &ctx, v, 16, iv, src, buf );
 
         if( memcmp( buf, dst, 16 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
             return( 1 );
         }
     }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
 #if defined(POLARSSL_CIPHER_MODE_CTR)
     /*
@@ -987,8 +1015,8 @@ int camellia_self_test( int verbose )
         v = i  & 1;
 
         if( verbose != 0 )
-            printf( "  CAMELLIA-CTR-128 (%s): ",
-                    ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+            polarssl_printf( "  CAMELLIA-CTR-128 (%s): ",
+                             ( v == CAMELLIA_DECRYPT ) ? "dec" : "enc" );
 
         memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
         memcpy( key, camellia_test_ctr_key[u], 16 );
@@ -1001,12 +1029,13 @@ int camellia_self_test( int verbose )
             len = camellia_test_ctr_len[u];
             memcpy( buf, camellia_test_ctr_ct[u], len );
 
-            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                                buf, buf );
 
             if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
                 return( 1 );
             }
@@ -1016,28 +1045,29 @@ int camellia_self_test( int verbose )
             len = camellia_test_ctr_len[u];
             memcpy( buf, camellia_test_ctr_pt[u], len );
 
-            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, buf, buf );
+            camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                                buf, buf );
 
             if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
                 return( 1 );
             }
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 
-    return ( 0 );
+    return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_CAMELLIA_C */
diff --git a/pdns/ext/polarssl/library/ccm.c b/pdns/ext/polarssl/library/ccm.c
new file mode 100644 (file)
index 0000000..72d766b
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ *  NIST SP800-38C compliant CCM implementation
+ *
+ *  Copyright (C) 2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Definition of CCM:
+ * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+ * RFC 3610 "Counter with CBC-MAC (CCM)"
+ *
+ * Related:
+ * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_CCM_C)
+
+#include "polarssl/ccm.h"
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#define CCM_ENCRYPT 0
+#define CCM_DECRYPT 1
+
+/*
+ * Initialize context
+ */
+int ccm_init( ccm_context *ctx, cipher_id_t cipher,
+              const unsigned char *key, unsigned int keysize )
+{
+    int ret;
+    const cipher_info_t *cipher_info;
+
+    memset( ctx, 0, sizeof( ccm_context ) );
+
+    cipher_init( &ctx->cipher_ctx );
+
+    cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
+    if( cipher_info == NULL )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    if( cipher_info->block_size != 16 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
+        return( ret );
+
+    if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
+                               POLARSSL_ENCRYPT ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Free context
+ */
+void ccm_free( ccm_context *ctx )
+{
+    cipher_free( &ctx->cipher_ctx );
+    polarssl_zeroize( ctx, sizeof( ccm_context ) );
+}
+
+/*
+ * Macros for common operations.
+ * Results in smaller compiled code than static inline functions.
+ */
+
+/*
+ * Update the CBC-MAC state in y using a block in b
+ * (Always using b as the source helps the compiler optimise a bit better.)
+ */
+#define UPDATE_CBC_MAC                                                      \
+    for( i = 0; i < 16; i++ )                                               \
+        y[i] ^= b[i];                                                       \
+                                                                            \
+    if( ( ret = cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
+        return( ret );
+
+/*
+ * Encrypt or decrypt a partial block with CTR
+ * Warning: using b for temporary storage! src and dst must not be b!
+ * This avoids allocating one more 16 bytes buffer while allowing src == dst.
+ */
+#define CTR_CRYPT( dst, src, len  )                                            \
+    if( ( ret = cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 )  \
+        return( ret );                                                         \
+                                                                               \
+    for( i = 0; i < len; i++ )                                                 \
+        dst[i] = src[i] ^ b[i];
+
+/*
+ * Authenticated encryption or decryption
+ */
+static int ccm_auth_crypt( ccm_context *ctx, int mode, size_t length,
+                           const unsigned char *iv, size_t iv_len,
+                           const unsigned char *add, size_t add_len,
+                           const unsigned char *input, unsigned char *output,
+                           unsigned char *tag, size_t tag_len )
+{
+    int ret;
+    unsigned char i;
+    unsigned char q = 16 - 1 - iv_len;
+    size_t len_left, olen;
+    unsigned char b[16];
+    unsigned char y[16];
+    unsigned char ctr[16];
+    const unsigned char *src;
+    unsigned char *dst;
+
+    /*
+     * Check length requirements: SP800-38C A.1
+     * Additional requirement: a < 2^16 - 2^8 to simplify the code.
+     * 'length' checked later (when writing it to the first block)
+     */
+    if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    /* Also implies q is within bounds */
+    if( iv_len < 7 || iv_len > 13 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    if( add_len > 0xFF00 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+    /*
+     * First block B_0:
+     * 0        .. 0        flags
+     * 1        .. iv_len   nonce (aka iv)
+     * iv_len+1 .. 15       length
+     *
+     * With flags as (bits):
+     * 7        0
+     * 6        add present?
+     * 5 .. 3   (t - 2) / 2
+     * 2 .. 0   q - 1
+     */
+    b[0] = 0;
+    b[0] |= ( add_len > 0 ) << 6;
+    b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
+    b[0] |= q - 1;
+
+    memcpy( b + 1, iv, iv_len );
+
+    for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
+        b[15-i] = (unsigned char)( len_left & 0xFF );
+
+    if( len_left > 0 )
+        return( POLARSSL_ERR_CCM_BAD_INPUT );
+
+
+    /* Start CBC-MAC with first block */
+    memset( y, 0, 16 );
+    UPDATE_CBC_MAC;
+
+    /*
+     * If there is additional data, update CBC-MAC with
+     * add_len, add, 0 (padding to a block boundary)
+     */
+    if( add_len > 0 )
+    {
+        size_t use_len;
+        len_left = add_len;
+        src = add;
+
+        memset( b, 0, 16 );
+        b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
+        b[1] = (unsigned char)( ( add_len      ) & 0xFF );
+
+        use_len = len_left < 16 - 2 ? len_left : 16 - 2;
+        memcpy( b + 2, src, use_len );
+        len_left -= use_len;
+        src += use_len;
+
+        UPDATE_CBC_MAC;
+
+        while( len_left > 0 )
+        {
+            use_len = len_left > 16 ? 16 : len_left;
+
+            memset( b, 0, 16 );
+            memcpy( b, src, use_len );
+            UPDATE_CBC_MAC;
+
+            len_left -= use_len;
+            src += use_len;
+        }
+    }
+
+    /*
+     * Prepare counter block for encryption:
+     * 0        .. 0        flags
+     * 1        .. iv_len   nonce (aka iv)
+     * iv_len+1 .. 15       counter (initially 1)
+     *
+     * With flags as (bits):
+     * 7 .. 3   0
+     * 2 .. 0   q - 1
+     */
+    ctr[0] = q - 1;
+    memcpy( ctr + 1, iv, iv_len );
+    memset( ctr + 1 + iv_len, 0, q );
+    ctr[15] = 1;
+
+    /*
+     * Authenticate and {en,de}crypt the message.
+     *
+     * The only difference between encryption and decryption is
+     * the respective order of authentication and {en,de}cryption.
+     */
+    len_left = length;
+    src = input;
+    dst = output;
+
+    while( len_left > 0 )
+    {
+        unsigned char use_len = len_left > 16 ? 16 : len_left;
+
+        if( mode == CCM_ENCRYPT )
+        {
+            memset( b, 0, 16 );
+            memcpy( b, src, use_len );
+            UPDATE_CBC_MAC;
+        }
+
+        CTR_CRYPT( dst, src, use_len );
+
+        if( mode == CCM_DECRYPT )
+        {
+            memset( b, 0, 16 );
+            memcpy( b, dst, use_len );
+            UPDATE_CBC_MAC;
+        }
+
+        dst += use_len;
+        src += use_len;
+        len_left -= use_len;
+
+        /*
+         * Increment counter.
+         * No need to check for overflow thanks to the length check above.
+         */
+        for( i = 0; i < q; i++ )
+            if( ++ctr[15-i] != 0 )
+                break;
+    }
+
+    /*
+     * Authentication: reset counter and crypt/mask internal tag
+     */
+    for( i = 0; i < q; i++ )
+        ctr[15-i] = 0;
+
+    CTR_CRYPT( y, y, 16 );
+    memcpy( tag, y, tag_len );
+
+    return( 0 );
+}
+
+/*
+ * Authenticated encryption
+ */
+int ccm_encrypt_and_tag( ccm_context *ctx, size_t length,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output,
+                         unsigned char *tag, size_t tag_len )
+{
+    return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
+                            add, add_len, input, output, tag, tag_len ) );
+}
+
+/*
+ * Authenticated decryption
+ */
+int ccm_auth_decrypt( ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      const unsigned char *tag, size_t tag_len )
+{
+    int ret;
+    unsigned char check_tag[16];
+    unsigned char i;
+    int diff;
+
+    if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
+                                iv, iv_len, add, add_len,
+                                input, output, check_tag, tag_len ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /* Check tag in "constant-time" */
+    for( diff = 0, i = 0; i < tag_len; i++ )
+        diff |= tag[i] ^ check_tag[i];
+
+    if( diff != 0 )
+    {
+        polarssl_zeroize( output, length );
+        return( POLARSSL_ERR_CCM_AUTH_FAILED );
+    }
+
+    return( 0 );
+}
+
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf printf
+#endif
+
+/*
+ * Examples 1 to 3 from SP800-38C Appendix C
+ */
+
+#define NB_TESTS 3
+
+/*
+ * The data is the same for all tests, only the used length changes
+ */
+static const unsigned char key[] = {
+    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
+};
+
+static const unsigned char iv[] = {
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b
+};
+
+static const unsigned char ad[] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13
+};
+
+static const unsigned char msg[] = {
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+};
+
+static const size_t iv_len [NB_TESTS] = { 7, 8,  12 };
+static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
+static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
+static const size_t tag_len[NB_TESTS] = { 4, 6,  8  };
+
+static const unsigned char res[NB_TESTS][32] = {
+    {   0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
+    {   0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
+        0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
+        0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
+    {   0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
+        0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
+        0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
+        0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
+};
+
+int ccm_self_test( int verbose )
+{
+    ccm_context ctx;
+    unsigned char out[32];
+    size_t i;
+    int ret;
+
+    if( ccm_init( &ctx, POLARSSL_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  CCM: setup failed" );
+
+        return( 1 );
+    }
+
+    for( i = 0; i < NB_TESTS; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  CCM-AES #%u: ", (unsigned int) i + 1 );
+
+        ret = ccm_encrypt_and_tag( &ctx, msg_len[i],
+                                   iv, iv_len[i], ad, add_len[i],
+                                   msg, out,
+                                   out + msg_len[i], tag_len[i] );
+
+        if( ret != 0 ||
+            memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        ret = ccm_auth_decrypt( &ctx, msg_len[i],
+                                iv, iv_len[i], ad, add_len[i],
+                                res[i], out,
+                                res[i] + msg_len[i], tag_len[i] );
+
+        if( ret != 0 ||
+            memcmp( out, msg, msg_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+    }
+
+    ccm_free( &ctx );
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
+
+#endif /* POLARSSL_CCM_C */
index 17775b889fd76844c1658c972074e96353ed7aed..a782bc11443255da99ecb1e1d9e20e059acdcdb8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  X.509 test certificates
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_CERTS_C)
 
@@ -169,55 +173,56 @@ const char test_ca_pwd_rsa[] = "PolarSSLTest";
 
 const char test_srv_crt_rsa[] =
 "-----BEGIN CERTIFICATE-----\r\n"
-"MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
+"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
 "MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
-"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
-"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN\r\n"
-"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/\r\n"
-"uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD\r\n"
-"d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf\r\n"
-"CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr\r\n"
-"lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w\r\n"
-"bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB\r\n"
-"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf\r\n"
-"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
-"AQEAvc+WwZUemsJu2IiI2Cp6liA+UAvIx98dQe3kZs2zAoF9VwQbXcYzWQ/BILkj\r\n"
-"NImKbPL9x0g2jIDn4ZvGYFywMwIO/d++YbwYiQw42/v7RiMy94zBPnzeHi86dy/0\r\n"
-"jpOOJUx3IXRsGLdyjb/1T11klcFqGnARiK+8VYolMPP6afKvLXX7K4kiUpsFQhUp\r\n"
-"E5VeM5pV1Mci2ETOJau2cO40FJvI/C9W/wR+GAArMaw2fxG77E3laaa0LAOlexM6\r\n"
-"A4KOb5f5cGTM5Ih6tEF5FVq3/9vzNIYMa1FqzacBLZF8zSHYLEimXBdzjBoN4qDU\r\n"
-"/WzRyYRBRjAI49mzHX6raleqnw==\r\n"
+"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"
+"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"
+"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n"
+"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n"
+"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n"
+"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n"
+"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n"
+"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n"
+"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n"
+"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n"
+"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n"
+"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n"
+"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n"
+"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n"
+"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n"
+"zhuYwjVuX6JHG0c=\r\n"
 "-----END CERTIFICATE-----\r\n";
 
 const char test_srv_key_rsa[] =
 "-----BEGIN RSA PRIVATE KEY-----\r\n"
-"MIIEogIBAAKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/uOhFkNvuiBZS0/FDUEeW\r\n"
-"Ellkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFDd185fAkER4KwVzlw7aPs\r\n"
-"FRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVfCrFTxjB+FTms+Vruf5Ke\r\n"
-"pgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTrlZvc/kFeF6babFtpzAK6\r\n"
-"FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9wbp7OvViJ4lNZnm5akmXi\r\n"
-"iD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQABAoIBABaJ9eiRQq4Ypv+w\r\n"
-"UTcVpLC0oTueWzcpor1i1zjG4Vzqe/Ok2FqyGToGKMlFK7Hwwa+LEyeJ3xyV5yd4\r\n"
-"v1Mw9bDZFdJC1eCBjoUAHtX6k9HOE0Vd6woVQ4Vi6OPI1g7B5Mnr/58rNrnN6TMs\r\n"
-"x58NF6euecwTU811QJrZtLbX7j2Cr28yB2Vs8qyYlHwVw5jbDOv43D7vU5gmlIDN\r\n"
-"0JQRuWAnOuPzZNoJr4SfJKqHNGxYYY6pHZ1s0dOTLIDb/B8KQWapA2kRmZyid2EH\r\n"
-"nwzgLbAsHJCf+bQnhXjXuxtUsrcIL8noZLazlOMxwNEammglVWW23Ud/QRnFgJg5\r\n"
-"UgcAcRECgYEA19uYetht5qmwdJ+12oC6zeO+vXLcyD9gon23T5J6w2YThld7/OW0\r\n"
-"oArQJGgkAdaq0pcTyOIjtTQVMFygdVmCEJmxh/3RutPcTeydqW9fphKDMej32J8e\r\n"
-"GniGmNGiclbcfNOS8E5TGp445yZb9P1+7AHng16bGg3Ykj5EA4G+HCcCgYEAyHAl\r\n"
-"//ekk8YjQElm+8izLtFkymIK0aCtEe9C/RIRhFYBeFaotC5dStNhBOncn4ovMAPD\r\n"
-"lX/92yDi9OP8PPLN3a4B9XpW3k/SS5GrbT5cwOivBHNllZSmu/2qz5WPGcjVCOrB\r\n"
-"LYl3YWr2h3EGKICT03kEoTkiDBvCeOpW7cCGl2cCgYBD5whoXHz1+ptPlI4YVjZt\r\n"
-"Xh86aU+ajpVPiEyJ84I6xXmO4SZXv8q6LaycR0ZMbcL+zBelMb4Z2nBv7jNrtuR7\r\n"
-"ZF28cdPv+YVr3esaybZE/73VjXup4SQPH6r3l7qKTVi+y6+FeJ4b2Xn8/MwgnT23\r\n"
-"8EFrye7wmzpthrjOgZnUMQKBgE9Lhsz/5J0Nis6Y+2Pqn3CLKEukg9Ewtqdct2y0\r\n"
-"5Dcta0F3TyCRIxlCDKTL/BslqMtfAdY4H268UO0+8IAQMn9boqzBrHIgs/pvc5kx\r\n"
-"TbKHmw2wtWR6vYersBKVgVpbCGSRssDYHGFu1n74qM4HJ/RGcR1zI9QUe1gopSFD\r\n"
-"xDtLAoGAVAdWvrqDwgoL2hHW3scGpxdE/ygJDOwHnf+1B9goKAOP5lf2FJaiAxf3\r\n"
-"ectoPOgZbCmm/iiDmigu703ld3O+VoCLDD4qx3R+KyALL78gtVJYzSRiKhzgCZ3g\r\n"
-"mKsIVRBq4IfwiwyMNG2BYZQAwbSDjjPtn/kPBduPzPj7eriByhI=\r\n"
+"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n"
+"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n"
+"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n"
+"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n"
+"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n"
+"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n"
+"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n"
+"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n"
+"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n"
+"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n"
+"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n"
+"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n"
+"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n"
+"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n"
+"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n"
+"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n"
+"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n"
+"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n"
+"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n"
+"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n"
+"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n"
+"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n"
+"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n"
+"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n"
+"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n"
 "-----END RSA PRIVATE KEY-----\r\n";
 
+
 const char test_cli_crt_rsa[] =
 "-----BEGIN CERTIFICATE-----\r\n"
 "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
@@ -300,6 +305,6 @@ const char *test_srv_crt = test_srv_crt_ec;
 const char *test_srv_key = test_srv_key_ec;
 const char *test_cli_crt = test_cli_crt_ec;
 const char *test_cli_key = test_cli_key_ec;
-#endif
+#endif /* POLARSSL_RSA_C */
 
 #endif /* POLARSSL_CERTS_C */
index f0a770abaeb4eecac60c7fe146373de84eea9473..5cd30f8ad912befd462380bfe2bd27f0a46a44f7 100644 (file)
@@ -1,11 +1,11 @@
 /**
  * \file cipher.c
- * 
+ *
  * \brief Generic cipher wrapper for PolarSSL
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_CIPHER_C)
 
 #include "polarssl/gcm.h"
 #endif
 
+#if defined(POLARSSL_CCM_C)
+#include "polarssl/ccm.h"
+#endif
+
 #include <stdlib.h>
 
 #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
 #define strcasecmp _stricmp
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 static int supported_init = 0;
 
 const int *cipher_list( void )
@@ -69,7 +82,7 @@ const int *cipher_list( void )
         supported_init = 1;
     }
 
-    return supported_ciphers;
+    return( supported_ciphers );
 }
 
 const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
@@ -80,7 +93,7 @@ const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type )
         if( def->type == cipher_type )
             return( def->info );
 
-    return NULL;
+    return( NULL );
 }
 
 const cipher_info_t *cipher_info_from_string( const char *cipher_name )
@@ -88,13 +101,13 @@ const cipher_info_t *cipher_info_from_string( const char *cipher_name )
     const cipher_definition_t *def;
 
     if( NULL == cipher_name )
-        return NULL;
+        return( NULL );
 
     for( def = cipher_definitions; def->info != NULL; def++ )
         if( !  strcasecmp( def->info->name, cipher_name ) )
             return( def->info );
 
-    return NULL;
+    return( NULL );
 }
 
 const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id,
@@ -109,18 +122,34 @@ const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id,
             def->info->mode == mode )
             return( def->info );
 
-    return NULL;
+    return( NULL );
+}
+
+void cipher_init( cipher_context_t *ctx )
+{
+    memset( ctx, 0, sizeof( cipher_context_t ) );
+}
+
+void cipher_free( cipher_context_t *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    if( ctx->cipher_ctx )
+        ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
+
+    polarssl_zeroize( ctx, sizeof(cipher_context_t) );
 }
 
 int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
 {
     if( NULL == cipher_info || NULL == ctx )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     memset( ctx, 0, sizeof( cipher_context_t ) );
 
     if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
-        return POLARSSL_ERR_CIPHER_ALLOC_FAILED;
+        return( POLARSSL_ERR_CIPHER_ALLOC_FAILED );
 
     ctx->cipher_info = cipher_info;
 
@@ -135,27 +164,28 @@ int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
 #endif
 #endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
 
-    return 0;
+    return( 0 );
 }
 
+/* Deprecated, redirects to cipher_free() */
 int cipher_free_ctx( cipher_context_t *ctx )
 {
-    if( ctx == NULL || ctx->cipher_info == NULL )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    cipher_free( ctx );
 
-    ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
-
-    return 0;
+    return( 0 );
 }
 
 int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
         int key_length, const operation_t operation )
 {
     if( NULL == ctx || NULL == ctx->cipher_info )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
-    if( (int) ctx->cipher_info->key_length != key_length )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    if( ( ctx->cipher_info->flags & POLARSSL_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
+        (int) ctx->cipher_info->key_length != key_length )
+    {
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
+    }
 
     ctx->key_length = key_length;
     ctx->operation = operation;
@@ -175,7 +205,7 @@ int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,
         return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
                 ctx->key_length );
 
-    return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 }
 
 int cipher_set_iv( cipher_context_t *ctx,
@@ -184,13 +214,13 @@ int cipher_set_iv( cipher_context_t *ctx,
     size_t actual_iv_size;
 
     if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     /* avoid buffer overflow in ctx->iv */
     if( iv_len > POLARSSL_MAX_IV_LENGTH )
-        return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+        return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
 
-    if( ctx->cipher_info->accepts_variable_iv_size )
+    if( ( ctx->cipher_info->flags & POLARSSL_CIPHER_VARIABLE_IV_LEN ) != 0 )
         actual_iv_size = iv_len;
     else
     {
@@ -198,70 +228,68 @@ int cipher_set_iv( cipher_context_t *ctx,
 
         /* avoid reading past the end of input buffer */
         if( actual_iv_size > iv_len )
-            return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+            return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
     }
 
     memcpy( ctx->iv, iv, actual_iv_size );
     ctx->iv_size = actual_iv_size;
 
-    return 0;
+    return( 0 );
 }
 
 int cipher_reset( cipher_context_t *ctx )
 {
     if( NULL == ctx || NULL == ctx->cipher_info )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     ctx->unprocessed_len = 0;
 
-    return 0;
+    return( 0 );
 }
 
-#if defined(POLARSSL_CIPHER_MODE_AEAD)
+#if defined(POLARSSL_GCM_C)
 int cipher_update_ad( cipher_context_t *ctx,
                       const unsigned char *ad, size_t ad_len )
 {
     if( NULL == ctx || NULL == ctx->cipher_info )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
-#if defined(POLARSSL_GCM_C)
     if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
     {
         return gcm_starts( (gcm_context *) ctx->cipher_ctx, ctx->operation,
                            ctx->iv, ctx->iv_size, ad, ad_len );
     }
-#endif
 
-    return 0;
+    return( 0 );
 }
-#endif /* POLARSSL_CIPHER_MODE_AEAD */
+#endif /* POLARSSL_GCM_C */
 
-int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
-        unsigned char *output, size_t *olen )
+int cipher_update( cipher_context_t *ctx, const unsigned char *input,
+                   size_t ilen, unsigned char *output, size_t *olen )
 {
     int ret;
 
-    *olen = 0;
-
     if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
     {
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
     }
 
+    *olen = 0;
+
     if( ctx->cipher_info->mode == POLARSSL_MODE_ECB )
     {
         if( ilen != cipher_get_block_size( ctx ) )
-            return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+            return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED );
 
         *olen = ilen;
 
         if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
                     ctx->operation, input, output ) ) )
         {
-            return ret;
+            return( ret );
         }
 
-        return 0;
+        return( 0 );
     }
 
 #if defined(POLARSSL_GCM_C)
@@ -276,7 +304,7 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
     if( input == output &&
        ( ctx->unprocessed_len != 0 || ilen % cipher_get_block_size( ctx ) ) )
     {
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
     }
 
 #if defined(POLARSSL_CIPHER_MODE_CBC)
@@ -296,7 +324,7 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
                     ilen );
 
             ctx->unprocessed_len += ilen;
-            return 0;
+            return( 0 );
         }
 
         /*
@@ -313,7 +341,7 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
                     ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
                     ctx->unprocessed_data, output ) ) )
             {
-                return ret;
+                return( ret );
             }
 
             *olen += cipher_get_block_size( ctx );
@@ -331,7 +359,7 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
         {
             copy_len = ilen % cipher_get_block_size( ctx );
             if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT )
-                copy_len = cipher_get_block_size(ctx);
+                copy_len = cipher_get_block_size( ctx );
 
             memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
                     copy_len );
@@ -348,13 +376,13 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
             if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
                     ctx->operation, ilen, ctx->iv, input, output ) ) )
             {
-                return ret;
+                return( ret );
             }
 
             *olen += ilen;
         }
 
-        return 0;
+        return( 0 );
     }
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 
@@ -365,14 +393,14 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
                 ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
                 input, output ) ) )
         {
-            return ret;
+            return( ret );
         }
 
         *olen = ilen;
 
-        return 0;
+        return( 0 );
     }
-#endif
+#endif /* POLARSSL_CIPHER_MODE_CFB */
 
 #if defined(POLARSSL_CIPHER_MODE_CTR)
     if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )
@@ -381,14 +409,14 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
                 ilen, &ctx->unprocessed_len, ctx->iv,
                 ctx->unprocessed_data, input, output ) ) )
         {
-            return ret;
+            return( ret );
         }
 
         *olen = ilen;
 
-        return 0;
+        return( 0 );
     }
-#endif
+#endif /* POLARSSL_CIPHER_MODE_CTR */
 
 #if defined(POLARSSL_CIPHER_MODE_STREAM)
     if( ctx->cipher_info->mode == POLARSSL_MODE_STREAM )
@@ -396,16 +424,16 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile
         if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
                                                     ilen, input, output ) ) )
         {
-            return ret;
+            return( ret );
         }
 
         *olen = ilen;
 
-        return 0;
+        return( 0 );
     }
-#endif
+#endif /* POLARSSL_CIPHER_MODE_STREAM */
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
 }
 
 #if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
@@ -430,7 +458,7 @@ static int get_pkcs_padding( unsigned char *input, size_t input_len,
     unsigned char padding_len, bad = 0;
 
     if( NULL == input || NULL == data_len )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     padding_len = input[input_len - 1];
     *data_len = input_len - padding_len;
@@ -445,7 +473,7 @@ static int get_pkcs_padding( unsigned char *input, size_t input_len,
     for( i = 0; i < input_len; i++ )
         bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
 
-    return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+    return( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
 }
 #endif /* POLARSSL_CIPHER_PADDING_PKCS7 */
 
@@ -471,7 +499,7 @@ static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
     unsigned char done = 0, prev_done, bad;
 
     if( NULL == input || NULL == data_len )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     bad = 0xFF;
     *data_len = 0;
@@ -483,7 +511,7 @@ static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
         bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done );
     }
 
-    return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+    return( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
 
 }
 #endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */
@@ -510,7 +538,7 @@ static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
     unsigned char padding_len, bad = 0;
 
     if( NULL == input || NULL == data_len )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     padding_len = input[input_len - 1];
     *data_len = input_len - padding_len;
@@ -524,7 +552,7 @@ static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
     for( i = 0; i < input_len - 1; i++ )
         bad |= input[i] * ( i >= pad_idx );
 
-    return POLARSSL_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+    return( POLARSSL_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
 }
 #endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */
 
@@ -548,7 +576,7 @@ static int get_zeros_padding( unsigned char *input, size_t input_len,
     unsigned char done = 0, prev_done;
 
     if( NULL == input || NULL == data_len )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     *data_len = 0;
     for( i = input_len; i > 0; i-- )
@@ -558,7 +586,7 @@ static int get_zeros_padding( unsigned char *input, size_t input_len,
         *data_len |= i * ( done != prev_done );
     }
 
-    return 0;
+    return( 0 );
 }
 #endif /* POLARSSL_CIPHER_PADDING_ZEROS */
 
@@ -572,11 +600,11 @@ static int get_no_padding( unsigned char *input, size_t input_len,
                               size_t *data_len )
 {
     if( NULL == input || NULL == data_len )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     *data_len = input_len;
 
-    return 0;
+    return( 0 );
 }
 #endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
 
@@ -584,7 +612,7 @@ int cipher_finish( cipher_context_t *ctx,
                    unsigned char *output, size_t *olen )
 {
     if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     *olen = 0;
 
@@ -593,15 +621,15 @@ int cipher_finish( cipher_context_t *ctx,
         POLARSSL_MODE_GCM == ctx->cipher_info->mode ||
         POLARSSL_MODE_STREAM == ctx->cipher_info->mode )
     {
-        return 0;
+        return( 0 );
     }
 
     if( POLARSSL_MODE_ECB == ctx->cipher_info->mode )
     {
         if( ctx->unprocessed_len != 0 )
-            return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+            return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED );
 
-        return 0;
+        return( 0 );
     }
 
 #if defined(POLARSSL_CIPHER_MODE_CBC)
@@ -615,24 +643,24 @@ int cipher_finish( cipher_context_t *ctx,
             if( NULL == ctx->add_padding )
             {
                 if( 0 != ctx->unprocessed_len )
-                    return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+                    return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED );
 
-                return 0;
+                return( 0 );
             }
 
             ctx->add_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ),
                     ctx->unprocessed_len );
         }
-        else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len )
+        else if( cipher_get_block_size( ctx ) != ctx->unprocessed_len )
         {
             /*
              * For decrypt operations, expect a full block,
              * or an empty block if no padding
              */
             if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
-                return 0;
+                return( 0 );
 
-            return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+            return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED );
         }
 
         /* cipher block */
@@ -640,7 +668,7 @@ int cipher_finish( cipher_context_t *ctx,
                 ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
                 ctx->unprocessed_data, output ) ) )
         {
-            return ret;
+            return( ret );
         }
 
         /* Set output size for decryption */
@@ -650,13 +678,13 @@ int cipher_finish( cipher_context_t *ctx,
 
         /* Set output size for encryption */
         *olen = cipher_get_block_size( ctx );
-        return 0;
+        return( 0 );
     }
 #else
     ((void) output);
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
 }
 
 #if defined(POLARSSL_CIPHER_MODE_WITH_PADDING)
@@ -665,7 +693,7 @@ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode )
     if( NULL == ctx ||
         POLARSSL_MODE_CBC != ctx->cipher_info->mode )
     {
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
     }
 
     switch( mode )
@@ -700,31 +728,29 @@ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode )
         break;
 
     default:
-        return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+        return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
     }
 
-    return 0;
+    return( 0 );
 }
 #endif /* POLARSSL_CIPHER_MODE_WITH_PADDING */
 
-#if defined(POLARSSL_CIPHER_MODE_AEAD)
+#if defined(POLARSSL_GCM_C)
 int cipher_write_tag( cipher_context_t *ctx,
                       unsigned char *tag, size_t tag_len )
 {
     if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     if( POLARSSL_ENCRYPT != ctx->operation )
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
-#if defined(POLARSSL_GCM_C)
     if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
         return gcm_finish( (gcm_context *) ctx->cipher_ctx, tag, tag_len );
-#endif
 
-    return 0;
+    return( 0 );
 }
+
 int cipher_check_tag( cipher_context_t *ctx,
                       const unsigned char *tag, size_t tag_len )
 {
@@ -733,10 +759,9 @@ int cipher_check_tag( cipher_context_t *ctx,
     if( NULL == ctx || NULL == ctx->cipher_info ||
         POLARSSL_DECRYPT != ctx->operation )
     {
-        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
     }
 
-#if defined(POLARSSL_GCM_C)
     if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
     {
         unsigned char check_tag[16];
@@ -744,7 +769,7 @@ int cipher_check_tag( cipher_context_t *ctx,
         int diff;
 
         if( tag_len > sizeof( check_tag ) )
-            return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+            return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
         if( 0 != ( ret = gcm_finish( (gcm_context *) ctx->cipher_ctx,
                                      check_tag, tag_len ) ) )
@@ -761,24 +786,125 @@ int cipher_check_tag( cipher_context_t *ctx,
 
         return( 0 );
     }
-#endif
 
     return( 0 );
 }
-#endif /* POLARSSL_CIPHER_MODE_AEAD */
+#endif /* POLARSSL_GCM_C */
 
-#if defined(POLARSSL_SELF_TEST)
+/*
+ * Packet-oriented wrapper for non-AEAD modes
+ */
+int cipher_crypt( cipher_context_t *ctx,
+                  const unsigned char *iv, size_t iv_len,
+                  const unsigned char *input, size_t ilen,
+                  unsigned char *output, size_t *olen )
+{
+    int ret;
+    size_t finish_olen;
+
+    if( ( ret = cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
+        return( ret );
+
+    if( ( ret = cipher_reset( ctx ) ) != 0 )
+        return( ret );
+
+    if( ( ret = cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
+        return( ret );
 
-#include <stdio.h>
+    if( ( ret = cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
+        return( ret );
 
-#define ASSERT(x) if (!(x)) { \
-        printf( "failed with %i at %s\n", value, (#x) ); \
-    return( 1 ); \
+    *olen += finish_olen;
+
+    return( 0 );
 }
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
 /*
- * Checkup routine
+ * Packet-oriented encryption for AEAD modes
  */
+int cipher_auth_encrypt( cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         unsigned char *tag, size_t tag_len )
+{
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+    {
+        *olen = ilen;
+        return( gcm_crypt_and_tag( ctx->cipher_ctx, GCM_ENCRYPT, ilen,
+                                   iv, iv_len, ad, ad_len, input, output,
+                                   tag_len, tag ) );
+    }
+#endif /* POLARSSL_GCM_C */
+#if defined(POLARSSL_CCM_C)
+    if( POLARSSL_MODE_CCM == ctx->cipher_info->mode )
+    {
+        *olen = ilen;
+        return( ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
+                                     iv, iv_len, ad, ad_len, input, output,
+                                     tag, tag_len ) );
+    }
+#endif /* POLARSSL_CCM_C */
 
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+/*
+ * Packet-oriented decryption for AEAD modes
+ */
+int cipher_auth_decrypt( cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *ad, size_t ad_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen,
+                         const unsigned char *tag, size_t tag_len )
+{
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+    {
+        int ret;
+
+        *olen = ilen;
+        ret = gcm_auth_decrypt( ctx->cipher_ctx, ilen,
+                                iv, iv_len, ad, ad_len,
+                                tag, tag_len, input, output );
+
+        if( ret == POLARSSL_ERR_GCM_AUTH_FAILED )
+            ret = POLARSSL_ERR_CIPHER_AUTH_FAILED;
+
+        return( ret );
+    }
+#endif /* POLARSSL_GCM_C */
+#if defined(POLARSSL_CCM_C)
+    if( POLARSSL_MODE_CCM == ctx->cipher_info->mode )
+    {
+        int ret;
+
+        *olen = ilen;
+        ret = ccm_auth_decrypt( ctx->cipher_ctx, ilen,
+                                iv, iv_len, ad, ad_len,
+                                input, output, tag, tag_len );
+
+        if( ret == POLARSSL_ERR_CCM_AUTH_FAILED )
+            ret = POLARSSL_ERR_CIPHER_AUTH_FAILED;
+
+        return( ret );
+    }
+#endif /* POLARSSL_CCM_C */
+
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
+
+#if defined(POLARSSL_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
 int cipher_self_test( int verbose )
 {
     ((void) verbose);
@@ -786,6 +912,6 @@ int cipher_self_test( int verbose )
     return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_CIPHER_C */
index 3020e14e21b8ecde5a8dfe851c3efc67d28e34f6..47a69a97b2392c9648bc9648dc5029040c423768 100644 (file)
@@ -1,11 +1,11 @@
 /**
  * \file cipher_wrap.c
- * 
+ *
  * \brief Generic cipher wrapper for PolarSSL
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_CIPHER_C)
 
 #include "polarssl/gcm.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_CCM_C)
+#include "polarssl/ccm.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
@@ -78,7 +86,21 @@ static void gcm_ctx_free( void *ctx )
     gcm_free( ctx );
     polarssl_free( ctx );
 }
-#endif
+#endif /* POLARSSL_GCM_C */
+
+#if defined(POLARSSL_CCM_C)
+/* shared by all CCM ciphers */
+static void *ccm_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( ccm_context ) );
+}
+
+static void ccm_ctx_free( void *ctx )
+{
+    ccm_free( ctx );
+    polarssl_free( ctx );
+}
+#endif /* POLARSSL_CCM_C */
 
 #if defined(POLARSSL_AES_C)
 
@@ -92,7 +114,8 @@ static int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
         unsigned char *iv, const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CBC)
-    return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input, output );
+    return aes_crypt_cbc( (aes_context *) ctx, operation, length, iv, input,
+                          output );
 #else
     ((void) ctx);
     ((void) operation);
@@ -101,15 +124,17 @@ static int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 }
 
-static int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
-        size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int aes_crypt_cfb128_wrap( void *ctx, operation_t operation,
+        size_t length, size_t *iv_off, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CFB)
-    return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv, input, output );
+    return aes_crypt_cfb128( (aes_context *) ctx, operation, length, iv_off, iv,
+                             input, output );
 #else
     ((void) ctx);
     ((void) operation);
@@ -119,12 +144,12 @@ static int aes_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t lengt
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
 }
 
-static int aes_crypt_ctr_wrap( void *ctx, size_t length,
-        size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+        unsigned char *nonce_counter, unsigned char *stream_block,
         const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CTR)
@@ -139,27 +164,37 @@ static int aes_crypt_ctr_wrap( void *ctx, size_t length,
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
 }
 
-static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
 {
     return aes_setkey_dec( (aes_context *) ctx, key, key_length );
 }
 
-static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
 {
     return aes_setkey_enc( (aes_context *) ctx, key, key_length );
 }
 
 static void * aes_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( aes_context ) );
+    aes_context *aes = (aes_context *) polarssl_malloc( sizeof( aes_context ) );
+
+    if( aes == NULL )
+        return( NULL );
+
+    aes_init( aes );
+
+    return( aes );
 }
 
 static void aes_ctx_free( void *ctx )
 {
+    aes_free( (aes_context *) ctx );
     polarssl_free( ctx );
 }
 
@@ -315,7 +350,8 @@ const cipher_info_t aes_256_ctr_info = {
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 
 #if defined(POLARSSL_GCM_C)
-static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
 {
     return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_AES,
                      key, key_length );
@@ -340,7 +376,7 @@ const cipher_info_t aes_128_gcm_info = {
     128,
     "AES-128-GCM",
     12,
-    1,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
     16,
     &gcm_aes_info
 };
@@ -351,7 +387,7 @@ const cipher_info_t aes_192_gcm_info = {
     192,
     "AES-192-GCM",
     12,
-    1,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
     16,
     &gcm_aes_info
 };
@@ -362,27 +398,85 @@ const cipher_info_t aes_256_gcm_info = {
     256,
     "AES-256-GCM",
     12,
-    1,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
     16,
     &gcm_aes_info
 };
 #endif /* POLARSSL_GCM_C */
 
-#endif
+#if defined(POLARSSL_CCM_C)
+static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
+{
+    return ccm_init( (ccm_context *) ctx, POLARSSL_CIPHER_ID_AES,
+                     key, key_length );
+}
+
+const cipher_base_t ccm_aes_info = {
+    POLARSSL_CIPHER_ID_AES,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    ccm_aes_setkey_wrap,
+    ccm_aes_setkey_wrap,
+    ccm_ctx_alloc,
+    ccm_ctx_free,
+};
+
+const cipher_info_t aes_128_ccm_info = {
+    POLARSSL_CIPHER_AES_128_CCM,
+    POLARSSL_MODE_CCM,
+    128,
+    "AES-128-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+
+const cipher_info_t aes_192_ccm_info = {
+    POLARSSL_CIPHER_AES_192_CCM,
+    POLARSSL_MODE_CCM,
+    192,
+    "AES-192-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+
+const cipher_info_t aes_256_ccm_info = {
+    POLARSSL_CIPHER_AES_256_CCM,
+    POLARSSL_MODE_CCM,
+    256,
+    "AES-256-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+#endif /* POLARSSL_CCM_C */
+
+#endif /* POLARSSL_AES_C */
 
 #if defined(POLARSSL_CAMELLIA_C)
 
 static int camellia_crypt_ecb_wrap( void *ctx, operation_t operation,
         const unsigned char *input, unsigned char *output )
 {
-    return camellia_crypt_ecb( (camellia_context *) ctx, operation, input, output );
+    return camellia_crypt_ecb( (camellia_context *) ctx, operation, input,
+                               output );
 }
 
-static int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
-        unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int camellia_crypt_cbc_wrap( void *ctx, operation_t operation,
+        size_t length, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CBC)
-    return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv, input, output );
+    return camellia_crypt_cbc( (camellia_context *) ctx, operation, length, iv,
+                               input, output );
 #else
     ((void) ctx);
     ((void) operation);
@@ -391,15 +485,17 @@ static int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, size_t len
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 }
 
-static int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
-        size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation,
+        size_t length, size_t *iv_off, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CFB)
-    return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length, iv_off, iv, input, output );
+    return camellia_crypt_cfb128( (camellia_context *) ctx, operation, length,
+                                  iv_off, iv, input, output );
 #else
     ((void) ctx);
     ((void) operation);
@@ -409,17 +505,17 @@ static int camellia_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
 }
 
-static int camellia_crypt_ctr_wrap( void *ctx, size_t length,
-        size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+        unsigned char *nonce_counter, unsigned char *stream_block,
         const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CTR)
-    return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off, nonce_counter,
-                          stream_block, input, output );
+    return camellia_crypt_ctr( (camellia_context *) ctx, length, nc_off,
+                               nonce_counter, stream_block, input, output );
 #else
     ((void) ctx);
     ((void) length);
@@ -429,27 +525,38 @@ static int camellia_crypt_ctr_wrap( void *ctx, size_t length,
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
 }
 
-static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key,
+                                     unsigned int key_length )
 {
     return camellia_setkey_dec( (camellia_context *) ctx, key, key_length );
 }
 
-static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key,
+                                     unsigned int key_length )
 {
     return camellia_setkey_enc( (camellia_context *) ctx, key, key_length );
 }
 
 static void * camellia_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( camellia_context ) );
+    camellia_context *ctx;
+    ctx = (camellia_context *) polarssl_malloc( sizeof( camellia_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    camellia_init( ctx );
+
+    return( ctx );
 }
 
 static void camellia_ctx_free( void *ctx )
 {
+    camellia_free( (camellia_context *) ctx );
     polarssl_free( ctx );
 }
 
@@ -605,7 +712,8 @@ const cipher_info_t camellia_256_ctr_info = {
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 
 #if defined(POLARSSL_GCM_C)
-static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key,
+                                     unsigned int key_length )
 {
     return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_CAMELLIA,
                      key, key_length );
@@ -630,7 +738,7 @@ const cipher_info_t camellia_128_gcm_info = {
     128,
     "CAMELLIA-128-GCM",
     12,
-    1,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
     16,
     &gcm_camellia_info
 };
@@ -641,7 +749,7 @@ const cipher_info_t camellia_192_gcm_info = {
     192,
     "CAMELLIA-192-GCM",
     12,
-    1,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
     16,
     &gcm_camellia_info
 };
@@ -652,12 +760,67 @@ const cipher_info_t camellia_256_gcm_info = {
     256,
     "CAMELLIA-256-GCM",
     12,
-    1,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
     16,
     &gcm_camellia_info
 };
 #endif /* POLARSSL_GCM_C */
 
+#if defined(POLARSSL_CCM_C)
+static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key,
+                                     unsigned int key_length )
+{
+    return ccm_init( (ccm_context *) ctx, POLARSSL_CIPHER_ID_CAMELLIA,
+                     key, key_length );
+}
+
+const cipher_base_t ccm_camellia_info = {
+    POLARSSL_CIPHER_ID_CAMELLIA,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    ccm_camellia_setkey_wrap,
+    ccm_camellia_setkey_wrap,
+    ccm_ctx_alloc,
+    ccm_ctx_free,
+};
+
+const cipher_info_t camellia_128_ccm_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_CCM,
+    POLARSSL_MODE_CCM,
+    128,
+    "CAMELLIA-128-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+
+const cipher_info_t camellia_192_ccm_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_CCM,
+    POLARSSL_MODE_CCM,
+    192,
+    "CAMELLIA-192-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+
+const cipher_info_t camellia_256_ccm_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_CCM,
+    POLARSSL_MODE_CCM,
+    256,
+    "CAMELLIA-256-CCM",
+    12,
+    POLARSSL_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+#endif /* POLARSSL_CCM_C */
+
 #endif /* POLARSSL_CAMELLIA_C */
 
 #if defined(POLARSSL_DES_C)
@@ -680,7 +843,8 @@ static int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
         unsigned char *iv, const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CBC)
-    return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input, output );
+    return des_crypt_cbc( (des_context *) ctx, operation, length, iv, input,
+                          output );
 #else
     ((void) ctx);
     ((void) operation);
@@ -689,7 +853,7 @@ static int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 }
 
@@ -697,7 +861,8 @@ static int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
         unsigned char *iv, const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CBC)
-    return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input, output );
+    return des3_crypt_cbc( (des3_context *) ctx, operation, length, iv, input,
+                           output );
 #else
     ((void) ctx);
     ((void) operation);
@@ -706,75 +871,52 @@ static int des3_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 }
 
-static int des_crypt_cfb128_wrap( void *ctx, operation_t operation, size_t length,
-        size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
-{
-    ((void) ctx);
-    ((void) operation);
-    ((void) length);
-    ((void) iv_off);
-    ((void) iv);
-    ((void) input);
-    ((void) output);
-
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-}
-
-static int des_crypt_ctr_wrap( void *ctx, size_t length,
-        size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
-        const unsigned char *input, unsigned char *output )
-{
-    ((void) ctx);
-    ((void) length);
-    ((void) nc_off);
-    ((void) nonce_counter);
-    ((void) stream_block);
-    ((void) input);
-    ((void) output);
-
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-}
-
-static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int des_setkey_dec_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
 {
     ((void) key_length);
 
     return des_setkey_dec( (des_context *) ctx, key );
 }
 
-static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int des_setkey_enc_wrap( void *ctx, const unsigned char *key,
+                                unsigned int key_length )
 {
     ((void) key_length);
 
     return des_setkey_enc( (des_context *) ctx, key );
 }
 
-static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key,
+                                  unsigned int key_length )
 {
     ((void) key_length);
 
     return des3_set2key_dec( (des3_context *) ctx, key );
 }
 
-static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key,
+                                  unsigned int key_length )
 {
     ((void) key_length);
 
     return des3_set2key_enc( (des3_context *) ctx, key );
 }
 
-static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key,
+                                  unsigned int key_length )
 {
     ((void) key_length);
 
     return des3_set3key_dec( (des3_context *) ctx, key );
 }
 
-static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key,
+                                  unsigned int key_length )
 {
     ((void) key_length);
 
@@ -783,16 +925,38 @@ static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, unsigned
 
 static void * des_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( des_context ) );
+    des_context *des = (des_context *) polarssl_malloc( sizeof( des_context ) );
+
+    if( des == NULL )
+        return( NULL );
+
+    des_init( des );
+
+    return( des );
+}
+
+static void des_ctx_free( void *ctx )
+{
+    des_free( (des_context *) ctx );
+    polarssl_free( ctx );
 }
 
 static void * des3_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( des3_context ) );
+    des3_context *des3;
+    des3 = (des3_context *) polarssl_malloc( sizeof( des3_context ) );
+
+    if( des3 == NULL )
+        return( NULL );
+
+    des3_init( des3 );
+
+    return( des3 );
 }
 
-static void des_ctx_free( void *ctx )
+static void des3_ctx_free( void *ctx )
 {
+    des3_free( (des3_context *) ctx );
     polarssl_free( ctx );
 }
 
@@ -800,8 +964,8 @@ const cipher_base_t des_info = {
     POLARSSL_CIPHER_ID_DES,
     des_crypt_ecb_wrap,
     des_crypt_cbc_wrap,
-    des_crypt_cfb128_wrap,
-    des_crypt_ctr_wrap,
+    NULL,
+    NULL,
     NULL,
     des_setkey_enc_wrap,
     des_setkey_dec_wrap,
@@ -837,13 +1001,13 @@ const cipher_base_t des_ede_info = {
     POLARSSL_CIPHER_ID_DES,
     des3_crypt_ecb_wrap,
     des3_crypt_cbc_wrap,
-    des_crypt_cfb128_wrap,
-    des_crypt_ctr_wrap,
+    NULL,
+    NULL,
     NULL,
     des3_set2key_enc_wrap,
     des3_set2key_dec_wrap,
     des3_ctx_alloc,
-    des_ctx_free
+    des3_ctx_free
 };
 
 const cipher_info_t des_ede_ecb_info = {
@@ -874,13 +1038,13 @@ const cipher_base_t des_ede3_info = {
     POLARSSL_CIPHER_ID_DES,
     des3_crypt_ecb_wrap,
     des3_crypt_cbc_wrap,
-    des_crypt_cfb128_wrap,
-    des_crypt_ctr_wrap,
+    NULL,
+    NULL,
     NULL,
     des3_set3key_enc_wrap,
     des3_set3key_dec_wrap,
     des3_ctx_alloc,
-    des_ctx_free
+    des3_ctx_free
 };
 
 const cipher_info_t des_ede3_ecb_info = {
@@ -905,21 +1069,24 @@ const cipher_info_t des_ede3_cbc_info = {
     &des_ede3_info
 };
 #endif /* POLARSSL_CIPHER_MODE_CBC */
-#endif
+#endif /* POLARSSL_DES_C */
 
 #if defined(POLARSSL_BLOWFISH_C)
 
 static int blowfish_crypt_ecb_wrap( void *ctx, operation_t operation,
         const unsigned char *input, unsigned char *output )
 {
-    return blowfish_crypt_ecb( (blowfish_context *) ctx, operation, input, output );
+    return blowfish_crypt_ecb( (blowfish_context *) ctx, operation, input,
+                               output );
 }
 
-static int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
-        unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation,
+        size_t length, unsigned char *iv, const unsigned char *input,
+        unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CBC)
-    return blowfish_crypt_cbc( (blowfish_context *) ctx, operation, length, iv, input, output );
+    return blowfish_crypt_cbc( (blowfish_context *) ctx, operation, length, iv,
+                               input, output );
 #else
     ((void) ctx);
     ((void) operation);
@@ -928,15 +1095,17 @@ static int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation, size_t len
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 }
 
-static int blowfish_crypt_cfb64_wrap( void *ctx, operation_t operation, size_t length,
-        size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int blowfish_crypt_cfb64_wrap( void *ctx, operation_t operation,
+        size_t length, size_t *iv_off, unsigned char *iv,
+        const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CFB)
-    return blowfish_crypt_cfb64( (blowfish_context *) ctx, operation, length, iv_off, iv, input, output );
+    return blowfish_crypt_cfb64( (blowfish_context *) ctx, operation, length,
+                                 iv_off, iv, input, output );
 #else
     ((void) ctx);
     ((void) operation);
@@ -946,17 +1115,17 @@ static int blowfish_crypt_cfb64_wrap( void *ctx, operation_t operation, size_t l
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_CIPHER_MODE_CFB */
 }
 
-static int blowfish_crypt_ctr_wrap( void *ctx, size_t length,
-        size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block,
+static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+        unsigned char *nonce_counter, unsigned char *stream_block,
         const unsigned char *input, unsigned char *output )
 {
 #if defined(POLARSSL_CIPHER_MODE_CTR)
-    return blowfish_crypt_ctr( (blowfish_context *) ctx, length, nc_off, nonce_counter,
-                          stream_block, input, output );
+    return blowfish_crypt_ctr( (blowfish_context *) ctx, length, nc_off,
+                               nonce_counter, stream_block, input, output );
 #else
     ((void) ctx);
     ((void) length);
@@ -966,22 +1135,32 @@ static int blowfish_crypt_ctr_wrap( void *ctx, size_t length,
     ((void) input);
     ((void) output);
 
-    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
-#endif
+    return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_CIPHER_MODE_CTR */
 }
 
-static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int blowfish_setkey_wrap( void *ctx, const unsigned char *key,
+                                 unsigned int key_length )
 {
     return blowfish_setkey( (blowfish_context *) ctx, key, key_length );
 }
 
 static void * blowfish_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( blowfish_context ) );
+    blowfish_context *ctx;
+    ctx = (blowfish_context *) polarssl_malloc( sizeof( blowfish_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    blowfish_init( ctx );
+
+    return( ctx );
 }
 
 static void blowfish_ctx_free( void *ctx )
 {
+    blowfish_free( (blowfish_context *) ctx );
     polarssl_free( ctx );
 }
 
@@ -1004,7 +1183,7 @@ const cipher_info_t blowfish_ecb_info = {
     128,
     "BLOWFISH-ECB",
     8,
-    0,
+    POLARSSL_CIPHER_VARIABLE_KEY_LEN,
     8,
     &blowfish_info
 };
@@ -1016,7 +1195,7 @@ const cipher_info_t blowfish_cbc_info = {
     128,
     "BLOWFISH-CBC",
     8,
-    0,
+    POLARSSL_CIPHER_VARIABLE_KEY_LEN,
     8,
     &blowfish_info
 };
@@ -1029,7 +1208,7 @@ const cipher_info_t blowfish_cfb64_info = {
     128,
     "BLOWFISH-CFB64",
     8,
-    0,
+    POLARSSL_CIPHER_VARIABLE_KEY_LEN,
     8,
     &blowfish_info
 };
@@ -1042,7 +1221,7 @@ const cipher_info_t blowfish_ctr_info = {
     128,
     "BLOWFISH-CTR",
     8,
-    0,
+    POLARSSL_CIPHER_VARIABLE_KEY_LEN,
     8,
     &blowfish_info
 };
@@ -1061,7 +1240,7 @@ static int arc4_setkey_wrap( void *ctx, const unsigned char *key,
                              unsigned int key_length )
 {
     /* we get key_length in bits, arc4 expects it in bytes */
-    if( key_length % 8 != 0)
+    if( key_length % 8 != 0 )
         return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
 
     arc4_setup( (arc4_context *) ctx, key, key_length / 8 );
@@ -1070,11 +1249,20 @@ static int arc4_setkey_wrap( void *ctx, const unsigned char *key,
 
 static void * arc4_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( arc4_context ) );
+    arc4_context *ctx;
+    ctx = (arc4_context *) polarssl_malloc( sizeof( arc4_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    arc4_init( ctx );
+
+    return( ctx );
 }
 
 static void arc4_ctx_free( void *ctx )
 {
+    arc4_free( (arc4_context *) ctx );
     polarssl_free( ctx );
 }
 
@@ -1125,7 +1313,7 @@ static int null_setkey( void *ctx, const unsigned char *key,
 
 static void * null_ctx_alloc( void )
 {
-    return (void *) 1;
+    return( (void *) 1 )
 }
 
 static void null_ctx_free( void *ctx )
@@ -1184,6 +1372,11 @@ const cipher_definition_t cipher_definitions[] =
     { POLARSSL_CIPHER_AES_192_GCM,          &aes_192_gcm_info },
     { POLARSSL_CIPHER_AES_256_GCM,          &aes_256_gcm_info },
 #endif
+#if defined(POLARSSL_CCM_C)
+    { POLARSSL_CIPHER_AES_128_CCM,          &aes_128_ccm_info },
+    { POLARSSL_CIPHER_AES_192_CCM,          &aes_192_ccm_info },
+    { POLARSSL_CIPHER_AES_256_CCM,          &aes_256_ccm_info },
+#endif
 #endif /* POLARSSL_AES_C */
 
 #if defined(POLARSSL_ARC4_C)
@@ -1227,6 +1420,11 @@ const cipher_definition_t cipher_definitions[] =
     { POLARSSL_CIPHER_CAMELLIA_192_GCM,     &camellia_192_gcm_info },
     { POLARSSL_CIPHER_CAMELLIA_256_GCM,     &camellia_256_gcm_info },
 #endif
+#if defined(POLARSSL_CCM_C)
+    { POLARSSL_CIPHER_CAMELLIA_128_CCM,     &camellia_128_ccm_info },
+    { POLARSSL_CIPHER_CAMELLIA_192_CCM,     &camellia_192_ccm_info },
+    { POLARSSL_CIPHER_CAMELLIA_256_CCM,     &camellia_256_ccm_info },
+#endif
 #endif /* POLARSSL_CAMELLIA_C */
 
 #if defined(POLARSSL_DES_C)
@@ -1250,4 +1448,4 @@ const cipher_definition_t cipher_definitions[] =
 #define NUM_CIPHERS sizeof cipher_definitions / sizeof cipher_definitions[0]
 int supported_ciphers[NUM_CIPHERS];
 
-#endif
+#endif /* POLARSSL_CIPHER_C */
index 53b8b54c3715202fe8b5cea7cacf0213afb94e18..96ee4f1625012d388cb2fd9ce4c2433ea96f08a7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_CTR_DRBG_C)
 
 #include <stdio.h>
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
  * tests to succeed (which require known length fixed entropy)
@@ -56,6 +71,8 @@ int ctr_drbg_init_entropy_len(
     memset( ctx, 0, sizeof(ctr_drbg_context) );
     memset( key, 0, CTR_DRBG_KEYSIZE );
 
+    aes_init( &ctx->aes_ctx );
+
     ctx->f_entropy = f_entropy;
     ctx->p_entropy = p_entropy;
 
@@ -83,6 +100,15 @@ int ctr_drbg_init( ctr_drbg_context *ctx,
                                        CTR_DRBG_ENTROPY_LEN ) );
 }
 
+void ctr_drbg_free( ctr_drbg_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    aes_free( &ctx->aes_ctx );
+    polarssl_zeroize( ctx, sizeof( ctr_drbg_context ) );
+}
+
 void ctr_drbg_set_prediction_resistance( ctr_drbg_context *ctx, int resistance )
 {
     ctx->prediction_resistance = resistance;
@@ -105,13 +131,14 @@ static int block_cipher_df( unsigned char *output,
     unsigned char tmp[CTR_DRBG_SEEDLEN];
     unsigned char key[CTR_DRBG_KEYSIZE];
     unsigned char chain[CTR_DRBG_BLOCKSIZE];
-    unsigned char *p = buf, *iv;
+    unsigned char *p, *iv;
     aes_context aes_ctx;
 
     int i, j;
     size_t buf_len, use_len;
 
     memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 );
+    aes_init( &aes_ctx );
 
     /*
      * Construct IV (16 bytes) and S in buffer
@@ -179,6 +206,8 @@ static int block_cipher_df( unsigned char *output,
         p += CTR_DRBG_BLOCKSIZE;
     }
 
+    aes_free( &aes_ctx );
+
     return( 0 );
 }
 
@@ -276,7 +305,7 @@ int ctr_drbg_reseed( ctr_drbg_context *ctx,
 
     return( 0 );
 }
-    
+
 int ctr_drbg_random_with_add( void *p_rng,
                               unsigned char *output, size_t output_len,
                               const unsigned char *additional, size_t add_len )
@@ -326,7 +355,8 @@ int ctr_drbg_random_with_add( void *p_rng,
          */
         aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );
 
-        use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
+        use_len = ( output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE :
+                                                       output_len;
         /*
          * Copy random block to destination
          */
@@ -410,7 +440,7 @@ int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
 
 #include <stdio.h>
 
-unsigned char entropy_source_pr[96] =
+static unsigned char entropy_source_pr[96] =
     { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
       0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
       0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
@@ -424,7 +454,7 @@ unsigned char entropy_source_pr[96] =
       0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
       0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
 
-unsigned char entropy_source_nopr[64] =
+static unsigned char entropy_source_nopr[64] =
     { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
       0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
       0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
@@ -434,32 +464,39 @@ unsigned char entropy_source_nopr[64] =
       0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
       0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
 
-unsigned char nonce_pers_pr[16] =
+static const unsigned char nonce_pers_pr[16] =
     { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
       0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
 
-unsigned char nonce_pers_nopr[16] =
+static const unsigned char nonce_pers_nopr[16] =
     { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
       0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
 
-unsigned char result_pr[16] =
+static const unsigned char result_pr[16] =
     { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
       0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
 
-unsigned char result_nopr[16] =
+static const unsigned char result_nopr[16] =
     { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
       0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
 
-int test_offset;
+static size_t test_offset;
 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
                                        size_t len )
 {
-    unsigned char *p = data;
+    const unsigned char *p = data;
     memcpy( buf, p + test_offset, len );
-    test_offset += 32;
+    test_offset += len;
     return( 0 );
 }
 
+#define CHK( c )    if( (c) != 0 )                          \
+                    {                                       \
+                        if( verbose != 0 )                  \
+                            polarssl_printf( "failed\n" );  \
+                        return( 1 );                        \
+                    }
+
 /*
  * Checkup routine
  */
@@ -472,100 +509,41 @@ int ctr_drbg_self_test( int verbose )
      * Based on a NIST CTR_DRBG test vector (PR = True)
      */
     if( verbose != 0 )
-        printf( "  CTR_DRBG (PR = TRUE) : " );
+        polarssl_printf( "  CTR_DRBG (PR = TRUE) : " );
 
     test_offset = 0;
-    if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
+    CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
+                                entropy_source_pr, nonce_pers_pr, 16, 32 ) );
     ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
+    CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
+    CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
+    CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
 
-    if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-    
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
     /*
      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
      */
     if( verbose != 0 )
-        printf( "  CTR_DRBG (PR = FALSE): " );
+        polarssl_printf( "  CTR_DRBG (PR = FALSE): " );
 
     test_offset = 0;
-    if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
+    CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
+                            entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
+    CHK( ctr_drbg_random( &ctx, buf, 16 ) );
+    CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
+    CHK( ctr_drbg_random( &ctx, buf, 16 ) );
+    CHK( memcmp( buf, result_nopr, 16 ) );
 
-        return( 1 );
-    }
-
-    if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( memcmp( buf, result_nopr, 16 ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-    
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
     if( verbose != 0 )
-            printf( "\n" );
+            polarssl_printf( "\n" );
 
     return( 0 );
 }
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_CTR_DRBG_C */
index 371cbf95cf20216e85f9d8b1f534ee669215ff8c..a81f502bfb763e2151c1d8a0b877257cac4a935e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Debugging routines
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_DEBUG_C)
 
 #endif
 #endif /* _MSC_VER */
 
+static int debug_log_mode = POLARSSL_DEBUG_DFL_MODE;
+static int debug_threshold = 0;
+
+void debug_set_log_mode( int log_mode )
+{
+    debug_log_mode = log_mode;
+}
+
+void debug_set_threshold( int threshold )
+{
+    debug_threshold = threshold;
+}
+
 char *debug_fmt( const char *format, ... )
 {
     va_list argp;
@@ -66,8 +83,14 @@ void debug_print_msg( const ssl_context *ssl, int level,
     char str[512];
     int maxlen = sizeof( str ) - 1;
 
-    if( ssl->f_dbg == NULL )
+    if( ssl->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_RAW )
+    {
+        ssl->f_dbg( ssl->p_dbg, level, text );
         return;
+    }
 
     snprintf( str, maxlen, "%s(%04d): %s\n", file, line, text );
     str[maxlen] = '\0';
@@ -80,12 +103,16 @@ void debug_print_ret( const ssl_context *ssl, int level,
 {
     char str[512];
     int maxlen = sizeof( str ) - 1;
+    size_t idx = 0;
 
-    if( ssl->f_dbg == NULL )
+    if( ssl->f_dbg == NULL || level > debug_threshold )
         return;
 
-    snprintf( str, maxlen, "%s(%04d): %s() returned %d (0x%x)\n",
-              file, line, text, ret, ret );
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+        idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    snprintf( str + idx, maxlen - idx, "%s() returned %d (-0x%04x)\n",
+              text, ret, -ret );
 
     str[maxlen] = '\0';
     ssl->f_dbg( ssl->p_dbg, level, str );
@@ -96,17 +123,21 @@ void debug_print_buf( const ssl_context *ssl, int level,
                       unsigned char *buf, size_t len )
 {
     char str[512];
-    size_t i, maxlen = sizeof( str ) - 1;
+    size_t i, maxlen = sizeof( str ) - 1, idx = 0;
 
-    if( ssl->f_dbg == NULL )
+    if( ssl->f_dbg == NULL || level > debug_threshold )
         return;
 
-    snprintf( str, maxlen, "%s(%04d): dumping '%s' (%d bytes)\n",
-              file, line, text, (unsigned int) len );
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+        idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    snprintf( str + idx, maxlen - idx, "dumping '%s' (%u bytes)\n",
+              text, (unsigned int) len );
 
     str[maxlen] = '\0';
     ssl->f_dbg( ssl->p_dbg, level, str );
 
+    idx = 0;
     for( i = 0; i < len; i++ )
     {
         if( i >= 4096 )
@@ -115,23 +146,29 @@ void debug_print_buf( const ssl_context *ssl, int level,
         if( i % 16 == 0 )
         {
             if( i > 0 )
-                ssl->f_dbg( ssl->p_dbg, level, "\n" );
+            {
+                snprintf( str + idx, maxlen - idx, "\n" );
+                ssl->f_dbg( ssl->p_dbg, level, str );
+                idx = 0;
+            }
 
-            snprintf( str, maxlen, "%s(%04d): %04x: ", file, line,
-                      (unsigned int) i );
+            if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+                idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
 
-            str[maxlen] = '\0';
-            ssl->f_dbg( ssl->p_dbg, level, str );
-        }
+            idx += snprintf( str + idx, maxlen - idx, "%04x: ",
+                             (unsigned int) i );
 
-        snprintf( str, maxlen, " %02x", (unsigned int) buf[i] );
+        }
 
-        str[maxlen] = '\0';
-        ssl->f_dbg( ssl->p_dbg, level, str );
+        idx += snprintf( str + idx, maxlen - idx, " %02x",
+                         (unsigned int) buf[i] );
     }
 
     if( len > 0 )
-        ssl->f_dbg( ssl->p_dbg, level, "\n" );
+    {
+        snprintf( str + idx, maxlen - idx, "\n" );
+        ssl->f_dbg( ssl->p_dbg, level, str );
+    }
 }
 
 #if defined(POLARSSL_ECP_C)
@@ -142,6 +179,9 @@ void debug_print_ecp( const ssl_context *ssl, int level,
     char str[512];
     int maxlen = sizeof( str ) - 1;
 
+    if( ssl->f_dbg == NULL || level > debug_threshold )
+        return;
+
     snprintf( str, maxlen, "%s(X)", text );
     str[maxlen] = '\0';
     debug_print_mpi( ssl, level, file, line, str, &X->X );
@@ -149,10 +189,6 @@ void debug_print_ecp( const ssl_context *ssl, int level,
     snprintf( str, maxlen, "%s(Y)", text );
     str[maxlen] = '\0';
     debug_print_mpi( ssl, level, file, line, str, &X->Y );
-
-    snprintf( str, maxlen, "%s(Z)", text );
-    str[maxlen] = '\0';
-    debug_print_mpi( ssl, level, file, line, str, &X->Z );
 }
 #endif /* POLARSSL_ECP_C */
 
@@ -163,9 +199,9 @@ void debug_print_mpi( const ssl_context *ssl, int level,
 {
     char str[512];
     int j, k, maxlen = sizeof( str ) - 1, zeros = 1;
-    size_t i, n;
+    size_t i, n, idx = 0;
 
-    if( ssl->f_dbg == NULL || X == NULL )
+    if( ssl->f_dbg == NULL || X == NULL || level > debug_threshold )
         return;
 
     for( n = X->n - 1; n > 0; n-- )
@@ -176,13 +212,16 @@ void debug_print_mpi( const ssl_context *ssl, int level,
         if( ( ( X->p[n] >> j ) & 1 ) != 0 )
             break;
 
-    snprintf( str, maxlen, "%s(%04d): value of '%s' (%d bits) is:\n",
-              file, line, text, 
-              (int) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) );
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+        idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+    snprintf( str + idx, maxlen - idx, "value of '%s' (%d bits) is:\n",
+              text, (int) ( ( n * ( sizeof(t_uint) << 3 ) ) + j + 1 ) );
 
     str[maxlen] = '\0';
     ssl->f_dbg( ssl->p_dbg, level, str );
 
+    idx = 0;
     for( i = n + 1, j = 0; i > 0; i-- )
     {
         if( zeros && X->p[i - 1] == 0 )
@@ -190,7 +229,7 @@ void debug_print_mpi( const ssl_context *ssl, int level,
 
         for( k = sizeof( t_uint ) - 1; k >= 0; k-- )
         {
-            if( zeros && ( ( X->p[i - 1] >> (k << 3) ) & 0xFF ) == 0 )
+            if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
                 continue;
             else
                 zeros = 0;
@@ -198,19 +237,18 @@ void debug_print_mpi( const ssl_context *ssl, int level,
             if( j % 16 == 0 )
             {
                 if( j > 0 )
-                    ssl->f_dbg( ssl->p_dbg, level, "\n" );
-
-                snprintf( str, maxlen, "%s(%04d): ", file, line );
-
-                str[maxlen] = '\0';
-                ssl->f_dbg( ssl->p_dbg, level, str );
+                {
+                    snprintf( str + idx, maxlen - idx, "\n" );
+                    ssl->f_dbg( ssl->p_dbg, level, str );
+                    idx = 0;
+                }
+
+                if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+                    idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
             }
 
-            snprintf( str, maxlen, " %02x", (unsigned int)
-                      ( X->p[i - 1] >> (k << 3) ) & 0xFF );
-
-            str[maxlen] = '\0';
-            ssl->f_dbg( ssl->p_dbg, level, str );
+            idx += snprintf( str + idx, maxlen - idx, " %02x", (unsigned int)
+                             ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
 
             j++;
         }
@@ -219,14 +257,16 @@ void debug_print_mpi( const ssl_context *ssl, int level,
 
     if( zeros == 1 )
     {
-        snprintf( str, maxlen, "%s(%04d): ", file, line );
+        if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+        {
+            idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
 
-        str[maxlen] = '\0';
-        ssl->f_dbg( ssl->p_dbg, level, str );
-        ssl->f_dbg( ssl->p_dbg, level, " 00" );
+        }
+        idx += snprintf( str + idx, maxlen - idx, " 00" );
     }
 
-    ssl->f_dbg( ssl->p_dbg, level, "\n" );
+    snprintf( str + idx, maxlen - idx, "\n" );
+    ssl->f_dbg( ssl->p_dbg, level, str );
 }
 #endif /* POLARSSL_BIGNUM_C */
 
@@ -247,7 +287,7 @@ static void debug_print_pk( const ssl_context *ssl, int level,
         return;
     }
 
-    for( i = 0; i < sizeof( items ); i++ )
+    for( i = 0; i < POLARSSL_PK_DEBUG_MAX_ITEMS; i++ )
     {
         if( items[i].type == POLARSSL_PK_DEBUG_NONE )
             return;
@@ -272,13 +312,19 @@ void debug_print_crt( const ssl_context *ssl, int level,
                       const char *text, const x509_crt *crt )
 {
     char str[1024], prefix[64];
-    int i = 0, maxlen = sizeof( prefix ) - 1;
+    int i = 0, maxlen = sizeof( prefix ) - 1, idx = 0;
 
-    if( ssl->f_dbg == NULL || crt == NULL )
+    if( ssl->f_dbg == NULL || crt == NULL || level > debug_threshold )
         return;
 
-    snprintf( prefix, maxlen, "%s(%04d): ", file, line );
-    prefix[maxlen] = '\0';
+    if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+    {
+        snprintf( prefix, maxlen, "%s(%04d): ", file, line );
+        prefix[maxlen] = '\0';
+    }
+    else
+        prefix[0] = '\0';
+
     maxlen = sizeof( str ) - 1;
 
     while( crt != NULL )
@@ -286,8 +332,11 @@ void debug_print_crt( const ssl_context *ssl, int level,
         char buf[1024];
         x509_crt_info( buf, sizeof( buf ) - 1, prefix, crt );
 
-        snprintf( str, maxlen, "%s(%04d): %s #%d:\n%s",
-                  file, line, text, ++i, buf );
+        if( debug_log_mode == POLARSSL_DEBUG_LOG_FULL )
+            idx = snprintf( str, maxlen, "%s(%04d): ", file, line );
+
+        snprintf( str + idx, maxlen - idx, "%s #%d:\n%s",
+                  text, ++i, buf );
 
         str[maxlen] = '\0';
         ssl->f_dbg( ssl->p_dbg, level, str );
@@ -299,4 +348,4 @@ void debug_print_crt( const ssl_context *ssl, int level,
 }
 #endif /* POLARSSL_X509_CRT_PARSE_C */
 
-#endif
+#endif /* POLARSSL_DEBUG_C */
index 153810d7275b2513d5257ccc7bdfc3c85a025294..12fe4f46a66faa7533463a26d1d4c686f2a2394f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  FIPS-46-3 compliant Triple-DES implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_DES_C)
 
 #include "polarssl/des.h"
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
 #if !defined(POLARSSL_DES_ALT)
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -290,6 +305,32 @@ static const uint32_t RHs[16] =
 
 #define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
 
+void des_init( des_context *ctx )
+{
+    memset( ctx, 0, sizeof( des_context ) );
+}
+
+void des_free( des_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( des_context ) );
+}
+
+void des3_init( des3_context *ctx )
+{
+    memset( ctx, 0, sizeof( des3_context ) );
+}
+
+void des3_free( des3_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( des3_context ) );
+}
+
 static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
         11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
         47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
@@ -317,7 +358,7 @@ int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
     int i;
 
     for( i = 0; i < DES_KEY_SIZE; i++ )
-        if ( key[i] != odd_parity_table[key[i] / 2] )
+        if( key[i] != odd_parity_table[key[i] / 2] )
             return( 1 );
 
     return( 0 );
@@ -372,7 +413,7 @@ int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
     int i;
 
     for( i = 0; i < WEAK_KEY_COUNT; i++ )
-        if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0)
+        if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0 )
             return( 1 );
 
     return( 0 );
@@ -503,12 +544,13 @@ static void des3_set2key( uint32_t esk[96],
 /*
  * Triple-DES key schedule (112-bit, encryption)
  */
-int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
+int des3_set2key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] )
 {
     uint32_t sk[96];
 
     des3_set2key( ctx->sk, sk, key );
-    memset( sk,  0, sizeof( sk ) );
+    polarssl_zeroize( sk,  sizeof( sk ) );
 
     return( 0 );
 }
@@ -516,12 +558,13 @@ int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE *
 /*
  * Triple-DES key schedule (112-bit, decryption)
  */
-int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
+int des3_set2key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 2] )
 {
     uint32_t sk[96];
 
     des3_set2key( sk, ctx->sk, key );
-    memset( sk,  0, sizeof( sk ) );
+    polarssl_zeroize( sk,  sizeof( sk ) );
 
     return( 0 );
 }
@@ -552,12 +595,13 @@ static void des3_set3key( uint32_t esk[96],
 /*
  * Triple-DES key schedule (168-bit, encryption)
  */
-int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
+int des3_set3key_enc( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] )
 {
     uint32_t sk[96];
 
     des3_set3key( ctx->sk, sk, key );
-    memset( sk, 0, sizeof( sk ) );
+    polarssl_zeroize( sk,  sizeof( sk ) );
 
     return( 0 );
 }
@@ -565,12 +609,13 @@ int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE *
 /*
  * Triple-DES key schedule (168-bit, decryption)
  */
-int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
+int des3_set3key_dec( des3_context *ctx,
+                      const unsigned char key[DES_KEY_SIZE * 3] )
 {
     uint32_t sk[96];
 
     des3_set3key( sk, ctx->sk, key );
-    memset( sk, 0, sizeof( sk ) );
+    polarssl_zeroize( sk,  sizeof( sk ) );
 
     return( 0 );
 }
@@ -775,11 +820,6 @@ static const unsigned char des3_test_keys[24] =
     0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
 };
 
-static const unsigned char des3_test_iv[8] =
-{
-    0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
-};
-
 static const unsigned char des3_test_buf[8] =
 {
     0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
@@ -799,6 +839,12 @@ static const unsigned char des3_test_ecb_enc[3][8] =
     { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
 };
 
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+static const unsigned char des3_test_iv[8] =
+{
+    0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
 static const unsigned char des3_test_cbc_dec[3][8] =
 {
     { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
@@ -812,24 +858,24 @@ static const unsigned char des3_test_cbc_enc[3][8] =
     { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
     { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
 };
+#endif /* POLARSSL_CIPHER_MODE_CBC */
 
 /*
  * Checkup routine
  */
 int des_self_test( int verbose )
 {
-    int i, j, u, v;
+    int i, j, u, v, ret = 0;
     des_context ctx;
     des3_context ctx3;
-    unsigned char key[24];
     unsigned char buf[8];
 #if defined(POLARSSL_CIPHER_MODE_CBC)
     unsigned char prv[8];
     unsigned char iv[8];
 #endif
 
-    memset( key, 0, 24 );
-
+    des_init( &ctx );
+    des3_init( &ctx3 );
     /*
      * ECB mode
      */
@@ -839,9 +885,9 @@ int des_self_test( int verbose )
         v = i  & 1;
 
         if( verbose != 0 )
-            printf( "  DES%c-ECB-%3d (%s): ",
-                    ( u == 0 ) ? ' ' : '3', 56 + u * 56,
-                    ( v == DES_DECRYPT ) ? "dec" : "enc" );
+            polarssl_printf( "  DES%c-ECB-%3d (%s): ",
+                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                             ( v == DES_DECRYPT ) ? "dec" : "enc" );
 
         memcpy( buf, des3_test_buf, 8 );
 
@@ -889,17 +935,18 @@ int des_self_test( int verbose )
                 memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
 #if defined(POLARSSL_CIPHER_MODE_CBC)
     /*
@@ -911,9 +958,9 @@ int des_self_test( int verbose )
         v = i  & 1;
 
         if( verbose != 0 )
-            printf( "  DES%c-CBC-%3d (%s): ",
-                    ( u == 0 ) ? ' ' : '3', 56 + u * 56,
-                    ( v == DES_DECRYPT ) ? "dec" : "enc" );
+            polarssl_printf( "  DES%c-CBC-%3d (%s): ",
+                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                             ( v == DES_DECRYPT ) ? "dec" : "enc" );
 
         memcpy( iv,  des3_test_iv,  8 );
         memcpy( prv, des3_test_iv,  8 );
@@ -984,22 +1031,27 @@ int des_self_test( int verbose )
                 memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
-    return( 0 );
+exit:
+    des_free( &ctx );
+    des3_free( &ctx3 );
+
+    return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_DES_C */
index e8aa8191c0f74613c59337ef56cedb717782514e..089c11b3d953152ec650d46158cd128188bc2b35 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Diffie-Hellman-Merkle key exchange
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_DHM_C)
 
 #include "polarssl/asn1.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #include <stdlib.h>
+#define polarssl_printf     printf
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * helper to validate the mpi size and import it
  */
@@ -91,8 +101,9 @@ static int dhm_check_range( const mpi *param, const mpi *P )
     int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA;
 
     mpi_init( &L ); mpi_init( &U );
-    mpi_lset( &L, 2 );
-    mpi_sub_int( &U, P, 2 );
+
+    MPI_CHK( mpi_lset( &L, 2 ) );
+    MPI_CHK( mpi_sub_int( &U, P, 2 ) );
 
     if( mpi_cmp_mpi( param, &L ) >= 0 &&
         mpi_cmp_mpi( param, &U ) <= 0 )
@@ -100,11 +111,16 @@ static int dhm_check_range( const mpi *param, const mpi *P )
         ret = 0;
     }
 
+cleanup:
     mpi_free( &L ); mpi_free( &U );
-
     return( ret );
 }
 
+void dhm_init( dhm_context *ctx )
+{
+    memset( ctx, 0, sizeof( dhm_context ) );
+}
+
 /*
  * Parse the ServerKeyExchange parameters
  */
@@ -114,8 +130,6 @@ int dhm_read_params( dhm_context *ctx,
 {
     int ret;
 
-    dhm_free( ctx );
-
     if( ( ret = dhm_read_bignum( &ctx->P,  p, end ) ) != 0 ||
         ( ret = dhm_read_bignum( &ctx->G,  p, end ) ) != 0 ||
         ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
@@ -152,7 +166,7 @@ int dhm_make_params( dhm_context *ctx, int x_size,
         mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
 
         while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
-            mpi_shift_r( &ctx->X, 1 );
+            MPI_CHK( mpi_shift_r( &ctx->X, 1 ) );
 
         if( count++ > 10 )
             return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED );
@@ -238,7 +252,7 @@ int dhm_make_public( dhm_context *ctx, int x_size,
         mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
 
         while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
-            mpi_shift_r( &ctx->X, 1 );
+            MPI_CHK( mpi_shift_r( &ctx->X, 1 ) );
 
         if( count++ > 10 )
             return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED );
@@ -311,7 +325,7 @@ static int dhm_update_blinding( dhm_context *ctx,
         mpi_fill_random( &ctx->Vi, mpi_size( &ctx->P ), f_rng, p_rng );
 
         while( mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
-            mpi_shift_r( &ctx->Vi, 1 );
+            MPI_CHK( mpi_shift_r( &ctx->Vi, 1 ) );
 
         if( count++ > 10 )
             return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
@@ -389,14 +403,15 @@ void dhm_free( dhm_context *ctx )
     mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
     mpi_free( &ctx->P );
 
-    memset( ctx, 0, sizeof( dhm_context ) );
+    polarssl_zeroize( ctx, sizeof( dhm_context ) );
 }
 
 #if defined(POLARSSL_ASN1_PARSE_C)
 /*
  * Parse DHM parameters
  */
-int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
+int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin,
+                   size_t dhminlen )
 {
     int ret;
     size_t len;
@@ -405,7 +420,6 @@ int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen
     pem_context pem;
 
     pem_init( &pem );
-    memset( dhm, 0, sizeof( dhm_context ) );
 
     ret = pem_read_buffer( &pem,
                            "-----BEGIN DH PARAMETERS-----",
@@ -425,7 +439,7 @@ int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen
     p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
 #else
     p = (unsigned char *) dhmin;
-#endif
+#endif /* POLARSSL_PEM_PARSE_C */
     end = p + dhminlen;
 
     /*
@@ -459,6 +473,8 @@ int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen
 
     ret = 0;
 
+    dhm->len = mpi_size( &dhm->P );
+
 exit:
 #if defined(POLARSSL_PEM_PARSE_C)
     pem_free( &pem );
@@ -521,12 +537,12 @@ int dhm_parse_dhmfile( dhm_context *dhm, const char *path )
     size_t n;
     unsigned char *buf;
 
-    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
+    if( ( ret = load_file( path, &buf, &n ) ) != 0 )
         return( ret );
 
     ret = dhm_parse_dhm( dhm, buf, n );
 
-    memset( buf, 0, n + 1 );
+    polarssl_zeroize( buf, n + 1 );
     polarssl_free( buf );
 
     return( ret );
@@ -547,30 +563,36 @@ int dhm_self_test( int verbose )
     int ret;
     dhm_context dhm;
 
+    dhm_init( &dhm );
+
     if( verbose != 0 )
-        printf( "  DHM parameter load: " );
+        polarssl_printf( "  DHM parameter load: " );
 
     if( ( ret = dhm_parse_dhm( &dhm, (const unsigned char *) test_dhm_params,
                                strlen( test_dhm_params ) ) ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
-        return( ret );
+        ret = 1;
+        goto exit;
     }
 
     if( verbose != 0 )
-        printf( "passed\n\n" );
+        polarssl_printf( "passed\n\n" );
 
+exit:
     dhm_free( &dhm );
 
-    return( 0 );
+    return( ret );
 #else
-    ((void) verbose);
-    return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-#endif
+    if( verbose != 0 )
+        polarssl_printf( "  DHM parameter load: skipped\n" );
+
+    return( 0 );
+#endif /* POLARSSL_CERTS_C */
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_DHM_C */
index 400e45fa2e13fe9529d88ed53d475e538a50a921..b93d82ec6bddca04cc0b80a6c639265045f754aa 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Elliptic curve Diffie-Hellman
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  * RFC 4492
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_ECDH_C)
 
@@ -97,13 +101,13 @@ void ecdh_free( ecdh_context *ctx )
         return;
 
     ecp_group_free( &ctx->grp );
-    mpi_free      ( &ctx->d   );
     ecp_point_free( &ctx->Q   );
     ecp_point_free( &ctx->Qp  );
-    mpi_free      ( &ctx->z   );
     ecp_point_free( &ctx->Vi  );
     ecp_point_free( &ctx->Vf  );
-    mpi_free      ( &ctx->_d  );
+    mpi_free( &ctx->d  );
+    mpi_free( &ctx->z  );
+    mpi_free( &ctx->_d );
 }
 
 /*
@@ -140,7 +144,7 @@ int ecdh_make_params( ecdh_context *ctx, size_t *olen,
         return( ret );
 
     *olen = grp_len + pt_len;
-    return 0;
+    return( 0 );
 }
 
 /*
@@ -162,7 +166,33 @@ int ecdh_read_params( ecdh_context *ctx,
                 != 0 )
         return( ret );
 
-    return 0;
+    return( 0 );
+}
+
+/*
+ * Get parameters from a keypair
+ */
+int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key,
+                     ecdh_side side )
+{
+    int ret;
+
+    if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
+        return( ret );
+
+    /* If it's not our key, just import the public part as Qp */
+    if( side == POLARSSL_ECDH_THEIRS )
+        return( ecp_copy( &ctx->Qp, &key->Q ) );
+
+    /* Our key: import public (as Q) and private parts */
+    if( side != POLARSSL_ECDH_OURS )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
+        ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 )
+        return( ret );
+
+    return( 0 );
 }
 
 /*
@@ -192,10 +222,19 @@ int ecdh_make_public( ecdh_context *ctx, size_t *olen,
 int ecdh_read_public( ecdh_context *ctx,
                       const unsigned char *buf, size_t blen )
 {
+    int ret;
+    const unsigned char *p = buf;
+
     if( ctx == NULL )
         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
-    return ecp_tls_read_point( &ctx->grp, &ctx->Qp, &buf, blen );
+    if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 )
+        return( ret );
+
+    if( (size_t)( p - buf ) != blen )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    return( 0 );
 }
 
 /*
@@ -220,7 +259,7 @@ int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
     if( mpi_size( &ctx->z ) > blen )
         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
-    *olen = ctx->grp.nbits / 8 + ( ( ctx->grp.nbits % 8 ) != 0 );
+    *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
     return mpi_write_binary( &ctx->z, buf, *olen );
 }
 
@@ -232,9 +271,10 @@ int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
  */
 int ecdh_self_test( int verbose )
 {
-    return( verbose++ );
+    ((void) verbose );
+    return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif /* defined(POLARSSL_ECDH_C) */
+#endif /* POLARSSL_ECDH_C */
index 13f394bc89d16f0c89bcf1418f21f0a754c6589c..5af7f6b53e14273cf6aeec04f7653c41bdd63b67 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Elliptic curve DSA
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_ECDSA_C)
 
 #include "polarssl/ecdsa.h"
 #include "polarssl/asn1write.h"
 
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+#include "polarssl/hmac_drbg.h"
+#endif
+
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/*
+ * This a hopefully temporary compatibility function.
+ *
+ * Since we can't ensure the caller will pass a valid md_alg before the next
+ * interface change, try to pick up a decent md by size.
+ *
+ * Argument is the minimum size in bytes of the MD output.
+ */
+static const md_info_t *md_info_by_size( size_t min_size )
+{
+    const md_info_t *md_cur, *md_picked = NULL;
+    const int *md_alg;
+
+    for( md_alg = md_list(); *md_alg != 0; md_alg++ )
+    {
+        if( ( md_cur = md_info_from_type( *md_alg ) ) == NULL ||
+            (size_t) md_cur->size < min_size ||
+            ( md_picked != NULL && md_cur->size > md_picked->size ) )
+            continue;
+
+        md_picked = md_cur;
+    }
+
+    return( md_picked );
+}
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
 /*
  * Derive a suitable integer for group grp from a buffer of length len
  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
 static int derive_mpi( const ecp_group *grp, mpi *x,
                        const unsigned char *buf, size_t blen )
 {
-    size_t n_size = (grp->nbits + 7) / 8;
-    return( mpi_read_binary( x, buf, blen > n_size ? n_size : blen ) );
+    int ret;
+    size_t n_size = ( grp->nbits + 7 ) / 8;
+    size_t use_size = blen > n_size ? n_size : blen;
+
+    MPI_CHK( mpi_read_binary( x, buf, use_size ) );
+    if( use_size * 8 > grp->nbits )
+        MPI_CHK( mpi_shift_r( x, use_size * 8 - grp->nbits ) );
+
+    /* While at it, reduce modulo N */
+    if( mpi_cmp_mpi( x, &grp->N ) >= 0 )
+        MPI_CHK( mpi_sub_mpi( x, x, &grp->N ) );
+
+cleanup:
+    return( ret );
 }
 
 /*
@@ -55,13 +103,16 @@ int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s,
                 const mpi *d, const unsigned char *buf, size_t blen,
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
-    int ret, key_tries, sign_tries;
+    int ret, key_tries, sign_tries, blind_tries;
     ecp_point R;
-    mpi k, e;
+    mpi k, e, t;
+
+    /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
+    if( grp->N.p == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
     ecp_point_init( &R );
-    mpi_init( &k );
-    mpi_init( &e );
+    mpi_init( &k ); mpi_init( &e ); mpi_init( &t );
 
     sign_tries = 0;
     do
@@ -90,10 +141,30 @@ int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s,
         MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
 
         /*
-         * Step 6: compute s = (e + r * d) / k mod n
+         * Generate a random value to blind inv_mod in next step,
+         * avoiding a potential timing leak.
+         */
+        blind_tries = 0;
+        do
+        {
+            size_t n_size = ( grp->nbits + 7 ) / 8;
+            MPI_CHK( mpi_fill_random( &t, n_size, f_rng, p_rng ) );
+            MPI_CHK( mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
+
+            /* See ecp_gen_keypair() */
+            if( ++blind_tries > 30 )
+                return( POLARSSL_ERR_ECP_RANDOM_FAILED );
+        }
+        while( mpi_cmp_int( &t, 1 ) < 0 ||
+               mpi_cmp_mpi( &t, &grp->N ) >= 0 );
+
+        /*
+         * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
          */
         MPI_CHK( mpi_mul_mpi( s, r, d ) );
         MPI_CHK( mpi_add_mpi( &e, &e, s ) );
+        MPI_CHK( mpi_mul_mpi( &e, &e, &t ) );
+        MPI_CHK( mpi_mul_mpi( &k, &k, &t ) );
         MPI_CHK( mpi_inv_mod( s, &k, &grp->N ) );
         MPI_CHK( mpi_mul_mpi( s, s, &e ) );
         MPI_CHK( mpi_mod_mpi( s, s, &grp->N ) );
@@ -108,12 +179,55 @@ int ecdsa_sign( ecp_group *grp, mpi *r, mpi *s,
 
 cleanup:
     ecp_point_free( &R );
-    mpi_free( &k );
-    mpi_free( &e );
+    mpi_free( &k ); mpi_free( &e ); mpi_free( &t );
 
     return( ret );
 }
 
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/*
+ * Deterministic signature wrapper
+ */
+int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s,
+                    const mpi *d, const unsigned char *buf, size_t blen,
+                    md_type_t md_alg )
+{
+    int ret;
+    hmac_drbg_context rng_ctx;
+    unsigned char data[2 * POLARSSL_ECP_MAX_BYTES];
+    size_t grp_len = ( grp->nbits + 7 ) / 8;
+    const md_info_t *md_info;
+    mpi h;
+
+    /* Temporary fallback */
+    if( md_alg == POLARSSL_MD_NONE )
+        md_info = md_info_by_size( blen );
+    else
+        md_info = md_info_from_type( md_alg );
+
+    if( md_info == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    mpi_init( &h );
+    memset( &rng_ctx, 0, sizeof( hmac_drbg_context ) );
+
+    /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
+    MPI_CHK( mpi_write_binary( d, data, grp_len ) );
+    MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
+    MPI_CHK( mpi_write_binary( &h, data + grp_len, grp_len ) );
+    hmac_drbg_init_buf( &rng_ctx, md_info, data, 2 * grp_len );
+
+    ret = ecdsa_sign( grp, r, s, d, buf, blen,
+                      hmac_drbg_random, &rng_ctx );
+
+cleanup:
+    hmac_drbg_free( &rng_ctx );
+    mpi_free( &h );
+
+    return( ret );
+}
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+
 /*
  * Verify ECDSA signature of hashed message (SEC1 4.1.4)
  * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
@@ -129,6 +243,10 @@ int ecdsa_verify( ecp_group *grp,
     ecp_point_init( &R ); ecp_point_init( &P );
     mpi_init( &e ); mpi_init( &s_inv ); mpi_init( &u1 ); mpi_init( &u2 );
 
+    /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
+    if( grp->N.p == NULL )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
     /*
      * Step 1: make sure r and s are in range 1..n-1
      */
@@ -217,6 +335,30 @@ cleanup:
 #endif
 #define MAX_SIG_LEN ( 3 + 2 * ( 2 + POLARSSL_ECP_MAX_BYTES ) )
 
+/*
+ * Convert a signature (given by context) to ASN.1
+ */
+static int ecdsa_signature_to_asn1( ecdsa_context *ctx,
+                                    unsigned char *sig, size_t *slen )
+{
+    int ret;
+    unsigned char buf[MAX_SIG_LEN];
+    unsigned char *p = buf + sizeof( buf );
+    size_t len = 0;
+
+    ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->s ) );
+    ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->r ) );
+
+    ASN1_CHK_ADD( len, asn1_write_len( &p, buf, len ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &p, buf,
+                                       ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+
+    memcpy( sig, p, len );
+    *slen = len;
+
+    return( 0 );
+}
+
 /*
  * Compute and write signature
  */
@@ -227,9 +369,6 @@ int ecdsa_write_signature( ecdsa_context *ctx,
                            void *p_rng )
 {
     int ret;
-    unsigned char buf[MAX_SIG_LEN];
-    unsigned char *p = buf + sizeof( buf );
-    size_t len = 0;
 
     if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d,
                             hash, hlen, f_rng, p_rng ) ) != 0 )
@@ -237,18 +376,29 @@ int ecdsa_write_signature( ecdsa_context *ctx,
         return( ret );
     }
 
-    ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->s ) );
-    ASN1_CHK_ADD( len, asn1_write_mpi( &p, buf, &ctx->r ) );
+    return( ecdsa_signature_to_asn1( ctx, sig, slen ) );
+}
 
-    ASN1_CHK_ADD( len, asn1_write_len( &p, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &p, buf,
-                                       ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+/*
+ * Compute and write signature deterministically
+ */
+int ecdsa_write_signature_det( ecdsa_context *ctx,
+                               const unsigned char *hash, size_t hlen,
+                               unsigned char *sig, size_t *slen,
+                               md_type_t md_alg )
+{
+    int ret;
 
-    memcpy( sig, p, len );
-    *slen = len;
+    if( ( ret = ecdsa_sign_det( &ctx->grp, &ctx->r, &ctx->s, &ctx->d,
+                                hash, hlen, md_alg ) ) != 0 )
+    {
+        return( ret );
+    }
 
-    return( 0 );
+    return( ecdsa_signature_to_asn1( ctx, sig, slen ) );
 }
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
 
 /*
  * Read and check signature
@@ -276,11 +426,14 @@ int ecdsa_read_signature( ecdsa_context *ctx,
         ( ret = asn1_get_mpi( &p, end, &ctx->s ) ) != 0 )
         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret );
 
+    if( ( ret = ecdsa_verify( &ctx->grp, hash, hlen,
+                              &ctx->Q, &ctx->r, &ctx->s ) ) != 0 )
+        return( ret );
+
     if( p != end )
-        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+        return( POLARSSL_ERR_ECP_SIG_LEN_MISMATCH );
 
-    return( ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &ctx->r, &ctx->s ) );
+    return( 0 );
 }
 
 /*
@@ -341,9 +494,10 @@ void ecdsa_free( ecdsa_context *ctx )
  */
 int ecdsa_self_test( int verbose )
 {
-    return( verbose++ );
+    ((void) verbose );
+    return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif /* defined(POLARSSL_ECDSA_C) */
+#endif /* POLARSSL_ECDSA_C */
index 3a075c40368d2fda43b2c9178a22db57da131a9c..afa795525d0bbfce883d6f6feedef349be460b18 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  Elliptic curves over GF(p)
+ *  Elliptic curves over GF(p): generic functions
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
  * RFC 4492 for the related TLS structures and constants
  *
- * [1] OKEYA, Katsuyuki and TAKAGI, Tsuyoshi. The width-w NAF method provides
- *     small memory and fast elliptic scalar multiplications secure against
- *     side channel attacks. In : Topics in Cryptology—CT-RSA 2003. Springer
- *     Berlin Heidelberg, 2003. p. 328-343.
- *     <http://rd.springer.com/chapter/10.1007/3-540-36563-X_23>.
+ * [M255] http://cr.yp.to/ecdh/curve25519-20060209.pdf
  *
  * [2] CORON, Jean-Sébastien. Resistance against differential power analysis
  *     for elliptic curve cryptosystems. In : Cryptographic Hardware and
  *     Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
  *     <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
+ *
+ * [3] HEDABOU, Mustapha, PINEL, Pierre, et BÉNÉTEAU, Lucien. A comb method to
+ *     render ECC resistant against Side Channel Attacks. IACR Cryptology
+ *     ePrint Archive, 2004, vol. 2004, p. 342.
+ *     <http://eprint.iacr.org/2004/342.pdf>
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_ECP_C)
 
 #include "polarssl/ecp.h"
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
+#define polarssl_printf     printf
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #endif
 
-#include <limits.h>
 #include <stdlib.h>
 
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
 #if defined(_MSC_VER) && !defined(inline)
 #define inline _inline
 #else
 #endif /* __ARMCC_VERSION */
 #endif /*_MSC_VER */
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if defined(POLARSSL_SELF_TEST)
 /*
- * Counts of point addition and doubling operations.
+ * Counts of point addition and doubling, and field multiplications.
  * Used to test resistance of point multiplication to simple timing attacks.
  */
-unsigned long add_count, dbl_count;
+static unsigned long add_count, dbl_count, mul_count;
+#endif
+
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP384R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP521R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_BP256R1_ENABLED)   ||   \
+    defined(POLARSSL_ECP_DP_BP384R1_ENABLED)   ||   \
+    defined(POLARSSL_ECP_DP_BP512R1_ENABLED)   ||   \
+    defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+#define POLARSSL_ECP_SHORT_WEIERSTRASS
+#endif
+
+#if defined(POLARSSL_ECP_DP_M221_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_M255_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_M383_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_M511_ENABLED)
+#define POLARSSL_ECP_MONTGOMERY
 #endif
 
+/*
+ * Curve types: internal for now, might be exposed later
+ */
+typedef enum
+{
+    POLARSSL_ECP_TYPE_NONE = 0,
+    POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS,    /* y^2 = x^3 + a x + b      */
+    POLARSSL_ECP_TYPE_MONTGOMERY,           /* y^2 = x^3 + a x^2 + x    */
+} ecp_curve_type;
+
 /*
  * List of supported curves:
  *  - internal ID
  *  - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
  *  - size in bits
  *  - readable name
+ *
+ * Curves are listed in order: largest curves first, and for a given size,
+ * fastest curves first. This provides the default order for the SSL module.
  */
-const ecp_curve_info ecp_supported_curves[] =
+static const ecp_curve_info ecp_supported_curves[] =
 {
-#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
-    { POLARSSL_ECP_DP_BP512R1,      28,     512,    "brainpool512r1"    },
-#endif
-#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
-    { POLARSSL_ECP_DP_BP384R1,      27,     384,    "brainpool384r1"    },
-#endif
-#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
-    { POLARSSL_ECP_DP_BP256R1,      26,     256,    "brainpool256r1"    },
-#endif
 #if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
     { POLARSSL_ECP_DP_SECP521R1,    25,     521,    "secp521r1"         },
 #endif
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+    { POLARSSL_ECP_DP_BP512R1,      28,     512,    "brainpoolP512r1"   },
+#endif
 #if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
     { POLARSSL_ECP_DP_SECP384R1,    24,     384,    "secp384r1"         },
 #endif
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+    { POLARSSL_ECP_DP_BP384R1,      27,     384,    "brainpoolP384r1"   },
+#endif
 #if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
     { POLARSSL_ECP_DP_SECP256R1,    23,     256,    "secp256r1"         },
 #endif
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+    { POLARSSL_ECP_DP_SECP256K1,    22,     256,    "secp256k1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+    { POLARSSL_ECP_DP_BP256R1,      26,     256,    "brainpoolP256r1"   },
+#endif
 #if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
     { POLARSSL_ECP_DP_SECP224R1,    21,     224,    "secp224r1"         },
 #endif
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+    { POLARSSL_ECP_DP_SECP224K1,    20,     224,    "secp224k1"         },
+#endif
 #if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
     { POLARSSL_ECP_DP_SECP192R1,    19,     192,    "secp192r1"         },
+#endif
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+    { POLARSSL_ECP_DP_SECP192K1,    18,     192,    "secp192k1"         },
 #endif
     { POLARSSL_ECP_DP_NONE,          0,     0,      NULL                },
 };
 
+#define ECP_NB_CURVES   sizeof( ecp_supported_curves ) /    \
+                        sizeof( ecp_supported_curves[0] )
+
+static ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
+
 /*
  * List of supported curves and associated info
  */
 const ecp_curve_info *ecp_curve_list( void )
 {
-    return ecp_supported_curves;
+    return( ecp_supported_curves );
+}
+
+/*
+ * List of supported curves, group ID only
+ */
+const ecp_group_id *ecp_grp_id_list( void )
+{
+    static int init_done = 0;
+
+    if( ! init_done )
+    {
+        size_t i = 0;
+        const ecp_curve_info *curve_info;
+
+        for( curve_info = ecp_curve_list();
+             curve_info->grp_id != POLARSSL_ECP_DP_NONE;
+             curve_info++ )
+        {
+            ecp_supported_grp_id[i++] = curve_info->grp_id;
+        }
+        ecp_supported_grp_id[i] = POLARSSL_ECP_DP_NONE;
+
+        init_done = 1;
+    }
+
+    return( ecp_supported_grp_id );
 }
 
 /*
- * Get the curve info for the internal identifer
+ * Get the curve info for the internal identifier
  */
 const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id )
 {
@@ -155,6 +244,38 @@ const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id )
     return( NULL );
 }
 
+/*
+ * Get the curve info from the name
+ */
+const ecp_curve_info *ecp_curve_info_from_name( const char *name )
+{
+    const ecp_curve_info *curve_info;
+
+    for( curve_info = ecp_curve_list();
+         curve_info->grp_id != POLARSSL_ECP_DP_NONE;
+         curve_info++ )
+    {
+        if( strcasecmp( curve_info->name, name ) == 0 )
+            return( curve_info );
+    }
+
+    return( NULL );
+}
+
+/*
+ * Get the type of a curve
+ */
+static inline ecp_curve_type ecp_get_type( const ecp_group *grp )
+{
+    if( grp->G.X.p == NULL )
+        return( POLARSSL_ECP_TYPE_NONE );
+
+    if( grp->G.Y.p == NULL )
+        return( POLARSSL_ECP_TYPE_MONTGOMERY );
+    else
+        return( POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS );
+}
+
 /*
  * Initialize (the components of) a point
  */
@@ -184,7 +305,7 @@ void ecp_group_init( ecp_group *grp )
  */
 void ecp_keypair_init( ecp_keypair *key )
 {
-    if ( key == NULL )
+    if( key == NULL )
         return;
 
     ecp_group_init( &key->grp );
@@ -215,11 +336,14 @@ void ecp_group_free( ecp_group *grp )
     if( grp == NULL )
         return;
 
-    mpi_free( &grp->P );
-    mpi_free( &grp->A );
-    mpi_free( &grp->B );
-    ecp_point_free( &grp->G );
-    mpi_free( &grp->N );
+    if( grp->h != 1 )
+    {
+        mpi_free( &grp->P );
+        mpi_free( &grp->A );
+        mpi_free( &grp->B );
+        ecp_point_free( &grp->G );
+        mpi_free( &grp->N );
+    }
 
     if( grp->T != NULL )
     {
@@ -228,7 +352,7 @@ void ecp_group_free( ecp_group *grp )
         polarssl_free( grp->T );
     }
 
-    memset( grp, 0, sizeof( ecp_group ) );
+    polarssl_zeroize( grp, sizeof( ecp_group ) );
 }
 
 /*
@@ -236,7 +360,7 @@ void ecp_group_free( ecp_group *grp )
  */
 void ecp_keypair_free( ecp_keypair *key )
 {
-    if ( key == NULL )
+    if( key == NULL )
         return;
 
     ecp_group_free( &key->grp );
@@ -366,16 +490,28 @@ cleanup:
  * Import a point from unsigned binary data (SEC1 2.3.4)
  */
 int ecp_point_read_binary( const ecp_group *grp, ecp_point *pt,
-                           const unsigned char *buf, size_t ilen ) {
+                           const unsigned char *buf, size_t ilen )
+{
     int ret;
     size_t plen;
 
-    if( ilen == 1 && buf[0] == 0x00 )
-        return( ecp_set_zero( pt ) );
+    if ( ilen < 1 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+
+    if( buf[0] == 0x00 )
+    {
+        if( ilen == 1 )
+            return( ecp_set_zero( pt ) );
+        else
+            return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+    }
 
     plen = mpi_size( &grp->P );
 
-    if( ilen != 2 * plen + 1 || buf[0] != 0x04 )
+    if( buf[0] != 0x04 )
+        return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
+
+    if( ilen != 2 * plen + 1 )
         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
     MPI_CHK( mpi_read_binary( &pt->X, buf + 1, plen ) );
@@ -399,7 +535,7 @@ int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt,
     const unsigned char *buf_start;
 
     /*
-     * We must have at least two bytes (1 for length, at least of for data)
+     * We must have at least two bytes (1 for length, at least one for data)
      */
     if( buf_len < 2 )
         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
@@ -445,20 +581,19 @@ int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt,
     buf[0] = (unsigned char) *olen;
     ++*olen;
 
-    return 0;
+    return( 0 );
 }
 
 /*
- * Import an ECP group from ASCII strings, general case (A used)
+ * Import an ECP group from ASCII strings, case A == -3
  */
-static int ecp_group_read_string_gen( ecp_group *grp, int radix,
-                           const char *p, const char *a, const char *b,
+int ecp_group_read_string( ecp_group *grp, int radix,
+                           const char *p, const char *b,
                            const char *gx, const char *gy, const char *n)
 {
     int ret;
 
     MPI_CHK( mpi_read_string( &grp->P, radix, p ) );
-    MPI_CHK( mpi_read_string( &grp->A, radix, a ) );
     MPI_CHK( mpi_read_string( &grp->B, radix, b ) );
     MPI_CHK( ecp_point_read_string( &grp->G, radix, gx, gy ) );
     MPI_CHK( mpi_read_string( &grp->N, radix, n ) );
@@ -473,265 +608,6 @@ cleanup:
     return( ret );
 }
 
-/*
- * Import an ECP group from ASCII strings, case A == -3
- */
-int ecp_group_read_string( ecp_group *grp, int radix,
-                           const char *p, const char *b,
-                           const char *gx, const char *gy, const char *n)
-{
-    int ret;
-
-    MPI_CHK( ecp_group_read_string_gen( grp, radix, p, "00", b, gx, gy, n ) );
-    MPI_CHK( mpi_add_int( &grp->A, &grp->P, -3 ) );
-
-cleanup:
-    if( ret != 0 )
-        ecp_group_free( grp );
-
-    return( ret );
-}
-
-/*
- * Domain parameters for secp192r1
- */
-#define SECP192R1_P \
-    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"
-#define SECP192R1_B \
-    "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"
-#define SECP192R1_GX \
-    "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
-#define SECP192R1_GY \
-    "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"
-#define SECP192R1_N \
-    "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"
-
-/*
- * Domain parameters for secp224r1
- */
-#define SECP224R1_P \
-    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"
-#define SECP224R1_B \
-    "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"
-#define SECP224R1_GX \
-    "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
-#define SECP224R1_GY \
-    "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"
-#define SECP224R1_N \
-    "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"
-
-/*
- * Domain parameters for secp256r1
- */
-#define SECP256R1_P \
-    "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"
-#define SECP256R1_B \
-    "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"
-#define SECP256R1_GX \
-    "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
-#define SECP256R1_GY \
-    "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"
-#define SECP256R1_N \
-    "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"
-
-/*
- * Domain parameters for secp384r1
- */
-#define SECP384R1_P \
-    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
-    "FFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"
-#define SECP384R1_B \
-    "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE814112" \
-    "0314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"
-#define SECP384R1_GX \
-    "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B98" \
-    "59F741E082542A385502F25DBF55296C3A545E3872760AB7"
-#define SECP384R1_GY \
-    "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147C" \
-    "E9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"
-#define SECP384R1_N \
-    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
-    "C7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"
-
-/*
- * Domain parameters for secp521r1
- */
-#define SECP521R1_P \
-    "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
-    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
-    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
-#define SECP521R1_B \
-    "00000051953EB9618E1C9A1F929A21A0B68540EEA2DA725B" \
-    "99B315F3B8B489918EF109E156193951EC7E937B1652C0BD" \
-    "3BB1BF073573DF883D2C34F1EF451FD46B503F00"
-#define SECP521R1_GX \
-    "000000C6858E06B70404E9CD9E3ECB662395B4429C648139" \
-    "053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127" \
-    "A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
-#define SECP521R1_GY \
-    "0000011839296A789A3BC0045C8A5FB42C7D1BD998F54449" \
-    "579B446817AFBD17273E662C97EE72995EF42640C550B901" \
-    "3FAD0761353C7086A272C24088BE94769FD16650"
-#define SECP521R1_N \
-    "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
-    "FFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148" \
-    "F709A5D03BB5C9B8899C47AEBB6FB71E91386409"
-
-/*
- * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
- */
-#define BP256R1_P \
-    "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377"
-#define BP256R1_A \
-    "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9"
-#define BP256R1_B \
-    "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6"
-#define BP256R1_GX \
-    "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262"
-#define BP256R1_GY \
-    "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997"
-#define BP256R1_N \
-    "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7"
-
-/*
- * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
- */
-#define BP384R1_P \
-    "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB711" \
-    "23ACD3A729901D1A71874700133107EC53"
-#define BP384R1_A \
-    "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F9" \
-    "0F8AA5814A503AD4EB04A8C7DD22CE2826"
-#define BP384R1_B \
-    "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62" \
-    "D57CB4390295DBC9943AB78696FA504C11"
-#define BP384R1_GX \
-    "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10" \
-    "E8E826E03436D646AAEF87B2E247D4AF1E"
-#define BP384R1_GY \
-    "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129" \
-    "280E4646217791811142820341263C5315"
-#define BP384R1_N \
-    "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425" \
-    "A7CF3AB6AF6B7FC3103B883202E9046565"
-
-/*
- * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
- */
-#define BP512R1_P \
-    "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308" \
-    "717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3"
-#define BP512R1_A \
-    "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863" \
-    "BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA"
-#define BP512R1_B \
-    "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117" \
-    "A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723"
-#define BP512R1_GX \
-    "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009" \
-    "8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822"
-#define BP512R1_GY \
-    "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81" \
-    "11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892"
-#define BP512R1_N \
-    "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308" \
-    "70553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069"
-
-#if defined(POLARSSL_ECP_NIST_OPTIM)
-/* Forward declarations */
-static int ecp_mod_p192( mpi * );
-static int ecp_mod_p224( mpi * );
-static int ecp_mod_p256( mpi * );
-static int ecp_mod_p384( mpi * );
-static int ecp_mod_p521( mpi * );
-#endif
-
-/*
- * Set a group using well-known domain parameters
- */
-int ecp_use_known_dp( ecp_group *grp, ecp_group_id id )
-{
-    grp->id = id;
-
-    switch( id )
-    {
-#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
-        case POLARSSL_ECP_DP_SECP192R1:
-#if defined(POLARSSL_ECP_NIST_OPTIM)
-            grp->modp = ecp_mod_p192;
-#endif
-            return( ecp_group_read_string( grp, 16,
-                        SECP192R1_P, SECP192R1_B,
-                        SECP192R1_GX, SECP192R1_GY, SECP192R1_N ) );
-#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
-
-#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
-        case POLARSSL_ECP_DP_SECP224R1:
-#if defined(POLARSSL_ECP_NIST_OPTIM)
-            grp->modp = ecp_mod_p224;
-#endif
-            return( ecp_group_read_string( grp, 16,
-                        SECP224R1_P, SECP224R1_B,
-                        SECP224R1_GX, SECP224R1_GY, SECP224R1_N ) );
-#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
-
-#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
-        case POLARSSL_ECP_DP_SECP256R1:
-#if defined(POLARSSL_ECP_NIST_OPTIM)
-            grp->modp = ecp_mod_p256;
-#endif
-            return( ecp_group_read_string( grp, 16,
-                        SECP256R1_P, SECP256R1_B,
-                        SECP256R1_GX, SECP256R1_GY, SECP256R1_N ) );
-#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
-
-#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
-        case POLARSSL_ECP_DP_SECP384R1:
-#if defined(POLARSSL_ECP_NIST_OPTIM)
-            grp->modp = ecp_mod_p384;
-#endif
-            return( ecp_group_read_string( grp, 16,
-                        SECP384R1_P, SECP384R1_B,
-                        SECP384R1_GX, SECP384R1_GY, SECP384R1_N ) );
-#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
-
-#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
-        case POLARSSL_ECP_DP_SECP521R1:
-#if defined(POLARSSL_ECP_NIST_OPTIM)
-            grp->modp = ecp_mod_p521;
-#endif
-            return( ecp_group_read_string( grp, 16,
-                        SECP521R1_P, SECP521R1_B,
-                        SECP521R1_GX, SECP521R1_GY, SECP521R1_N ) );
-#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
-
-#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
-        case POLARSSL_ECP_DP_BP256R1:
-            return( ecp_group_read_string_gen( grp, 16,
-                        BP256R1_P, BP256R1_A, BP256R1_B,
-                        BP256R1_GX, BP256R1_GY, BP256R1_N ) );
-#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
-
-#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
-        case POLARSSL_ECP_DP_BP384R1:
-            return( ecp_group_read_string_gen( grp, 16,
-                        BP384R1_P, BP384R1_A, BP384R1_B,
-                        BP384R1_GX, BP384R1_GY, BP384R1_N ) );
-#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
-
-#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
-        case POLARSSL_ECP_DP_BP512R1:
-            return( ecp_group_read_string_gen( grp, 16,
-                        BP512R1_P, BP512R1_A, BP512R1_B,
-                        BP512R1_GX, BP512R1_GY, BP512R1_N ) );
-#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
-
-        default:
-            ecp_group_free( grp );
-            return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
-    }
-}
-
 /*
  * Set a group from an ECParameters record (RFC 4492)
  */
@@ -794,7 +670,7 @@ int ecp_tls_write_group( const ecp_group *grp, size_t *olen,
     buf[0] = curve_info->tls_id >> 8;
     buf[1] = curve_info->tls_id & 0xFF;
 
-    return 0;
+    return( 0 );
 }
 
 /*
@@ -844,7 +720,14 @@ cleanup:
 /*
  * Reduce a mpi mod p in-place, general case, to use after mpi_mul_mpi
  */
-#define MOD_MUL( N )    MPI_CHK( ecp_modp( &N, grp ) )
+#if defined(POLARSSL_SELF_TEST)
+#define INC_MUL_COUNT   mul_count++;
+#else
+#define INC_MUL_COUNT
+#endif
+
+#define MOD_MUL( N )    do { MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
+                        while( 0 )
 
 /*
  * Reduce a mpi mod p in-place, to use after mpi_sub_mpi
@@ -863,10 +746,20 @@ cleanup:
     while( mpi_cmp_mpi( &N, &grp->P ) >= 0 )        \
         MPI_CHK( mpi_sub_abs( &N, &N, &grp->P ) )
 
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+/*
+ * For curves in short Weierstrass form, we do all the internal operations in
+ * Jacobian coordinates.
+ *
+ * For multiplication, we'll use a comb method with coutermeasueres against
+ * SPA, hence timing attacks.
+ */
+
 /*
  * Normalize jacobian coordinates so that Z == 0 || Z == 1  (GECC 3.2.1)
+ * Cost: 1N := 1I + 3M + 1S
  */
-static int ecp_normalize( const ecp_group *grp, ecp_point *pt )
+static int ecp_normalize_jac( const ecp_group *grp, ecp_point *pt )
 {
     int ret;
     mpi Zi, ZZi;
@@ -902,23 +795,25 @@ cleanup:
 }
 
 /*
- * Normalize jacobian coordinates of an array of points,
+ * Normalize jacobian coordinates of an array of (pointers to) points,
  * using Montgomery's trick to perform only one inversion mod P.
  * (See for example Cohen's "A Course in Computational Algebraic Number
  * Theory", Algorithm 10.3.4.)
  *
  * Warning: fails (returning an error) if one of the points is zero!
- * This should never happen, see choice of w in ecp_mul().
+ * This should never happen, see choice of w in ecp_mul_comb().
+ *
+ * Cost: 1N(t) := 1I + (6t - 3)M + 1S
  */
-static int ecp_normalize_many( const ecp_group *grp,
-                               ecp_point T[], size_t t_len )
+static int ecp_normalize_jac_many( const ecp_group *grp,
+                                   ecp_point *T[], size_t t_len )
 {
     int ret;
     size_t i;
     mpi *c, u, Zi, ZZi;
 
     if( t_len < 2 )
-        return( ecp_normalize( grp, T ) );
+        return( ecp_normalize_jac( grp, *T ) );
 
     if( ( c = (mpi *) polarssl_malloc( t_len * sizeof( mpi ) ) ) == NULL )
         return( POLARSSL_ERR_ECP_MALLOC_FAILED );
@@ -930,10 +825,10 @@ static int ecp_normalize_many( const ecp_group *grp,
     /*
      * c[i] = Z_0 * ... * Z_i
      */
-    MPI_CHK( mpi_copy( &c[0], &T[0].Z ) );
+    MPI_CHK( mpi_copy( &c[0], &T[0]->Z ) );
     for( i = 1; i < t_len; i++ )
     {
-        MPI_CHK( mpi_mul_mpi( &c[i], &c[i-1], &T[i].Z ) );
+        MPI_CHK( mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
         MOD_MUL( c[i] );
     }
 
@@ -953,18 +848,27 @@ static int ecp_normalize_many( const ecp_group *grp,
         }
         else
         {
-            MPI_CHK( mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
-            MPI_CHK( mpi_mul_mpi( &u,  &u, &T[i].Z ) ); MOD_MUL( u );
+            MPI_CHK( mpi_mul_mpi( &Zi, &u, &c[i-1]  ) ); MOD_MUL( Zi );
+            MPI_CHK( mpi_mul_mpi( &u,  &u, &T[i]->Z ) ); MOD_MUL( u );
         }
 
         /*
          * proceed as in normalize()
          */
-        MPI_CHK( mpi_mul_mpi( &ZZi,    &Zi,     &Zi     ) ); MOD_MUL( ZZi );
-        MPI_CHK( mpi_mul_mpi( &T[i].X, &T[i].X, &ZZi    ) ); MOD_MUL( T[i].X );
-        MPI_CHK( mpi_mul_mpi( &T[i].Y, &T[i].Y, &ZZi    ) ); MOD_MUL( T[i].Y );
-        MPI_CHK( mpi_mul_mpi( &T[i].Y, &T[i].Y, &Zi     ) ); MOD_MUL( T[i].Y );
-        MPI_CHK( mpi_lset( &T[i].Z, 1 ) );
+        MPI_CHK( mpi_mul_mpi( &ZZi,     &Zi,      &Zi  ) ); MOD_MUL( ZZi );
+        MPI_CHK( mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
+        MPI_CHK( mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
+        MPI_CHK( mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi  ) ); MOD_MUL( T[i]->Y );
+
+        /*
+         * Post-precessing: reclaim some memory by shrinking coordinates
+         * - not storing Z (always 1)
+         * - shrinking other coordinates, but still keeping the same number of
+         *   limbs as P, as otherwise it will too likely be regrown too fast.
+         */
+        MPI_CHK( mpi_shrink( &T[i]->X, grp->P.n ) );
+        MPI_CHK( mpi_shrink( &T[i]->Y, grp->P.n ) );
+        mpi_free( &T[i]->Z );
 
         if( i == 0 )
             break;
@@ -980,6 +884,31 @@ cleanup:
     return( ret );
 }
 
+/*
+ * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
+ * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
+ */
+static int ecp_safe_invert_jac( const ecp_group *grp,
+                            ecp_point *Q,
+                            unsigned char inv )
+{
+    int ret;
+    unsigned char nonzero;
+    mpi mQY;
+
+    mpi_init( &mQY );
+
+    /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
+    MPI_CHK( mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
+    nonzero = mpi_cmp_int( &Q->Y, 0 ) != 0;
+    MPI_CHK( mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
+
+cleanup:
+    mpi_free( &mQY );
+
+    return( ret );
+}
+
 /*
  * Point doubling R = 2 P, Jacobian coordinates
  *
@@ -987,6 +916,8 @@ cleanup:
  * with heavy variable renaming, some reordering and one minor modification
  * (a = 2 * b, c = d - 2a replaced with c = d, c = c - b, c = c - b)
  * in order to use a lot less intermediate variables (6 vs 25).
+ *
+ * Cost: 1D := 2M + 8S
  */
 static int ecp_double_jac( const ecp_group *grp, ecp_point *R,
                            const ecp_point *P )
@@ -1012,7 +943,17 @@ static int ecp_double_jac( const ecp_group *grp, ecp_point *R,
     MPI_CHK( mpi_mul_mpi( &Z3,  &P->Z,  &P->Z   ) ); MOD_MUL( Z3 );
     MPI_CHK( mpi_mul_mpi( &X3,  &Z3,    &Z3     ) ); MOD_MUL( X3 );
     MPI_CHK( mpi_mul_int( &T3,  &T3,    3       ) ); MOD_ADD( T3 );
-    MPI_CHK( mpi_mul_mpi( &X3,  &X3,    &grp->A ) ); MOD_MUL( X3 );
+
+    /* Special case for A = -3 */
+    if( grp->A.p == NULL )
+    {
+        MPI_CHK( mpi_mul_int( &X3, &X3, 3 ) );
+        X3.s = -1; /* mpi_mul_int doesn't handle negative numbers */
+        MOD_SUB( X3 );
+    }
+    else
+        MPI_CHK( mpi_mul_mpi( &X3,  &X3,    &grp->A ) ); MOD_MUL( X3 );
+
     MPI_CHK( mpi_add_mpi( &T3,  &T3,    &X3     ) ); MOD_ADD( T3 );
     MPI_CHK( mpi_mul_mpi( &X3,  &T3,    &T3     ) ); MOD_MUL( X3 );
     MPI_CHK( mpi_sub_mpi( &X3,  &X3,    &T1     ) ); MOD_SUB( X3 );
@@ -1038,19 +979,25 @@ cleanup:
 }
 
 /*
- * Addition or subtraction: R = P + Q or R = P - Q,
- * mixed affine-Jacobian coordinates (GECC 3.22)
+ * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
  *
  * The coordinates of Q must be normalized (= affine),
  * but those of P don't need to. R is not normalized.
  *
- * If sign >= 0, perform addition, otherwise perform subtraction,
- * taking advantage of the fact that, for Q != 0, we have
- * -Q = (Q.X, -Q.Y, Q.Z)
+ * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
+ * None of these cases can happen as intermediate step in ecp_mul_comb():
+ * - at each step, P, Q and R are multiples of the base point, the factor
+ *   being less than its order, so none of them is zero;
+ * - Q is an odd multiple of the base point, P an even multiple,
+ *   due to the choice of precomputed points in the modified comb method.
+ * So branches for these cases do not leak secret information.
+ *
+ * We accept Q->Z being unset (saving memory in tables) as meaning 1.
+ *
+ * Cost: 1A := 8M + 3S
  */
 static int ecp_add_mixed( const ecp_group *grp, ecp_point *R,
-                          const ecp_point *P, const ecp_point *Q,
-                          signed char sign )
+                          const ecp_point *P, const ecp_point *Q )
 {
     int ret;
     mpi T1, T2, T3, T4, X, Y, Z;
@@ -1060,30 +1007,18 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_point *R,
 #endif
 
     /*
-     * Trivial cases: P == 0 or Q == 0
-     * (Check Q first, so that we know Q != 0 when we compute -Q.)
+     * Trivial cases: P == 0 or Q == 0 (case 1)
      */
-    if( mpi_cmp_int( &Q->Z, 0 ) == 0 )
-        return( ecp_copy( R, P ) );
-
     if( mpi_cmp_int( &P->Z, 0 ) == 0 )
-    {
-        ret = ecp_copy( R, Q );
-
-        /*
-         * -R.Y mod P = P - R.Y unless R.Y == 0
-         */
-        if( ret == 0 && sign < 0)
-            if( mpi_cmp_int( &R->Y, 0 ) != 0 )
-                ret = mpi_sub_mpi( &R->Y, &grp->P, &R->Y );
+        return( ecp_copy( R, Q ) );
 
-        return( ret );
-    }
+    if( Q->Z.p != NULL && mpi_cmp_int( &Q->Z, 0 ) == 0 )
+        return( ecp_copy( R, P ) );
 
     /*
      * Make sure Q coordinates are normalized
      */
-    if( mpi_cmp_int( &Q->Z, 1 ) != 0 )
+    if( Q->Z.p != NULL && mpi_cmp_int( &Q->Z, 1 ) != 0 )
         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
     mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &T4 );
@@ -1093,20 +1028,10 @@ static int ecp_add_mixed( const ecp_group *grp, ecp_point *R,
     MPI_CHK( mpi_mul_mpi( &T2,  &T1,    &P->Z ) );  MOD_MUL( T2 );
     MPI_CHK( mpi_mul_mpi( &T1,  &T1,    &Q->X ) );  MOD_MUL( T1 );
     MPI_CHK( mpi_mul_mpi( &T2,  &T2,    &Q->Y ) );  MOD_MUL( T2 );
-
-    /*
-     * For subtraction, -Q.Y should have been used instead of Q.Y,
-     * so we replace T2 by -T2, which is P - T2 mod P
-     */
-    if( sign < 0 )
-    {
-        MPI_CHK( mpi_sub_mpi( &T2, &grp->P, &T2 ) );
-        MOD_SUB( T2 );
-    }
-
     MPI_CHK( mpi_sub_mpi( &T1,  &T1,    &P->X ) );  MOD_SUB( T1 );
     MPI_CHK( mpi_sub_mpi( &T2,  &T2,    &P->Y ) );  MOD_SUB( T2 );
 
+    /* Special cases (2) and (3) */
     if( mpi_cmp_int( &T1, 0 ) == 0 )
     {
         if( mpi_cmp_int( &T2, 0 ) == 0 )
@@ -1154,8 +1079,11 @@ int ecp_add( const ecp_group *grp, ecp_point *R,
 {
     int ret;
 
-    MPI_CHK( ecp_add_mixed( grp, R, P, Q , 1 ) );
-    MPI_CHK( ecp_normalize( grp, R ) );
+    if( ecp_get_type( grp ) != POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+        return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
+
+    MPI_CHK( ecp_add_mixed( grp, R, P, Q ) );
+    MPI_CHK( ecp_normalize_jac( grp, R ) );
 
 cleanup:
     return( ret );
@@ -1168,106 +1096,23 @@ int ecp_sub( const ecp_group *grp, ecp_point *R,
              const ecp_point *P, const ecp_point *Q )
 {
     int ret;
+    ecp_point mQ;
 
-    MPI_CHK( ecp_add_mixed( grp, R, P, Q, -1 ) );
-    MPI_CHK( ecp_normalize( grp, R ) );
-
-cleanup:
-    return( ret );
-}
-
-/*
- * Compute a modified width-w non-adjacent form (NAF) of a number,
- * with a fixed pattern for resistance to simple timing attacks (even SPA),
- * see [1]. (The resulting multiplication algorithm can also been seen as a
- * modification of 2^w-ary multiplication, with signed coefficients, all of
- * them odd.)
- *
- * Input:
- * m must be an odd positive mpi less than w * k bits long
- * x must be an array of k elements
- * w must be less than a certain maximum (currently 8)
- *
- * The result is a sequence x[0], ..., x[k-1] with x[i] in the range
- * - 2^(width - 1) .. 2^(width - 1) - 1 such that
- * m = (2 * x[0] + 1) + 2^width * (2 * x[1] + 1) + ...
- *     + 2^((k-1) * width) * (2 * x[k-1] + 1)
- *
- * Compared to "Algorithm SPA-resistant Width-w NAF with Odd Scalar"
- * p. 335 of the cited reference, here we return only u, not d_w since
- * it is known that the other d_w[j] will be 0.  Moreover, the returned
- * string doesn't actually store u_i but x_i = u_i / 2 since it is known
- * that u_i is odd. Also, since we always select a positive value for d
- * mod 2^w, we don't need to check the sign of u[i-1] when the reference
- * does. Finally, there is an off-by-one error in the reference: the
- * last index should be k-1, not k.
- */
-static int ecp_w_naf_fixed( signed char x[], size_t k,
-                            unsigned char w, const mpi *m )
-{
-    int ret;
-    unsigned int i, u, mask, carry;
-    mpi M;
-
-    mpi_init( &M );
-
-    MPI_CHK( mpi_copy( &M, m ) );
-    mask = ( 1 << w ) - 1;
-    carry = 1 << ( w - 1 );
-
-    for( i = 0; i < k; i++ )
-    {
-        u = M.p[0] & mask;
-
-        if( ( u & 1 ) == 0 && i > 0 )
-            x[i - 1] -= carry;
-
-        x[i] = u >> 1;
-        mpi_shift_r( &M, w );
-    }
-
-    /*
-     * We should have consumed all bits, unless the input value was too big
-     */
-    if( mpi_cmp_int( &M, 0 ) != 0 )
-        ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
-
-cleanup:
-
-    mpi_free( &M );
-
-    return( ret );
-}
-
-/*
- * Precompute odd multiples of P up to (2 * t_len - 1) P.
- * The table is filled with T[i] = (2 * i + 1) P.
- */
-static int ecp_precompute( const ecp_group *grp,
-                           ecp_point T[], size_t t_len,
-                           const ecp_point *P )
-{
-    int ret;
-    size_t i;
-    ecp_point PP;
-
-    ecp_point_init( &PP );
+    ecp_point_init( &mQ );
 
-    MPI_CHK( ecp_add( grp, &PP, P, P ) );
-
-    MPI_CHK( ecp_copy( &T[0], P ) );
+    if( ecp_get_type( grp ) != POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+        return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
 
-    for( i = 1; i < t_len; i++ )
-        MPI_CHK( ecp_add_mixed( grp, &T[i], &T[i-1], &PP, +1 ) );
+    /* mQ = - Q */
+    MPI_CHK( ecp_copy( &mQ, Q ) );
+    if( mpi_cmp_int( &mQ.Y, 0 ) != 0 )
+        MPI_CHK( mpi_sub_mpi( &mQ.Y, &grp->P, &mQ.Y ) );
 
-    /*
-     * T[0] = P already has normalized coordinates
-     */
-    MPI_CHK( ecp_normalize_many( grp, T + 1, t_len - 1 ) );
+    MPI_CHK( ecp_add_mixed( grp, R, P, &mQ ) );
+    MPI_CHK( ecp_normalize_jac( grp, R ) );
 
 cleanup:
-
-    ecp_point_free( &PP );
+    ecp_point_free( &mQ );
 
     return( ret );
 }
@@ -1275,14 +1120,16 @@ cleanup:
 /*
  * Randomize jacobian coordinates:
  * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
- * This is sort of the reverse operation of ecp_normalize().
+ * This is sort of the reverse operation of ecp_normalize_jac().
+ *
+ * This countermeasure was first suggested in [2].
  */
-static int ecp_randomize_coordinates( const ecp_group *grp, ecp_point *pt,
+static int ecp_randomize_jac( const ecp_group *grp, ecp_point *pt,
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
     int ret;
     mpi l, ll;
-    size_t p_size = (grp->pbits + 7) / 8;
+    size_t p_size = ( grp->pbits + 7 ) / 8;
     int count = 0;
 
     mpi_init( &l ); mpi_init( &ll );
@@ -1293,7 +1140,7 @@ static int ecp_randomize_coordinates( const ecp_group *grp, ecp_point *pt,
         mpi_fill_random( &l, p_size, f_rng, p_rng );
 
         while( mpi_cmp_mpi( &l, &grp->P ) >= 0 )
-            mpi_shift_r( &l, 1 );
+            MPI_CHK( mpi_shift_r( &l, 1 ) );
 
         if( count++ > 10 )
             return( POLARSSL_ERR_ECP_RANDOM_FAILED );
@@ -1318,86 +1165,256 @@ cleanup:
 }
 
 /*
- * Maximum length of the precomputed table
+ * Check and define parameters used by the comb method (see below for details)
  */
-#define MAX_PRE_LEN     ( 1 << (POLARSSL_ECP_WINDOW_SIZE - 1) )
+#if POLARSSL_ECP_WINDOW_SIZE < 2 || POLARSSL_ECP_WINDOW_SIZE > 7
+#error "POLARSSL_ECP_WINDOW_SIZE out of bounds"
+#endif
 
-/*
- * Maximum length of the NAF: ceil( grp->nbits + 1 ) / w
- * (that is: grp->nbits / w + 1)
- * Allow p_bits + 1 bits in case M = grp->N + 1 is one bit longer than N.
- */
-#define MAX_NAF_LEN     ( POLARSSL_ECP_MAX_BITS / 2 + 1 )
+/* d = ceil( n / w ) */
+#define COMB_MAX_D      ( POLARSSL_ECP_MAX_BITS + 1 ) / 2
+
+/* number of precomputed points */
+#define COMB_MAX_PRE    ( 1 << ( POLARSSL_ECP_WINDOW_SIZE - 1 ) )
 
 /*
- * Integer multiplication: R = m * P
+ * Compute the representation of m that will be used with our comb method.
  *
- * Based on fixed-pattern width-w NAF, see comments of ecp_w_naf_fixed().
+ * The basic comb method is described in GECC 3.44 for example. We use a
+ * modified version that provides resistance to SPA by avoiding zero
+ * digits in the representation as in [3]. We modify the method further by
+ * requiring that all K_i be odd, which has the small cost that our
+ * representation uses one more K_i, due to carries.
  *
- * This function executes a fixed number of operations for
- * random m in the range 0 .. 2^nbits - 1.
+ * Also, for the sake of compactness, only the seven low-order bits of x[i]
+ * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
+ * the paper): it is set if and only if if s_i == -1;
  *
- * As an additional countermeasure against potential timing attacks,
- * we randomize coordinates before each addition. This was suggested as a
- * countermeasure against DPA in 5.3 of [2] (with the obvious adaptation that
- * we use jacobian coordinates, not standard projective coordinates).
+ * Calling conventions:
+ * - x is an array of size d + 1
+ * - w is the size, ie number of teeth, of the comb, and must be between
+ *   2 and 7 (in practice, between 2 and POLARSSL_ECP_WINDOW_SIZE)
+ * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
+ *   (the result will be incorrect if these assumptions are not satisfied)
+ */
+static void ecp_comb_fixed( unsigned char x[], size_t d,
+                            unsigned char w, const mpi *m )
+{
+    size_t i, j;
+    unsigned char c, cc, adjust;
+
+    memset( x, 0, d+1 );
+
+    /* First get the classical comb values (except for x_d = 0) */
+    for( i = 0; i < d; i++ )
+        for( j = 0; j < w; j++ )
+            x[i] |= mpi_get_bit( m, i + d * j ) << j;
+
+    /* Now make sure x_1 .. x_d are odd */
+    c = 0;
+    for( i = 1; i <= d; i++ )
+    {
+        /* Add carry and update it */
+        cc   = x[i] & c;
+        x[i] = x[i] ^ c;
+        c = cc;
+
+        /* Adjust if needed, avoiding branches */
+        adjust = 1 - ( x[i] & 0x01 );
+        c   |= x[i] & ( x[i-1] * adjust );
+        x[i] = x[i] ^ ( x[i-1] * adjust );
+        x[i-1] |= adjust << 7;
+    }
+}
+
+/*
+ * Precompute points for the comb method
+ *
+ * If i = i_{w-1} ... i_1 is the binary representation of i, then
+ * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P
+ *
+ * T must be able to hold 2^{w - 1} elements
+ *
+ * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)
  */
-int ecp_mul( ecp_group *grp, ecp_point *R,
-             const mpi *m, const ecp_point *P,
-             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int ecp_precompute_comb( const ecp_group *grp,
+                                ecp_point T[], const ecp_point *P,
+                                unsigned char w, size_t d )
 {
     int ret;
-    unsigned char w, m_is_odd, p_eq_g;
-    size_t pre_len = 1, naf_len, i, j;
-    signed char naf[ MAX_NAF_LEN ];
-    ecp_point Q, *T = NULL, S[2];
-    mpi M;
+    unsigned char i, k;
+    size_t j;
+    ecp_point *cur, *TT[COMB_MAX_PRE - 1];
 
-    if( mpi_cmp_int( m, 0 ) < 0 || mpi_msb( m ) > grp->nbits )
-        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+    /*
+     * Set T[0] = P and
+     * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
+     */
+    MPI_CHK( ecp_copy( &T[0], P ) );
+
+    k = 0;
+    for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
+    {
+        cur = T + i;
+        MPI_CHK( ecp_copy( cur, T + ( i >> 1 ) ) );
+        for( j = 0; j < d; j++ )
+            MPI_CHK( ecp_double_jac( grp, cur, cur ) );
+
+        TT[k++] = cur;
+    }
+
+    MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+
+    /*
+     * Compute the remaining ones using the minimal number of additions
+     * Be careful to update T[2^l] only after using it!
+     */
+    k = 0;
+    for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
+    {
+        j = i;
+        while( j-- )
+        {
+            MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
+            TT[k++] = &T[i + j];
+        }
+    }
+
+    MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
+ */
+static int ecp_select_comb( const ecp_group *grp, ecp_point *R,
+                            const ecp_point T[], unsigned char t_len,
+                            unsigned char i )
+{
+    int ret;
+    unsigned char ii, j;
+
+    /* Ignore the "sign" bit and scale down */
+    ii =  ( i & 0x7Fu ) >> 1;
+
+    /* Read the whole table to thwart cache-based timing attacks */
+    for( j = 0; j < t_len; j++ )
+    {
+        MPI_CHK( mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
+        MPI_CHK( mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
+    }
+
+    /* Safely invert result if i is "negative" */
+    MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Core multiplication algorithm for the (modified) comb method.
+ * This part is actually common with the basic comb method (GECC 3.44)
+ *
+ * Cost: d A + d D + 1 R
+ */
+static int ecp_mul_comb_core( const ecp_group *grp, ecp_point *R,
+                              const ecp_point T[], unsigned char t_len,
+                              const unsigned char x[], size_t d,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng )
+{
+    int ret;
+    ecp_point Txi;
+    size_t i;
+
+    ecp_point_init( &Txi );
+
+    /* Start with a non-zero point and randomize its coordinates */
+    i = d;
+    MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
+    MPI_CHK( mpi_lset( &R->Z, 1 ) );
+    if( f_rng != 0 )
+        MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+
+    while( i-- != 0 )
+    {
+        MPI_CHK( ecp_double_jac( grp, R, R ) );
+        MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
+        MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
+    }
+
+cleanup:
+    ecp_point_free( &Txi );
+
+    return( ret );
+}
+
+/*
+ * Multiplication using the comb method,
+ * for curves in short Weierstrass form
+ */
+static int ecp_mul_comb( ecp_group *grp, ecp_point *R,
+                         const mpi *m, const ecp_point *P,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng )
+{
+    int ret;
+    unsigned char w, m_is_odd, p_eq_g, pre_len, i;
+    size_t d;
+    unsigned char k[COMB_MAX_D + 1];
+    ecp_point *T;
+    mpi M, mm;
 
     mpi_init( &M );
-    ecp_point_init( &Q );
-    ecp_point_init( &S[0] );
-    ecp_point_init( &S[1] );
+    mpi_init( &mm );
+
+    /* we need N to be odd to trnaform m in an odd number, check now */
+    if( mpi_get_bit( &grp->N, 0 ) != 1 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
     /*
-     * Check if P == G
+     * Minimize the number of multiplications, that is minimize
+     * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
+     * (see costs of the various parts, with 1S = 1M)
      */
-    p_eq_g = ( mpi_cmp_int( &P->Z, 1 ) == 0 &&
-               mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
-               mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
+    w = grp->nbits >= 384 ? 5 : 4;
 
     /*
-     * If P == G, pre-compute a lot of points: this will be re-used later,
-     * otherwise, choose window size depending on curve size
+     * If P == G, pre-compute a bit more, since this may be re-used later.
+     * Just adding one avoids upping the cost of the first mul too much,
+     * and the memory cost too.
      */
+#if POLARSSL_ECP_FIXED_POINT_OPTIM == 1
+    p_eq_g = ( mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
+               mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
     if( p_eq_g )
-        w = POLARSSL_ECP_WINDOW_SIZE;
-    else
-        w = grp->nbits >= 512 ? 6 :
-            grp->nbits >= 224 ? 5 :
-                                4;
+        w++;
+#else
+    p_eq_g = 0;
+#endif
 
     /*
-     * Make sure w is within the limits.
-     * The last test ensures that none of the precomputed points is zero,
-     * which wouldn't be handled correctly by ecp_normalize_many().
-     * It is only useful for very small curves as used in the test suite.
+     * Make sure w is within bounds.
+     * (The last test is useful only for very small curves in the test suite.)
      */
     if( w > POLARSSL_ECP_WINDOW_SIZE )
         w = POLARSSL_ECP_WINDOW_SIZE;
-    if( w < 2 || w >= grp->nbits )
+    if( w >= grp->nbits )
         w = 2;
 
-    pre_len <<= ( w - 1 );
-    naf_len = grp->nbits / w + 1;
+    /* Other sizes that depend on w */
+    pre_len = 1U << ( w - 1 );
+    d = ( grp->nbits + w - 1 ) / w;
 
     /*
      * Prepare precomputed points: if P == G we want to
-     * use grp->T if already initialized, or initiliaze it.
+     * use grp->T if already initialized, or initialize it.
      */
-    if( ! p_eq_g || grp->T == NULL )
+    T = p_eq_g ? grp->T : NULL;
+
+    if( T == NULL )
     {
         T = (ecp_point *) polarssl_malloc( pre_len * sizeof( ecp_point ) );
         if( T == NULL )
@@ -1409,7 +1426,7 @@ int ecp_mul( ecp_group *grp, ecp_point *R,
         for( i = 0; i < pre_len; i++ )
             ecp_point_init( &T[i] );
 
-        MPI_CHK( ecp_precompute( grp, T, pre_len, P ) );
+        MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
 
         if( p_eq_g )
         {
@@ -1417,74 +1434,27 @@ int ecp_mul( ecp_group *grp, ecp_point *R,
             grp->T_size = pre_len;
         }
     }
-    else
-    {
-        T = grp->T;
-
-        /* Should never happen, but we want to be extra sure */
-        if( pre_len != grp->T_size )
-        {
-            ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
-            goto cleanup;
-        }
-    }
 
     /*
-     * Make sure M is odd (M = m + 1 or M = m + 2)
-     * later we'll get m * P by subtracting P or 2 * P to M * P.
+     * Make sure M is odd (M = m or M = N - m, since N is odd)
+     * using the fact that m * P = - (N - m) * P
      */
     m_is_odd = ( mpi_get_bit( m, 0 ) == 1 );
-
     MPI_CHK( mpi_copy( &M, m ) );
-    MPI_CHK( mpi_add_int( &M, &M, 1 + m_is_odd ) );
+    MPI_CHK( mpi_sub_mpi( &mm, &grp->N, m ) );
+    MPI_CHK( mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
 
     /*
-     * Compute the fixed-pattern NAF of M
+     * Go for comb multiplication, R = M * P
      */
-    MPI_CHK( ecp_w_naf_fixed( naf, naf_len, w, &M ) );
+    ecp_comb_fixed( k, d, w, &M );
+    MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) );
 
     /*
-     * Compute M * P, using a variant of left-to-right 2^w-ary multiplication:
-     * at each step we add (2 * naf[i] + 1) P, then multiply by 2^w.
-     *
-     * If naf[i] >= 0, we have (2 * naf[i] + 1) P == T[ naf[i] ]
-     * Otherwise, (2 * naf[i] + 1) P == - ( 2 * ( - naf[i] - 1 ) + 1) P
-     *                               == T[ - naf[i] - 1 ]
+     * Now get m * P from M * P and normalize it
      */
-    MPI_CHK( ecp_set_zero( &Q ) );
-    i = naf_len - 1;
-    while( 1 )
-    {
-        /* Countermeasure (see comments above) */
-        if( f_rng != NULL )
-            ecp_randomize_coordinates( grp, &Q, f_rng, p_rng );
-
-        if( naf[i] < 0 )
-        {
-            MPI_CHK( ecp_add_mixed( grp, &Q, &Q, &T[ - naf[i] - 1 ], -1 ) );
-        }
-        else
-        {
-            MPI_CHK( ecp_add_mixed( grp, &Q, &Q, &T[ naf[i] ], +1 ) );
-        }
-
-        if( i == 0 )
-            break;
-        i--;
-
-        for( j = 0; j < w; j++ )
-        {
-            MPI_CHK( ecp_double_jac( grp, &Q, &Q ) );
-        }
-    }
-
-    /*
-     * Now get m * P from M * P
-     */
-    MPI_CHK( ecp_copy( &S[0], P ) );
-    MPI_CHK( ecp_add( grp, &S[1], P, P ) );
-    MPI_CHK( ecp_sub( grp, R, &Q, &S[m_is_odd] ) );
-
+    MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
+    MPI_CHK( ecp_normalize_jac( grp, R ) );
 
 cleanup:
 
@@ -1495,501 +1465,435 @@ cleanup:
         polarssl_free( T );
     }
 
-    ecp_point_free( &S[1] );
-    ecp_point_free( &S[0] );
-    ecp_point_free( &Q );
     mpi_free( &M );
+    mpi_free( &mm );
+
+    if( ret != 0 )
+        ecp_point_free( R );
 
     return( ret );
 }
 
+#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */
+
+#if defined(POLARSSL_ECP_MONTGOMERY)
 /*
- * Check that a point is valid as a public key (SEC1 3.2.3.1)
+ * For Montgomery curves, we do all the internal arithmetic in projective
+ * coordinates. Import/export of points uses only the x coordinates, which is
+ * internaly represented as X / Z.
+ *
+ * For scalar multiplication, we'll use a Montgomery ladder.
  */
-int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt )
+
+/*
+ * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
+ * Cost: 1M + 1I
+ */
+static int ecp_normalize_mxz( const ecp_group *grp, ecp_point *P )
 {
     int ret;
-    mpi YY, RHS;
 
-    if( mpi_cmp_int( &pt->Z, 0 ) == 0 )
-        return( POLARSSL_ERR_ECP_INVALID_KEY );
-
-    /*
-     * pt coordinates must be normalized for our checks
-     */
-    if( mpi_cmp_int( &pt->Z, 1 ) != 0 )
-        return( POLARSSL_ERR_ECP_INVALID_KEY );
-
-    if( mpi_cmp_int( &pt->X, 0 ) < 0 ||
-        mpi_cmp_int( &pt->Y, 0 ) < 0 ||
-        mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
-        mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
-        return( POLARSSL_ERR_ECP_INVALID_KEY );
-
-    mpi_init( &YY ); mpi_init( &RHS );
-
-    /*
-     * YY = Y^2
-     * RHS = X (X^2 + A) + B = X^3 + A X + B
-     */
-    MPI_CHK( mpi_mul_mpi( &YY,  &pt->Y,   &pt->Y  ) );  MOD_MUL( YY  );
-    MPI_CHK( mpi_mul_mpi( &RHS, &pt->X,   &pt->X  ) );  MOD_MUL( RHS );
-    MPI_CHK( mpi_add_mpi( &RHS, &RHS,     &grp->A ) );  MOD_ADD( RHS );
-    MPI_CHK( mpi_mul_mpi( &RHS, &RHS,     &pt->X  ) );  MOD_MUL( RHS );
-    MPI_CHK( mpi_add_mpi( &RHS, &RHS,     &grp->B ) );  MOD_ADD( RHS );
-
-    if( mpi_cmp_mpi( &YY, &RHS ) != 0 )
-        ret = POLARSSL_ERR_ECP_INVALID_KEY;
+    MPI_CHK( mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
+    MPI_CHK( mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
+    MPI_CHK( mpi_lset( &P->Z, 1 ) );
 
 cleanup:
-
-    mpi_free( &YY ); mpi_free( &RHS );
-
     return( ret );
 }
 
 /*
- * Check that an mpi is valid as a private key (SEC1 3.2)
- */
-int ecp_check_privkey( const ecp_group *grp, const mpi *d )
-{
-    /* We want 1 <= d <= N-1 */
-    if ( mpi_cmp_int( d, 1 ) < 0 || mpi_cmp_mpi( d, &grp->N ) >= 0 )
-        return( POLARSSL_ERR_ECP_INVALID_KEY );
-
-    return( 0 );
-}
-
-/*
- * Generate a keypair (SEC1 3.2.1)
+ * Randomize projective x/z coordinates:
+ * (X, Z) -> (l X, l Z) for random l
+ * This is sort of the reverse operation of ecp_normalize_mxz().
+ *
+ * This countermeasure was first suggested in [2].
+ * Cost: 2M
  */
-int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+static int ecp_randomize_mxz( const ecp_group *grp, ecp_point *P,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
+    int ret;
+    mpi l;
+    size_t p_size = ( grp->pbits + 7 ) / 8;
     int count = 0;
-    size_t n_size = (grp->nbits + 7) / 8;
 
-    /*
-     * Generate d such that 1 <= n < N
-     */
+    mpi_init( &l );
+
+    /* Generate l such that 1 < l < p */
     do
     {
-        mpi_fill_random( d, n_size, f_rng, p_rng );
+        mpi_fill_random( &l, p_size, f_rng, p_rng );
 
-        while( mpi_cmp_mpi( d, &grp->N ) >= 0 )
-            mpi_shift_r( d, 1 );
+        while( mpi_cmp_mpi( &l, &grp->P ) >= 0 )
+            MPI_CHK( mpi_shift_r( &l, 1 ) );
 
         if( count++ > 10 )
             return( POLARSSL_ERR_ECP_RANDOM_FAILED );
     }
-    while( mpi_cmp_int( d, 1 ) < 0 );
+    while( mpi_cmp_int( &l, 1 ) <= 0 );
 
-    return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) );
+    MPI_CHK( mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
+    MPI_CHK( mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z );
+
+cleanup:
+    mpi_free( &l );
+
+    return( ret );
 }
 
-#if defined(POLARSSL_ECP_NIST_OPTIM)
 /*
- * Fast reduction modulo the primes used by the NIST curves.
+ * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
+ * for Montgomery curves in x/z coordinates.
  *
- * These functions are: critical for speed, but not need for correct
- * operations. So, we make the choice to heavily rely on the internals of our
- * bignum library, which creates a tight coupling between these functions and
- * our MPI implementation.  However, the coupling between the ECP module and
- * MPI remains loose, since these functions can be deactivated at will.
- */
-
-#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
-/*
- * Compared to the way things are presented in FIPS 186-3 D.2,
- * we proceed in columns, from right (least significant chunk) to left,
- * adding chunks to N in place, and keeping a carry for the next chunk.
- * This avoids moving things around in memory, and uselessly adding zeros,
- * compared to the more straightforward, line-oriented approach.
+ * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
+ * with
+ * d =  X1
+ * P = (X2, Z2)
+ * Q = (X3, Z3)
+ * R = (X4, Z4)
+ * S = (X5, Z5)
+ * and eliminating temporary variables tO, ..., t4.
  *
- * For this prime we need to handle data in chunks of 64 bits.
- * Since this is always a multiple of our basic t_uint, we can
- * use a t_uint * to designate such a chunk, and small loops to handle it.
+ * Cost: 5M + 4S
  */
-
-/* Add 64-bit chunks (dst += src) and update carry */
-static inline void add64( t_uint *dst, t_uint *src, t_uint *carry )
+static int ecp_double_add_mxz( const ecp_group *grp,
+                               ecp_point *R, ecp_point *S,
+                               const ecp_point *P, const ecp_point *Q,
+                               const mpi *d )
 {
-    unsigned char i;
-    t_uint c = 0;
-    for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ )
-    {
-        *dst += c;      c  = ( *dst < c );
-        *dst += *src;   c += ( *dst < *src );
-    }
-    *carry += c;
-}
+    int ret;
+    mpi A, AA, B, BB, E, C, D, DA, CB;
+
+    mpi_init( &A ); mpi_init( &AA ); mpi_init( &B );
+    mpi_init( &BB ); mpi_init( &E ); mpi_init( &C );
+    mpi_init( &D ); mpi_init( &DA ); mpi_init( &CB );
+
+    MPI_CHK( mpi_add_mpi( &A,    &P->X,   &P->Z ) ); MOD_ADD( A    );
+    MPI_CHK( mpi_mul_mpi( &AA,   &A,      &A    ) ); MOD_MUL( AA   );
+    MPI_CHK( mpi_sub_mpi( &B,    &P->X,   &P->Z ) ); MOD_SUB( B    );
+    MPI_CHK( mpi_mul_mpi( &BB,   &B,      &B    ) ); MOD_MUL( BB   );
+    MPI_CHK( mpi_sub_mpi( &E,    &AA,     &BB   ) ); MOD_SUB( E    );
+    MPI_CHK( mpi_add_mpi( &C,    &Q->X,   &Q->Z ) ); MOD_ADD( C    );
+    MPI_CHK( mpi_sub_mpi( &D,    &Q->X,   &Q->Z ) ); MOD_SUB( D    );
+    MPI_CHK( mpi_mul_mpi( &DA,   &D,      &A    ) ); MOD_MUL( DA   );
+    MPI_CHK( mpi_mul_mpi( &CB,   &C,      &B    ) ); MOD_MUL( CB   );
+    MPI_CHK( mpi_add_mpi( &S->X, &DA,     &CB   ) ); MOD_MUL( S->X );
+    MPI_CHK( mpi_mul_mpi( &S->X, &S->X,   &S->X ) ); MOD_MUL( S->X );
+    MPI_CHK( mpi_sub_mpi( &S->Z, &DA,     &CB   ) ); MOD_SUB( S->Z );
+    MPI_CHK( mpi_mul_mpi( &S->Z, &S->Z,   &S->Z ) ); MOD_MUL( S->Z );
+    MPI_CHK( mpi_mul_mpi( &S->Z, d,       &S->Z ) ); MOD_MUL( S->Z );
+    MPI_CHK( mpi_mul_mpi( &R->X, &AA,     &BB   ) ); MOD_MUL( R->X );
+    MPI_CHK( mpi_mul_mpi( &R->Z, &grp->A, &E    ) ); MOD_MUL( R->Z );
+    MPI_CHK( mpi_add_mpi( &R->Z, &BB,     &R->Z ) ); MOD_ADD( R->Z );
+    MPI_CHK( mpi_mul_mpi( &R->Z, &E,      &R->Z ) ); MOD_MUL( R->Z );
 
-/* Add carry to a 64-bit chunk and update carry */
-static inline void carry64( t_uint *dst, t_uint *carry )
-{
-    unsigned char i;
-    for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ )
-    {
-        *dst += *carry;
-        *carry  = ( *dst < *carry );
-    }
-}
+cleanup:
+    mpi_free( &A ); mpi_free( &AA ); mpi_free( &B );
+    mpi_free( &BB ); mpi_free( &E ); mpi_free( &C );
+    mpi_free( &D ); mpi_free( &DA ); mpi_free( &CB );
 
-#define WIDTH       8 / sizeof( t_uint )
-#define A( i )      N->p + i * WIDTH
-#define ADD( i )    add64( p, A( i ), &c )
-#define NEXT        p += WIDTH; carry64( p, &c )
-#define LAST        p += WIDTH; *p = c; while( ++p < end ) *p = 0
+    return( ret );
+}
 
 /*
- * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
+ * Multiplication with Montgomery ladder in x/z coordinates,
+ * for curves in Montgomery form
  */
-static int ecp_mod_p192( mpi *N )
+static int ecp_mul_mxz( ecp_group *grp, ecp_point *R,
+                        const mpi *m, const ecp_point *P,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng )
 {
     int ret;
-    t_uint c = 0;
-    t_uint *p, *end;
+    size_t i;
+    unsigned char b;
+    ecp_point RP;
+    mpi PX;
 
-    /* Make sure we have enough blocks so that A(5) is legal */
-    MPI_CHK( mpi_grow( N, 6 * WIDTH ) );
+    ecp_point_init( &RP ); mpi_init( &PX );
 
-    p = N->p;
-    end = p + N->n;
+    /* Save PX and read from P before writing to R, in case P == R */
+    MPI_CHK( mpi_copy( &PX, &P->X ) );
+    MPI_CHK( ecp_copy( &RP, P ) );
 
-    ADD( 3 ); ADD( 5 );             NEXT; // A0 += A3 + A5
-    ADD( 3 ); ADD( 4 ); ADD( 5 );   NEXT; // A1 += A3 + A4 + A5
-    ADD( 4 ); ADD( 5 );             LAST; // A2 += A4 + A5
+    /* Set R to zero in modified x/z coordinates */
+    MPI_CHK( mpi_lset( &R->X, 1 ) );
+    MPI_CHK( mpi_lset( &R->Z, 0 ) );
+    mpi_free( &R->Y );
 
-cleanup:
-    return( ret );
-}
+    /* RP.X might be sligtly larger than P, so reduce it */
+    MOD_ADD( RP.X );
 
-#undef WIDTH
-#undef A
-#undef ADD
-#undef NEXT
-#undef LAST
-#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+    /* Randomize coordinates of the starting point */
+    if( f_rng != NULL )
+        MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
 
-#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) ||   \
-    defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) ||   \
-    defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
-/*
- * The reader is advised to first understand ecp_mod_p192() since the same
- * general structure is used here, but with additional complications:
- * (1) chunks of 32 bits, and (2) subtractions.
- */
-
-/*
- * For these primes, we need to handle data in chunks of 32 bits.
- * This makes it more complicated if we use 64 bits limbs in MPI,
- * which prevents us from using a uniform access method as for p192.
- *
- * So, we define a mini abstraction layer to access 32 bit chunks,
- * load them in 'cur' for work, and store them back from 'cur' when done.
- *
- * While at it, also define the size of N in terms of 32-bit chunks.
- */
-#define LOAD32      cur = A( i );
-
-#if defined(POLARSSL_HAVE_INT8)     /* 8 bit */
-
-#define MAX32       N->n / 4
-#define A( j )      (uint32_t)( N->p[4*j+0]       ) |  \
-                              ( N->p[4*j+1] << 8  ) |  \
-                              ( N->p[4*j+2] << 16 ) |  \
-                              ( N->p[4*j+3] << 24 )
-#define STORE32     N->p[4*i+0] = (uint8_t)( cur       );   \
-                    N->p[4*i+1] = (uint8_t)( cur >> 8  );   \
-                    N->p[4*i+2] = (uint8_t)( cur >> 16 );   \
-                    N->p[4*i+3] = (uint8_t)( cur >> 24 );
-
-#elif defined(POLARSSL_HAVE_INT16)  /* 16 bit */
-
-#define MAX32       N->n / 2
-#define A( j )      (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 )
-#define STORE32     N->p[2*i+0] = (uint16_t)( cur       );  \
-                    N->p[2*i+1] = (uint16_t)( cur >> 16 );
-
-#elif defined(POLARSSL_HAVE_INT32)  /* 32 bit */
-
-#define MAX32       N->n
-#define A( j )      N->p[j]
-#define STORE32     N->p[i] = cur;
-
-#else                               /* 64-bit */
-
-#define MAX32       N->n * 2
-#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] )
-#define STORE32                                   \
-    if( i % 2 ) {                                 \
-        N->p[i/2] &= 0x00000000FFFFFFFF;          \
-        N->p[i/2] |= ((uint64_t) cur) << 32;      \
-    } else {                                      \
-        N->p[i/2] &= 0xFFFFFFFF00000000;          \
-        N->p[i/2] |= (uint64_t) cur;              \
+    /* Loop invariant: R = result so far, RP = R + P */
+    i = mpi_msb( m ); /* one past the (zero-based) most significant bit */
+    while( i-- > 0 )
+    {
+        b = mpi_get_bit( m, i );
+        /*
+         *  if (b) R = 2R + P else R = 2R,
+         * which is:
+         *  if (b) double_add( RP, R, RP, R )
+         *  else   double_add( R, RP, R, RP )
+         * but using safe conditional swaps to avoid leaks
+         */
+        MPI_CHK( mpi_safe_cond_swap( &R->X, &RP.X, b ) );
+        MPI_CHK( mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
+        MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
+        MPI_CHK( mpi_safe_cond_swap( &R->X, &RP.X, b ) );
+        MPI_CHK( mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
     }
 
-#endif /* sizeof( t_uint ) */
+    MPI_CHK( ecp_normalize_mxz( grp, R ) );
 
-/*
- * Helpers for addition and subtraction of chunks, with signed carry.
- */
-static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
-{
-    *dst += src;
-    *carry += ( *dst < src );
-}
+cleanup:
+    ecp_point_free( &RP ); mpi_free( &PX );
 
-static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
-{
-    *carry -= ( *dst < src );
-    *dst -= src;
+    return( ret );
 }
 
-#define ADD( j )    add32( &cur, A( j ), &c );
-#define SUB( j )    sub32( &cur, A( j ), &c );
-
-/*
- * Helpers for the main 'loop'
- * (see fix_negative for the motivation of C)
- */
-#define INIT( b )                                           \
-    int ret;                                                \
-    signed char c = 0, cc;                                  \
-    uint32_t cur;                                           \
-    size_t i = 0, bits = b;                                 \
-    mpi C;                                                  \
-    t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ];               \
-                                                            \
-    C.s = 1;                                                \
-    C.n = b / 8 / sizeof( t_uint) + 1;                      \
-    C.p = Cp;                                               \
-    memset( Cp, 0, C.n * sizeof( t_uint ) );                \
-                                                            \
-    MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \
-    LOAD32;
-
-#define NEXT                    \
-    STORE32; i++; LOAD32;       \
-    cc = c; c = 0;              \
-    if( cc < 0 )                \
-        sub32( &cur, -cc, &c ); \
-    else                        \
-        add32( &cur, cc, &c );  \
-
-#define LAST                                    \
-    STORE32; i++;                               \
-    cur = c > 0 ? c : 0; STORE32;               \
-    cur = 0; while( ++i < MAX32 ) { STORE32; }  \
-    if( c < 0 ) fix_negative( N, c, &C, bits );
+#endif /* POLARSSL_ECP_MONTGOMERY */
 
 /*
- * If the result is negative, we get it in the form
- * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
+ * Multiplication R = m * P
  */
-static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits )
+int ecp_mul( ecp_group *grp, ecp_point *R,
+             const mpi *m, const ecp_point *P,
+             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
     int ret;
 
-    /* C = - c * 2^(bits + 32) */
-#if !defined(POLARSSL_HAVE_INT64)
-    ((void) bits);
-#else
-    if( bits == 224 )
-        C->p[ C->n - 1 ] = ((t_uint) -c) << 32;
-    else
-#endif
-        C->p[ C->n - 1 ] = (t_uint) -c;
-
-    /* N = - ( C - N ) */
-    MPI_CHK( mpi_sub_abs( N, C, N ) );
-    N->s = -1;
-
-cleanup:
-
-    return( ret );
-}
-
-#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
-/*
- * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
- */
-static int ecp_mod_p224( mpi *N )
-{
-    INIT( 224 );
+    /* Common sanity checks */
+    if( mpi_cmp_int( &P->Z, 1 ) != 0 )
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
-    SUB(  7 ); SUB( 11 );               NEXT; // A0 += -A7 - A11
-    SUB(  8 ); SUB( 12 );               NEXT; // A1 += -A8 - A12
-    SUB(  9 ); SUB( 13 );               NEXT; // A2 += -A9 - A13
-    SUB( 10 ); ADD(  7 ); ADD( 11 );    NEXT; // A3 += -A10 + A7 + A11
-    SUB( 11 ); ADD(  8 ); ADD( 12 );    NEXT; // A4 += -A11 + A8 + A12
-    SUB( 12 ); ADD(  9 ); ADD( 13 );    NEXT; // A5 += -A12 + A9 + A13
-    SUB( 13 ); ADD( 10 );               LAST; // A6 += -A13 + A10
+    if( ( ret = ecp_check_privkey( grp, m ) ) != 0 ||
+        ( ret = ecp_check_pubkey( grp, P ) ) != 0 )
+        return( ret );
 
-cleanup:
-    return( ret );
+#if defined(POLARSSL_ECP_MONTGOMERY)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY )
+        return( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
+#endif
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+        return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng ) );
+#endif
+    return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 }
-#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
 
-#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
 /*
- * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
+ * Check that an affine point is valid as a public key,
+ * short weierstrass curves (SEC1 3.2.3.1)
  */
-static int ecp_mod_p256( mpi *N )
+static int ecp_check_pubkey_sw( const ecp_group *grp, const ecp_point *pt )
 {
-    INIT( 256 );
+    int ret;
+    mpi YY, RHS;
 
-    ADD(  8 ); ADD(  9 );
-    SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 );             NEXT; // A0
+    /* pt coordinates must be normalized for our checks */
+    if( mpi_cmp_int( &pt->X, 0 ) < 0 ||
+        mpi_cmp_int( &pt->Y, 0 ) < 0 ||
+        mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
+        mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
+        return( POLARSSL_ERR_ECP_INVALID_KEY );
 
-    ADD(  9 ); ADD( 10 );
-    SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 );             NEXT; // A1
+    mpi_init( &YY ); mpi_init( &RHS );
 
-    ADD( 10 ); ADD( 11 );
-    SUB( 13 ); SUB( 14 ); SUB( 15 );                        NEXT; // A2
+    /*
+     * YY = Y^2
+     * RHS = X (X^2 + A) + B = X^3 + A X + B
+     */
+    MPI_CHK( mpi_mul_mpi( &YY,  &pt->Y,   &pt->Y  ) );  MOD_MUL( YY  );
+    MPI_CHK( mpi_mul_mpi( &RHS, &pt->X,   &pt->X  ) );  MOD_MUL( RHS );
 
-    ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
-    SUB( 15 ); SUB(  8 ); SUB(  9 );                        NEXT; // A3
+    /* Special case for A = -3 */
+    if( grp->A.p == NULL )
+    {
+        MPI_CHK( mpi_sub_int( &RHS, &RHS, 3       ) );  MOD_SUB( RHS );
+    }
+    else
+    {
+        MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->A ) );  MOD_ADD( RHS );
+    }
 
-    ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
-    SUB(  9 ); SUB( 10 );                                   NEXT; // A4
+    MPI_CHK( mpi_mul_mpi( &RHS, &RHS,     &pt->X  ) );  MOD_MUL( RHS );
+    MPI_CHK( mpi_add_mpi( &RHS, &RHS,     &grp->B ) );  MOD_ADD( RHS );
 
-    ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
-    SUB( 10 ); SUB( 11 );                                   NEXT; // A5
+    if( mpi_cmp_mpi( &YY, &RHS ) != 0 )
+        ret = POLARSSL_ERR_ECP_INVALID_KEY;
 
-    ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
-    SUB(  8 ); SUB(  9 );                                   NEXT; // A6
+cleanup:
 
-    ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
-    SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 );             LAST; // A7
+    mpi_free( &YY ); mpi_free( &RHS );
 
-cleanup:
     return( ret );
 }
-#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */
 
-#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+
+#if defined(POLARSSL_ECP_MONTGOMERY)
 /*
- * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
+ * Check validity of a public key for Montgomery curves with x-only schemes
  */
-static int ecp_mod_p384( mpi *N )
+static int ecp_check_pubkey_mx( const ecp_group *grp, const ecp_point *pt )
 {
-    INIT( 384 );
-
-    ADD( 12 ); ADD( 21 ); ADD( 20 );
-    SUB( 23 );                                              NEXT; // A0
-
-    ADD( 13 ); ADD( 22 ); ADD( 23 );
-    SUB( 12 ); SUB( 20 );                                   NEXT; // A2
-
-    ADD( 14 ); ADD( 23 );
-    SUB( 13 ); SUB( 21 );                                   NEXT; // A2
-
-    ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
-    SUB( 14 ); SUB( 22 ); SUB( 23 );                        NEXT; // A3
-
-    ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
-    SUB( 15 ); SUB( 23 ); SUB( 23 );                        NEXT; // A4
-
-    ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
-    SUB( 16 );                                              NEXT; // A5
-
-    ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
-    SUB( 17 );                                              NEXT; // A6
-
-    ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
-    SUB( 18 );                                              NEXT; // A7
-
-    ADD( 20 ); ADD( 17 ); ADD( 16 );
-    SUB( 19 );                                              NEXT; // A8
-
-    ADD( 21 ); ADD( 18 ); ADD( 17 );
-    SUB( 20 );                                              NEXT; // A9
-
-    ADD( 22 ); ADD( 19 ); ADD( 18 );
-    SUB( 21 );                                              NEXT; // A10
-
-    ADD( 23 ); ADD( 20 ); ADD( 19 );
-    SUB( 22 );                                              LAST; // A11
+    /* [M255 p. 5] Just check X is the correct number of bytes */
+    if( mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
+        return( POLARSSL_ERR_ECP_INVALID_KEY );
 
-cleanup:
-    return( ret );
+    return( 0 );
 }
-#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+#endif /* POLARSSL_ECP_MONTGOMERY */
 
-#undef A
-#undef LOAD32
-#undef STORE32
-#undef MAX32
-#undef INIT
-#undef NEXT
-#undef LAST
+/*
+ * Check that a point is valid as a public key
+ */
+int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt )
+{
+    /* Must use affine coordinates */
+    if( mpi_cmp_int( &pt->Z, 1 ) != 0 )
+        return( POLARSSL_ERR_ECP_INVALID_KEY );
 
-#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED ||
-          POLARSSL_ECP_DP_SECP256R1_ENABLED ||
-          POLARSSL_ECP_DP_SECP384R1_ENABLED */
+#if defined(POLARSSL_ECP_MONTGOMERY)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY )
+        return( ecp_check_pubkey_mx( grp, pt ) );
+#endif
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+        return( ecp_check_pubkey_sw( grp, pt ) );
+#endif
+    return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+}
 
-#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
 /*
- * Here we have an actual Mersenne prime, so things are more straightforward.
- * However, chunks are aligned on a 'weird' boundary (521 bits).
+ * Check that an mpi is valid as a private key
  */
+int ecp_check_privkey( const ecp_group *grp, const mpi *d )
+{
+#if defined(POLARSSL_ECP_MONTGOMERY)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY )
+    {
+        /* see [M255] page 5 */
+        if( mpi_get_bit( d, 0 ) != 0 ||
+            mpi_get_bit( d, 1 ) != 0 ||
+            mpi_get_bit( d, 2 ) != 0 ||
+            mpi_msb( d ) - 1 != grp->nbits ) /* mpi_msb is one-based! */
+            return( POLARSSL_ERR_ECP_INVALID_KEY );
+        else
+            return( 0 );
+    }
+#endif /* POLARSSL_ECP_MONTGOMERY */
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+    {
+        /* see SEC1 3.2 */
+        if( mpi_cmp_int( d, 1 ) < 0 ||
+            mpi_cmp_mpi( d, &grp->N ) >= 0 )
+            return( POLARSSL_ERR_ECP_INVALID_KEY );
+        else
+            return( 0 );
+    }
+#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */
 
-/* Size of p521 in terms of t_uint */
-#define P521_WIDTH      ( 521 / 8 / sizeof( t_uint ) + 1 )
-
-/* Bits to keep in the most significant t_uint */
-#if defined(POLARSSL_HAVE_INT8)
-#define P521_MASK       0x01
-#else
-#define P521_MASK       0x01FF
-#endif
+    return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
+}
 
 /*
- * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
- * Write N as A1 + 2^521 A0, return A0 + A1
+ * Generate a keypair
  */
-static int ecp_mod_p521( mpi *N )
+int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
 {
     int ret;
-    size_t i;
-    mpi M;
-    t_uint Mp[P521_WIDTH + 1];
-    /* Worst case for the size of M is when t_uint is 16 bits:
-     * we need to hold bits 513 to 1056, which is 34 limbs, that is
-     * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
+    size_t n_size = ( grp->nbits + 7 ) / 8;
 
-    if( N->n < P521_WIDTH )
-        return( 0 );
+#if defined(POLARSSL_ECP_MONTGOMERY)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_MONTGOMERY )
+    {
+        /* [M225] page 5 */
+        size_t b;
+
+        MPI_CHK( mpi_fill_random( d, n_size, f_rng, p_rng ) );
 
-    /* M = A1 */
-    M.s = 1;
-    M.n = N->n - ( P521_WIDTH - 1 );
-    if( M.n > P521_WIDTH + 1 )
-        M.n = P521_WIDTH + 1;
-    M.p = Mp;
-    memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) );
-    MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) );
+        /* Make sure the most significant bit is nbits */
+        b = mpi_msb( d ) - 1; /* mpi_msb is one-based */
+        if( b > grp->nbits )
+            MPI_CHK( mpi_shift_r( d, b - grp->nbits ) );
+        else
+            MPI_CHK( mpi_set_bit( d, grp->nbits, 1 ) );
 
-    /* N = A0 */
-    N->p[P521_WIDTH - 1] &= P521_MASK;
-    for( i = P521_WIDTH; i < N->n; i++ )
-        N->p[i] = 0;
+        /* Make sure the last three bits are unset */
+        MPI_CHK( mpi_set_bit( d, 0, 0 ) );
+        MPI_CHK( mpi_set_bit( d, 1, 0 ) );
+        MPI_CHK( mpi_set_bit( d, 2, 0 ) );
+    }
+    else
+#endif /* POLARSSL_ECP_MONTGOMERY */
+#if defined(POLARSSL_ECP_SHORT_WEIERSTRASS)
+    if( ecp_get_type( grp ) == POLARSSL_ECP_TYPE_SHORT_WEIERSTRASS )
+    {
+        /* SEC1 3.2.1: Generate d such that 1 <= n < N */
+        int count = 0;
+        unsigned char rnd[POLARSSL_ECP_MAX_BYTES];
 
-    /* N = A0 + A1 */
-    MPI_CHK( mpi_add_abs( N, N, &M ) );
+        /*
+         * Match the procedure given in RFC 6979 (deterministic ECDSA):
+         * - use the same byte ordering;
+         * - keep the leftmost nbits bits of the generated octet string;
+         * - try until result is in the desired range.
+         * This also avoids any biais, which is especially important for ECDSA.
+         */
+        do
+        {
+            MPI_CHK( f_rng( p_rng, rnd, n_size ) );
+            MPI_CHK( mpi_read_binary( d, rnd, n_size ) );
+            MPI_CHK( mpi_shift_r( d, 8 * n_size - grp->nbits ) );
+
+            /*
+             * Each try has at worst a probability 1/2 of failing (the msb has
+             * a probability 1/2 of being 0, and then the result will be < N),
+             * so after 30 tries failure probability is a most 2**(-30).
+             *
+             * For most curves, 1 try is enough with overwhelming probability,
+             * since N starts with a lot of 1s in binary, but some curves
+             * such as secp224k1 are actually very close to the worst case.
+             */
+            if( ++count > 30 )
+                return( POLARSSL_ERR_ECP_RANDOM_FAILED );
+        }
+        while( mpi_cmp_int( d, 1 ) < 0 ||
+               mpi_cmp_mpi( d, &grp->N ) >= 0 );
+    }
+    else
+#endif /* POLARSSL_ECP_SHORT_WEIERSTRASS */
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
 cleanup:
-    return( ret );
+    if( ret != 0 )
+        return( ret );
+
+    return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) );
 }
 
-#undef P521_WIDTH
-#undef P521_MASK
-#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+/*
+ * Generate a keypair, prettier wrapper
+ */
+int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
 
-#endif /* POLARSSL_ECP_NIST_OPTIM */
+    if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 )
+        return( ret );
+
+    return( ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
+}
 
 #if defined(POLARSSL_SELF_TEST)
 
@@ -2003,17 +1907,16 @@ int ecp_self_test( int verbose )
     ecp_group grp;
     ecp_point R, P;
     mpi m;
-    unsigned long add_c_prev, dbl_c_prev;
+    unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
     /* exponents especially adapted for secp192r1 */
     const char *exponents[] =
     {
-        "000000000000000000000000000000000000000000000000", /* zero */
         "000000000000000000000000000000000000000000000001", /* one */
-        "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* N */
+        "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
         "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
-        "400000000000000000000000000000000000000000000000",
-        "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
-        "555555555555555555555555555555555555555555555555",
+        "400000000000000000000000000000000000000000000000", /* one and zeros */
+        "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
+        "555555555555555555555555555555555555555555555555", /* 101010... */
     };
 
     ecp_group_init( &grp );
@@ -2029,7 +1932,7 @@ int ecp_self_test( int verbose )
 #endif
 
     if( verbose != 0 )
-        printf( "  ECP test #1 (constant op_count, base point G): " );
+        polarssl_printf( "  ECP test #1 (constant op_count, base point G): " );
 
     /* Do a dummy multiplication first to trigger precomputation */
     MPI_CHK( mpi_lset( &m, 2 ) );
@@ -2037,6 +1940,7 @@ int ecp_self_test( int verbose )
 
     add_count = 0;
     dbl_count = 0;
+    mul_count = 0;
     MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) );
     MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
 
@@ -2044,16 +1948,20 @@ int ecp_self_test( int verbose )
     {
         add_c_prev = add_count;
         dbl_c_prev = dbl_count;
+        mul_c_prev = mul_count;
         add_count = 0;
         dbl_count = 0;
+        mul_count = 0;
 
         MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) );
         MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
 
-        if( add_count != add_c_prev || dbl_count != dbl_c_prev )
+        if( add_count != add_c_prev ||
+            dbl_count != dbl_c_prev ||
+            mul_count != mul_c_prev )
         {
             if( verbose != 0 )
-                printf( "failed (%zu)\n", i );
+                polarssl_printf( "failed (%u)\n", (unsigned int) i );
 
             ret = 1;
             goto cleanup;
@@ -2061,14 +1969,15 @@ int ecp_self_test( int verbose )
     }
 
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
     if( verbose != 0 )
-        printf( "  ECP test #2 (constant op_count, other point): " );
+        polarssl_printf( "  ECP test #2 (constant op_count, other point): " );
     /* We computed P = 2G last time, use it */
 
     add_count = 0;
     dbl_count = 0;
+    mul_count = 0;
     MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) );
     MPI_CHK( ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
 
@@ -2076,16 +1985,20 @@ int ecp_self_test( int verbose )
     {
         add_c_prev = add_count;
         dbl_c_prev = dbl_count;
+        mul_c_prev = mul_count;
         add_count = 0;
         dbl_count = 0;
+        mul_count = 0;
 
         MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) );
         MPI_CHK( ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
 
-        if( add_count != add_c_prev || dbl_count != dbl_c_prev )
+        if( add_count != add_c_prev ||
+            dbl_count != dbl_c_prev ||
+            mul_count != mul_c_prev )
         {
             if( verbose != 0 )
-                printf( "failed (%zu)\n", i );
+                polarssl_printf( "failed (%u)\n", (unsigned int) i );
 
             ret = 1;
             goto cleanup;
@@ -2093,12 +2006,12 @@ int ecp_self_test( int verbose )
     }
 
     if( verbose != 0 )
-        printf( "passed\n" );
+        polarssl_printf( "passed\n" );
 
 cleanup:
 
     if( ret < 0 && verbose != 0 )
-        printf( "Unexpected error, return code = %08X\n", ret );
+        polarssl_printf( "Unexpected error, return code = %08X\n", ret );
 
     ecp_group_free( &grp );
     ecp_point_free( &R );
@@ -2106,11 +2019,11 @@ cleanup:
     mpi_free( &m );
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_ECP_C */
diff --git a/pdns/ext/polarssl/library/ecp_curves.c b/pdns/ext/polarssl/library/ecp_curves.c
new file mode 100644 (file)
index 0000000..4c0018c
--- /dev/null
@@ -0,0 +1,1380 @@
+/*
+ *  Elliptic curves over GF(p): curve-specific data and functions
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_ECP_C)
+
+#include "polarssl/ecp.h"
+
+#if defined(_MSC_VER) && !defined(inline)
+#define inline _inline
+#else
+#if defined(__ARMCC_VERSION) && !defined(inline)
+#define inline __inline
+#endif /* __ARMCC_VERSION */
+#endif /*_MSC_VER */
+
+/*
+ * Conversion macros for embedded constants:
+ * build lists of t_uint's from lists of unsigned char's grouped by 8, 4 or 2
+ */
+#if defined(POLARSSL_HAVE_INT8)
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    a, b, c, d, e, f, g, h
+
+#define BYTES_TO_T_UINT_4( a, b, c, d )             \
+    a, b, c, d
+
+#define BYTES_TO_T_UINT_2( a, b )                   \
+    a, b
+
+#elif defined(POLARSSL_HAVE_INT16)
+
+#define BYTES_TO_T_UINT_2( a, b )                   \
+    ( (t_uint) a << 0 ) |                           \
+    ( (t_uint) b << 8 )
+
+#define BYTES_TO_T_UINT_4( a, b, c, d )             \
+    BYTES_TO_T_UINT_2( a, b ),                      \
+    BYTES_TO_T_UINT_2( c, d )
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    BYTES_TO_T_UINT_2( a, b ),                      \
+    BYTES_TO_T_UINT_2( c, d ),                      \
+    BYTES_TO_T_UINT_2( e, f ),                      \
+    BYTES_TO_T_UINT_2( g, h )
+
+#elif defined(POLARSSL_HAVE_INT32)
+
+#define BYTES_TO_T_UINT_4( a, b, c, d )             \
+    ( (t_uint) a <<  0 ) |                          \
+    ( (t_uint) b <<  8 ) |                          \
+    ( (t_uint) c << 16 ) |                          \
+    ( (t_uint) d << 24 )
+
+#define BYTES_TO_T_UINT_2( a, b )                   \
+    BYTES_TO_T_UINT_4( a, b, 0, 0 )
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    BYTES_TO_T_UINT_4( a, b, c, d ),                \
+    BYTES_TO_T_UINT_4( e, f, g, h )
+
+#else /* 64-bits */
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    ( (t_uint) a <<  0 ) |                          \
+    ( (t_uint) b <<  8 ) |                          \
+    ( (t_uint) c << 16 ) |                          \
+    ( (t_uint) d << 24 ) |                          \
+    ( (t_uint) e << 32 ) |                          \
+    ( (t_uint) f << 40 ) |                          \
+    ( (t_uint) g << 48 ) |                          \
+    ( (t_uint) h << 56 )
+
+#define BYTES_TO_T_UINT_4( a, b, c, d )             \
+    BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 )
+
+#define BYTES_TO_T_UINT_2( a, b )                   \
+    BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 )
+
+#endif /* bits in t_uint */
+
+/*
+ * Note: the constants are in little-endian order
+ * to be directly usable in MPIs
+ */
+
+/*
+ * Domain parameters for secp192r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+static const t_uint secp192r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp192r1_b[] = {
+    BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ),
+    BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ),
+    BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ),
+};
+static const t_uint secp192r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ),
+    BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ),
+};
+static const t_uint secp192r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ),
+    BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ),
+    BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ),
+};
+static const t_uint secp192r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ),
+    BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+
+/*
+ * Domain parameters for secp224r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+static const t_uint secp224r1_p[] = {
+    BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+};
+static const t_uint secp224r1_b[] = {
+    BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ),
+    BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ),
+    BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ),
+    BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ),
+};
+static const t_uint secp224r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ),
+    BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ),
+    BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ),
+    BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ),
+};
+static const t_uint secp224r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ),
+    BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ),
+    BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ),
+    BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ),
+};
+static const t_uint secp224r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ),
+    BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
+
+/*
+ * Domain parameters for secp256r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+static const t_uint secp256r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp256r1_b[] = {
+    BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ),
+    BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ),
+    BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ),
+    BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ),
+};
+static const t_uint secp256r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ),
+    BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ),
+    BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ),
+    BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ),
+};
+static const t_uint secp256r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ),
+    BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ),
+    BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ),
+    BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ),
+};
+static const t_uint secp256r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ),
+    BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+
+/*
+ * Domain parameters for secp384r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+static const t_uint secp384r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp384r1_b[] = {
+    BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ),
+    BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ),
+    BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ),
+    BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ),
+    BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ),
+    BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ),
+};
+static const t_uint secp384r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ),
+    BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ),
+    BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ),
+    BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ),
+    BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ),
+    BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ),
+};
+static const t_uint secp384r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ),
+    BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ),
+    BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ),
+    BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ),
+    BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ),
+    BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ),
+};
+static const t_uint secp384r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ),
+    BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ),
+    BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+
+/*
+ * Domain parameters for secp521r1
+ */
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+static const t_uint secp521r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+};
+static const t_uint secp521r1_b[] = {
+    BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ),
+    BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ),
+    BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ),
+    BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ),
+    BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ),
+    BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ),
+    BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ),
+    BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ),
+    BYTES_TO_T_UINT_2( 0x51, 0x00 ),
+};
+static const t_uint secp521r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ),
+    BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ),
+    BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ),
+    BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ),
+    BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ),
+    BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ),
+    BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ),
+    BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ),
+    BYTES_TO_T_UINT_2( 0xC6, 0x00 ),
+};
+static const t_uint secp521r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ),
+    BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ),
+    BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ),
+    BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ),
+    BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ),
+    BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ),
+    BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ),
+    BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ),
+    BYTES_TO_T_UINT_2( 0x18, 0x01 ),
+};
+static const t_uint secp521r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ),
+    BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ),
+    BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ),
+    BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ),
+    BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+};
+#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+static const t_uint secp192k1_p[] = {
+    BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp192k1_a[] = {
+    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const t_uint secp192k1_b[] = {
+    BYTES_TO_T_UINT_2( 0x03, 0x00 ),
+};
+static const t_uint secp192k1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ),
+    BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ),
+    BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ),
+};
+static const t_uint secp192k1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ),
+    BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ),
+    BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ),
+};
+static const t_uint secp192k1_n[] = {
+    BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ),
+    BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+static const t_uint secp224k1_p[] = {
+    BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp224k1_a[] = {
+    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const t_uint secp224k1_b[] = {
+    BYTES_TO_T_UINT_2( 0x05, 0x00 ),
+};
+static const t_uint secp224k1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ),
+    BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ),
+    BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ),
+    BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ),
+};
+static const t_uint secp224k1_gy[] = {
+    BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ),
+    BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ),
+    BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ),
+    BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ),
+};
+static const t_uint secp224k1_n[] = {
+    BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ),
+    BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ),
+};
+#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+static const t_uint secp256k1_p[] = {
+    BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const t_uint secp256k1_a[] = {
+    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const t_uint secp256k1_b[] = {
+    BYTES_TO_T_UINT_2( 0x07, 0x00 ),
+};
+static const t_uint secp256k1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ),
+    BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ),
+    BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ),
+    BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ),
+};
+static const t_uint secp256k1_gy[] = {
+    BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ),
+    BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ),
+    BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ),
+    BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ),
+};
+static const t_uint secp256k1_n[] = {
+    BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ),
+    BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ),
+    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
+ */
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+static const t_uint brainpoolP256r1_p[] = {
+    BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ),
+    BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ),
+    BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
+    BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+};
+static const t_uint brainpoolP256r1_a[] = {
+    BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ),
+    BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ),
+    BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ),
+    BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ),
+};
+static const t_uint brainpoolP256r1_b[] = {
+    BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ),
+    BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ),
+    BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ),
+    BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ),
+};
+static const t_uint brainpoolP256r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ),
+    BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ),
+    BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ),
+    BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ),
+};
+static const t_uint brainpoolP256r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ),
+    BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ),
+    BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ),
+    BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ),
+};
+static const t_uint brainpoolP256r1_n[] = {
+    BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ),
+    BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ),
+    BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
+    BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+};
+#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
+ */
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+static const t_uint brainpoolP384r1_p[] = {
+    BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ),
+    BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ),
+    BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ),
+    BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
+    BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
+    BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+};
+static const t_uint brainpoolP384r1_a[] = {
+    BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+    BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ),
+    BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ),
+    BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ),
+    BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ),
+    BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ),
+};
+static const t_uint brainpoolP384r1_b[] = {
+    BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ),
+    BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ),
+    BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ),
+    BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ),
+    BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ),
+    BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+};
+static const t_uint brainpoolP384r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ),
+    BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ),
+    BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ),
+    BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ),
+    BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ),
+    BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ),
+};
+static const t_uint brainpoolP384r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ),
+    BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ),
+    BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ),
+    BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ),
+    BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ),
+    BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ),
+};
+static const t_uint brainpoolP384r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ),
+    BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ),
+    BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ),
+    BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
+    BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
+    BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+};
+#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
+ */
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+static const t_uint brainpoolP512r1_p[] = {
+    BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ),
+    BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ),
+    BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ),
+    BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ),
+    BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
+    BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
+    BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
+    BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+};
+static const t_uint brainpoolP512r1_a[] = {
+    BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ),
+    BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ),
+    BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ),
+    BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ),
+    BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ),
+    BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ),
+    BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ),
+    BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ),
+};
+static const t_uint brainpoolP512r1_b[] = {
+    BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ),
+    BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ),
+    BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ),
+    BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ),
+    BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ),
+    BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ),
+    BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ),
+    BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ),
+};
+static const t_uint brainpoolP512r1_gx[] = {
+    BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ),
+    BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ),
+    BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ),
+    BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ),
+    BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ),
+    BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ),
+    BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ),
+    BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ),
+};
+static const t_uint brainpoolP512r1_gy[] = {
+    BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ),
+    BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ),
+    BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ),
+    BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ),
+    BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ),
+    BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ),
+    BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ),
+    BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ),
+};
+static const t_uint brainpoolP512r1_n[] = {
+    BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ),
+    BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ),
+    BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ),
+    BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ),
+    BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
+    BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
+    BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
+    BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+};
+#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
+
+/*
+ * Create an MPI from embedded constants
+ * (assumes len is an exact multiple of sizeof t_uint)
+ */
+static inline void ecp_mpi_load( mpi *X, const t_uint *p, size_t len )
+{
+    X->s = 1;
+    X->n = len / sizeof( t_uint );
+    X->p = (t_uint *) p;
+}
+
+/*
+ * Set an MPI to static value 1
+ */
+static inline void ecp_mpi_set1( mpi *X )
+{
+    static t_uint one[] = { 1 };
+    X->s = 1;
+    X->n = 1;
+    X->p = one;
+}
+
+/*
+ * Make group available from embedded constants
+ */
+static int ecp_group_load( ecp_group *grp,
+                           const t_uint *p,  size_t plen,
+                           const t_uint *a,  size_t alen,
+                           const t_uint *b,  size_t blen,
+                           const t_uint *gx, size_t gxlen,
+                           const t_uint *gy, size_t gylen,
+                           const t_uint *n,  size_t nlen)
+{
+    ecp_mpi_load( &grp->P, p, plen );
+    if( a != NULL )
+        ecp_mpi_load( &grp->A, a, alen );
+    ecp_mpi_load( &grp->B, b, blen );
+    ecp_mpi_load( &grp->N, n, nlen );
+
+    ecp_mpi_load( &grp->G.X, gx, gxlen );
+    ecp_mpi_load( &grp->G.Y, gy, gylen );
+    ecp_mpi_set1( &grp->G.Z );
+
+    grp->pbits = mpi_msb( &grp->P );
+    grp->nbits = mpi_msb( &grp->N );
+
+    grp->h = 1;
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_ECP_NIST_OPTIM)
+/* Forward declarations */
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+static int ecp_mod_p192( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+static int ecp_mod_p224( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+static int ecp_mod_p256( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+static int ecp_mod_p384( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+static int ecp_mod_p521( mpi * );
+#endif
+
+#define NIST_MODP( P )      grp->modp = ecp_mod_ ## P;
+#else
+#define NIST_MODP( P )
+#endif /* POLARSSL_ECP_NIST_OPTIM */
+
+/* Additional forward declarations */
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+static int ecp_mod_p255( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+static int ecp_mod_p192k1( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+static int ecp_mod_p224k1( mpi * );
+#endif
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+static int ecp_mod_p256k1( mpi * );
+#endif
+
+#define LOAD_GROUP_A( G )   ecp_group_load( grp,            \
+                            G ## _p,  sizeof( G ## _p  ),   \
+                            G ## _a,  sizeof( G ## _a  ),   \
+                            G ## _b,  sizeof( G ## _b  ),   \
+                            G ## _gx, sizeof( G ## _gx ),   \
+                            G ## _gy, sizeof( G ## _gy ),   \
+                            G ## _n,  sizeof( G ## _n  ) )
+
+#define LOAD_GROUP( G )     ecp_group_load( grp,            \
+                            G ## _p,  sizeof( G ## _p  ),   \
+                            NULL,     0,                    \
+                            G ## _b,  sizeof( G ## _b  ),   \
+                            G ## _gx, sizeof( G ## _gx ),   \
+                            G ## _gy, sizeof( G ## _gy ),   \
+                            G ## _n,  sizeof( G ## _n  ) )
+
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+/*
+ * Specialized function for creating the Curve25519 group
+ */
+static int ecp_use_curve25519( ecp_group *grp )
+{
+    int ret;
+
+    /* Actually ( A + 2 ) / 4 */
+    MPI_CHK( mpi_read_string( &grp->A, 16, "01DB42" ) );
+
+    /* P = 2^255 - 19 */
+    MPI_CHK( mpi_lset( &grp->P, 1 ) );
+    MPI_CHK( mpi_shift_l( &grp->P, 255 ) );
+    MPI_CHK( mpi_sub_int( &grp->P, &grp->P, 19 ) );
+    grp->pbits = mpi_msb( &grp->P );
+
+    /* Y intentionaly not set, since we use x/z coordinates.
+     * This is used as a marker to identify Montgomery curves! */
+    MPI_CHK( mpi_lset( &grp->G.X, 9 ) );
+    MPI_CHK( mpi_lset( &grp->G.Z, 1 ) );
+    mpi_free( &grp->G.Y );
+
+    /* Actually, the required msb for private keys */
+    grp->nbits = 254;
+
+cleanup:
+    if( ret != 0 )
+        ecp_group_free( grp );
+
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_M255_ENABLED */
+
+/*
+ * Set a group using well-known domain parameters
+ */
+int ecp_use_known_dp( ecp_group *grp, ecp_group_id id )
+{
+    ecp_group_free( grp );
+
+    grp->id = id;
+
+    switch( id )
+    {
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP192R1:
+            NIST_MODP( p192 );
+            return( LOAD_GROUP( secp192r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP224R1:
+            NIST_MODP( p224 );
+            return( LOAD_GROUP( secp224r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP256R1:
+            NIST_MODP( p256 );
+            return( LOAD_GROUP( secp256r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP384R1:
+            NIST_MODP( p384 );
+            return( LOAD_GROUP( secp384r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+        case POLARSSL_ECP_DP_SECP521R1:
+            NIST_MODP( p521 );
+            return( LOAD_GROUP( secp521r1 ) );
+#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+        case POLARSSL_ECP_DP_SECP192K1:
+            grp->modp = ecp_mod_p192k1;
+            return( LOAD_GROUP_A( secp192k1 ) );
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+        case POLARSSL_ECP_DP_SECP224K1:
+            grp->modp = ecp_mod_p224k1;
+            return( LOAD_GROUP_A( secp224k1 ) );
+#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+        case POLARSSL_ECP_DP_SECP256K1:
+            grp->modp = ecp_mod_p256k1;
+            return( LOAD_GROUP_A( secp256k1 ) );
+#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+        case POLARSSL_ECP_DP_BP256R1:
+            return( LOAD_GROUP_A( brainpoolP256r1 ) );
+#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+        case POLARSSL_ECP_DP_BP384R1:
+            return( LOAD_GROUP_A( brainpoolP384r1 ) );
+#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+        case POLARSSL_ECP_DP_BP512R1:
+            return( LOAD_GROUP_A( brainpoolP512r1 ) );
+#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+        case POLARSSL_ECP_DP_M255:
+            grp->modp = ecp_mod_p255;
+            return( ecp_use_curve25519( grp ) );
+#endif /* POLARSSL_ECP_DP_M255_ENABLED */
+
+        default:
+            ecp_group_free( grp );
+            return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
+    }
+}
+
+#if defined(POLARSSL_ECP_NIST_OPTIM)
+/*
+ * Fast reduction modulo the primes used by the NIST curves.
+ *
+ * These functions are critical for speed, but not needed for correct
+ * operations. So, we make the choice to heavily rely on the internals of our
+ * bignum library, which creates a tight coupling between these functions and
+ * our MPI implementation.  However, the coupling between the ECP module and
+ * MPI remains loose, since these functions can be deactivated at will.
+ */
+
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+/*
+ * Compared to the way things are presented in FIPS 186-3 D.2,
+ * we proceed in columns, from right (least significant chunk) to left,
+ * adding chunks to N in place, and keeping a carry for the next chunk.
+ * This avoids moving things around in memory, and uselessly adding zeros,
+ * compared to the more straightforward, line-oriented approach.
+ *
+ * For this prime we need to handle data in chunks of 64 bits.
+ * Since this is always a multiple of our basic t_uint, we can
+ * use a t_uint * to designate such a chunk, and small loops to handle it.
+ */
+
+/* Add 64-bit chunks (dst += src) and update carry */
+static inline void add64( t_uint *dst, t_uint *src, t_uint *carry )
+{
+    unsigned char i;
+    t_uint c = 0;
+    for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ )
+    {
+        *dst += c;      c  = ( *dst < c );
+        *dst += *src;   c += ( *dst < *src );
+    }
+    *carry += c;
+}
+
+/* Add carry to a 64-bit chunk and update carry */
+static inline void carry64( t_uint *dst, t_uint *carry )
+{
+    unsigned char i;
+    for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ )
+    {
+        *dst += *carry;
+        *carry  = ( *dst < *carry );
+    }
+}
+
+#define WIDTH       8 / sizeof( t_uint )
+#define A( i )      N->p + i * WIDTH
+#define ADD( i )    add64( p, A( i ), &c )
+#define NEXT        p += WIDTH; carry64( p, &c )
+#define LAST        p += WIDTH; *p = c; while( ++p < end ) *p = 0
+
+/*
+ * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
+ */
+static int ecp_mod_p192( mpi *N )
+{
+    int ret;
+    t_uint c = 0;
+    t_uint *p, *end;
+
+    /* Make sure we have enough blocks so that A(5) is legal */
+    MPI_CHK( mpi_grow( N, 6 * WIDTH ) );
+
+    p = N->p;
+    end = p + N->n;
+
+    ADD( 3 ); ADD( 5 );             NEXT; // A0 += A3 + A5
+    ADD( 3 ); ADD( 4 ); ADD( 5 );   NEXT; // A1 += A3 + A4 + A5
+    ADD( 4 ); ADD( 5 );             LAST; // A2 += A4 + A5
+
+cleanup:
+    return( ret );
+}
+
+#undef WIDTH
+#undef A
+#undef ADD
+#undef NEXT
+#undef LAST
+#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+/*
+ * The reader is advised to first understand ecp_mod_p192() since the same
+ * general structure is used here, but with additional complications:
+ * (1) chunks of 32 bits, and (2) subtractions.
+ */
+
+/*
+ * For these primes, we need to handle data in chunks of 32 bits.
+ * This makes it more complicated if we use 64 bits limbs in MPI,
+ * which prevents us from using a uniform access method as for p192.
+ *
+ * So, we define a mini abstraction layer to access 32 bit chunks,
+ * load them in 'cur' for work, and store them back from 'cur' when done.
+ *
+ * While at it, also define the size of N in terms of 32-bit chunks.
+ */
+#define LOAD32      cur = A( i );
+
+#if defined(POLARSSL_HAVE_INT8)     /* 8 bit */
+
+#define MAX32       N->n / 4
+#define A( j )      (uint32_t)( N->p[4*j+0]       ) |  \
+                              ( N->p[4*j+1] << 8  ) |  \
+                              ( N->p[4*j+2] << 16 ) |  \
+                              ( N->p[4*j+3] << 24 )
+#define STORE32     N->p[4*i+0] = (t_uint)( cur       );   \
+                    N->p[4*i+1] = (t_uint)( cur >> 8  );   \
+                    N->p[4*i+2] = (t_uint)( cur >> 16 );   \
+                    N->p[4*i+3] = (t_uint)( cur >> 24 );
+
+#elif defined(POLARSSL_HAVE_INT16)  /* 16 bit */
+
+#define MAX32       N->n / 2
+#define A( j )      (uint32_t)( N->p[2*j] ) | ( N->p[2*j+1] << 16 )
+#define STORE32     N->p[2*i+0] = (t_uint)( cur       );  \
+                    N->p[2*i+1] = (t_uint)( cur >> 16 );
+
+#elif defined(POLARSSL_HAVE_INT32)  /* 32 bit */
+
+#define MAX32       N->n
+#define A( j )      N->p[j]
+#define STORE32     N->p[i] = cur;
+
+#else                               /* 64-bit */
+
+#define MAX32       N->n * 2
+#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] )
+#define STORE32                                   \
+    if( i % 2 ) {                                 \
+        N->p[i/2] &= 0x00000000FFFFFFFF;          \
+        N->p[i/2] |= ((t_uint) cur) << 32;        \
+    } else {                                      \
+        N->p[i/2] &= 0xFFFFFFFF00000000;          \
+        N->p[i/2] |= (t_uint) cur;                \
+    }
+
+#endif /* sizeof( t_uint ) */
+
+/*
+ * Helpers for addition and subtraction of chunks, with signed carry.
+ */
+static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
+{
+    *dst += src;
+    *carry += ( *dst < src );
+}
+
+static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
+{
+    *carry -= ( *dst < src );
+    *dst -= src;
+}
+
+#define ADD( j )    add32( &cur, A( j ), &c );
+#define SUB( j )    sub32( &cur, A( j ), &c );
+
+/*
+ * Helpers for the main 'loop'
+ * (see fix_negative for the motivation of C)
+ */
+#define INIT( b )                                           \
+    int ret;                                                \
+    signed char c = 0, cc;                                  \
+    uint32_t cur;                                           \
+    size_t i = 0, bits = b;                                 \
+    mpi C;                                                  \
+    t_uint Cp[ b / 8 / sizeof( t_uint) + 1 ];               \
+                                                            \
+    C.s = 1;                                                \
+    C.n = b / 8 / sizeof( t_uint) + 1;                      \
+    C.p = Cp;                                               \
+    memset( Cp, 0, C.n * sizeof( t_uint ) );                \
+                                                            \
+    MPI_CHK( mpi_grow( N, b * 2 / 8 / sizeof( t_uint ) ) ); \
+    LOAD32;
+
+#define NEXT                    \
+    STORE32; i++; LOAD32;       \
+    cc = c; c = 0;              \
+    if( cc < 0 )                \
+        sub32( &cur, -cc, &c ); \
+    else                        \
+        add32( &cur, cc, &c );  \
+
+#define LAST                                    \
+    STORE32; i++;                               \
+    cur = c > 0 ? c : 0; STORE32;               \
+    cur = 0; while( ++i < MAX32 ) { STORE32; }  \
+    if( c < 0 ) fix_negative( N, c, &C, bits );
+
+/*
+ * If the result is negative, we get it in the form
+ * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
+ */
+static inline int fix_negative( mpi *N, signed char c, mpi *C, size_t bits )
+{
+    int ret;
+
+    /* C = - c * 2^(bits + 32) */
+#if !defined(POLARSSL_HAVE_INT64)
+    ((void) bits);
+#else
+    if( bits == 224 )
+        C->p[ C->n - 1 ] = ((t_uint) -c) << 32;
+    else
+#endif
+        C->p[ C->n - 1 ] = (t_uint) -c;
+
+    /* N = - ( C - N ) */
+    MPI_CHK( mpi_sub_abs( N, C, N ) );
+    N->s = -1;
+
+cleanup:
+
+    return( ret );
+}
+
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ */
+static int ecp_mod_p224( mpi *N )
+{
+    INIT( 224 );
+
+    SUB(  7 ); SUB( 11 );               NEXT; // A0 += -A7 - A11
+    SUB(  8 ); SUB( 12 );               NEXT; // A1 += -A8 - A12
+    SUB(  9 ); SUB( 13 );               NEXT; // A2 += -A9 - A13
+    SUB( 10 ); ADD(  7 ); ADD( 11 );    NEXT; // A3 += -A10 + A7 + A11
+    SUB( 11 ); ADD(  8 ); ADD( 12 );    NEXT; // A4 += -A11 + A8 + A12
+    SUB( 12 ); ADD(  9 ); ADD( 13 );    NEXT; // A5 += -A12 + A9 + A13
+    SUB( 13 ); ADD( 10 );               LAST; // A6 += -A13 + A10
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
+ */
+static int ecp_mod_p256( mpi *N )
+{
+    INIT( 256 );
+
+    ADD(  8 ); ADD(  9 );
+    SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 );             NEXT; // A0
+
+    ADD(  9 ); ADD( 10 );
+    SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 );             NEXT; // A1
+
+    ADD( 10 ); ADD( 11 );
+    SUB( 13 ); SUB( 14 ); SUB( 15 );                        NEXT; // A2
+
+    ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
+    SUB( 15 ); SUB(  8 ); SUB(  9 );                        NEXT; // A3
+
+    ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
+    SUB(  9 ); SUB( 10 );                                   NEXT; // A4
+
+    ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
+    SUB( 10 ); SUB( 11 );                                   NEXT; // A5
+
+    ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
+    SUB(  8 ); SUB(  9 );                                   NEXT; // A6
+
+    ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
+    SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 );             LAST; // A7
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
+ */
+static int ecp_mod_p384( mpi *N )
+{
+    INIT( 384 );
+
+    ADD( 12 ); ADD( 21 ); ADD( 20 );
+    SUB( 23 );                                              NEXT; // A0
+
+    ADD( 13 ); ADD( 22 ); ADD( 23 );
+    SUB( 12 ); SUB( 20 );                                   NEXT; // A2
+
+    ADD( 14 ); ADD( 23 );
+    SUB( 13 ); SUB( 21 );                                   NEXT; // A2
+
+    ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
+    SUB( 14 ); SUB( 22 ); SUB( 23 );                        NEXT; // A3
+
+    ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
+    SUB( 15 ); SUB( 23 ); SUB( 23 );                        NEXT; // A4
+
+    ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
+    SUB( 16 );                                              NEXT; // A5
+
+    ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
+    SUB( 17 );                                              NEXT; // A6
+
+    ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
+    SUB( 18 );                                              NEXT; // A7
+
+    ADD( 20 ); ADD( 17 ); ADD( 16 );
+    SUB( 19 );                                              NEXT; // A8
+
+    ADD( 21 ); ADD( 18 ); ADD( 17 );
+    SUB( 20 );                                              NEXT; // A9
+
+    ADD( 22 ); ADD( 19 ); ADD( 18 );
+    SUB( 21 );                                              NEXT; // A10
+
+    ADD( 23 ); ADD( 20 ); ADD( 19 );
+    SUB( 22 );                                              LAST; // A11
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+
+#undef A
+#undef LOAD32
+#undef STORE32
+#undef MAX32
+#undef INIT
+#undef NEXT
+#undef LAST
+
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED ||
+          POLARSSL_ECP_DP_SECP256R1_ENABLED ||
+          POLARSSL_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+/*
+ * Here we have an actual Mersenne prime, so things are more straightforward.
+ * However, chunks are aligned on a 'weird' boundary (521 bits).
+ */
+
+/* Size of p521 in terms of t_uint */
+#define P521_WIDTH      ( 521 / 8 / sizeof( t_uint ) + 1 )
+
+/* Bits to keep in the most significant t_uint */
+#if defined(POLARSSL_HAVE_INT8)
+#define P521_MASK       0x01
+#else
+#define P521_MASK       0x01FF
+#endif
+
+/*
+ * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
+ * Write N as A1 + 2^521 A0, return A0 + A1
+ */
+static int ecp_mod_p521( mpi *N )
+{
+    int ret;
+    size_t i;
+    mpi M;
+    t_uint Mp[P521_WIDTH + 1];
+    /* Worst case for the size of M is when t_uint is 16 bits:
+     * we need to hold bits 513 to 1056, which is 34 limbs, that is
+     * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
+
+    if( N->n < P521_WIDTH )
+        return( 0 );
+
+    /* M = A1 */
+    M.s = 1;
+    M.n = N->n - ( P521_WIDTH - 1 );
+    if( M.n > P521_WIDTH + 1 )
+        M.n = P521_WIDTH + 1;
+    M.p = Mp;
+    memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( t_uint ) );
+    MPI_CHK( mpi_shift_r( &M, 521 % ( 8 * sizeof( t_uint ) ) ) );
+
+    /* N = A0 */
+    N->p[P521_WIDTH - 1] &= P521_MASK;
+    for( i = P521_WIDTH; i < N->n; i++ )
+        N->p[i] = 0;
+
+    /* N = A0 + A1 */
+    MPI_CHK( mpi_add_abs( N, N, &M ) );
+
+cleanup:
+    return( ret );
+}
+
+#undef P521_WIDTH
+#undef P521_MASK
+#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+
+#endif /* POLARSSL_ECP_NIST_OPTIM */
+
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+
+/* Size of p255 in terms of t_uint */
+#define P255_WIDTH      ( 255 / 8 / sizeof( t_uint ) + 1 )
+
+/*
+ * Fast quasi-reduction modulo p255 = 2^255 - 19
+ * Write N as A0 + 2^255 A1, return A0 + 19 * A1
+ */
+static int ecp_mod_p255( mpi *N )
+{
+    int ret;
+    size_t i;
+    mpi M;
+    t_uint Mp[P255_WIDTH + 2];
+
+    if( N->n < P255_WIDTH )
+        return( 0 );
+
+    /* M = A1 */
+    M.s = 1;
+    M.n = N->n - ( P255_WIDTH - 1 );
+    if( M.n > P255_WIDTH + 1 )
+        M.n = P255_WIDTH + 1;
+    M.p = Mp;
+    memset( Mp, 0, sizeof Mp );
+    memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( t_uint ) );
+    MPI_CHK( mpi_shift_r( &M, 255 % ( 8 * sizeof( t_uint ) ) ) );
+    M.n++; /* Make room for multiplication by 19 */
+
+    /* N = A0 */
+    MPI_CHK( mpi_set_bit( N, 255, 0 ) );
+    for( i = P255_WIDTH; i < N->n; i++ )
+        N->p[i] = 0;
+
+    /* N = A0 + 19 * A1 */
+    MPI_CHK( mpi_mul_int( &M, &M, 19 ) );
+    MPI_CHK( mpi_add_abs( N, N, &M ) );
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_M255_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP224K1_ENABLED) ||   \
+    defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo P = 2^s - R,
+ * with R about 33 bits, used by the Koblitz curves.
+ *
+ * Write N as A0 + 2^224 A1, return A0 + R * A1.
+ * Actually do two passes, since R is big.
+ */
+#define P_KOBLITZ_MAX   ( 256 / 8 / sizeof( t_uint ) )  // Max limbs in P
+#define P_KOBLITZ_R     ( 8 / sizeof( t_uint ) )        // Limbs in R
+static inline int ecp_mod_koblitz( mpi *N, t_uint *Rp, size_t p_limbs,
+                                   size_t adjust, size_t shift, t_uint mask )
+{
+    int ret;
+    size_t i;
+    mpi M, R;
+    t_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R];
+
+    if( N->n < p_limbs )
+        return( 0 );
+
+    /* Init R */
+    R.s = 1;
+    R.p = Rp;
+    R.n = P_KOBLITZ_R;
+
+    /* Common setup for M */
+    M.s = 1;
+    M.p = Mp;
+
+    /* M = A1 */
+    M.n = N->n - ( p_limbs - adjust );
+    if( M.n > p_limbs + adjust )
+        M.n = p_limbs + adjust;
+    memset( Mp, 0, sizeof Mp );
+    memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( t_uint ) );
+    if( shift != 0 )
+        MPI_CHK( mpi_shift_r( &M, shift ) );
+    M.n += R.n - adjust; /* Make room for multiplication by R */
+
+    /* N = A0 */
+    if( mask != 0 )
+        N->p[p_limbs - 1] &= mask;
+    for( i = p_limbs; i < N->n; i++ )
+        N->p[i] = 0;
+
+    /* N = A0 + R * A1 */
+    MPI_CHK( mpi_mul_mpi( &M, &M, &R ) );
+    MPI_CHK( mpi_add_abs( N, N, &M ) );
+
+    /* Second pass */
+
+    /* M = A1 */
+    M.n = N->n - ( p_limbs - adjust );
+    if( M.n > p_limbs + adjust )
+        M.n = p_limbs + adjust;
+    memset( Mp, 0, sizeof Mp );
+    memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( t_uint ) );
+    if( shift != 0 )
+        MPI_CHK( mpi_shift_r( &M, shift ) );
+    M.n += R.n - adjust; /* Make room for multiplication by R */
+
+    /* N = A0 */
+    if( mask != 0 )
+        N->p[p_limbs - 1] &= mask;
+    for( i = p_limbs; i < N->n; i++ )
+        N->p[i] = 0;
+
+    /* N = A0 + R * A1 */
+    MPI_CHK( mpi_mul_mpi( &M, &M, &R ) );
+    MPI_CHK( mpi_add_abs( N, N, &M ) );
+
+cleanup:
+    return( ret );
+}
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED) ||
+          POLARSSL_ECP_DP_SECP224K1_ENABLED) ||
+          POLARSSL_ECP_DP_SECP256K1_ENABLED) */
+
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p192k1 = 2^192 - R,
+ * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119
+ */
+static int ecp_mod_p192k1( mpi *N )
+{
+    static t_uint Rp[] = {
+        BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+
+    return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( t_uint ), 0, 0, 0 ) );
+}
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p224k1 = 2^224 - R,
+ * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93
+ */
+static int ecp_mod_p224k1( mpi *N )
+{
+    static t_uint Rp[] = {
+        BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+
+#if defined(POLARSSL_HAVE_INT64)
+    return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) );
+#else
+    return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( t_uint ), 0, 0, 0 ) );
+#endif
+}
+
+#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p256k1 = 2^256 - R,
+ * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1
+ */
+static int ecp_mod_p256k1( mpi *N )
+{
+    static t_uint Rp[] = {
+        BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+    return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( t_uint ), 0, 0, 0 ) );
+}
+#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */
+
+#endif /* POLARSSL_ECP_C */
index c5fac26e9c7da8cd1d9703e331888bfa50759576..bc7fb0fe461113f0fc69127e82cdee34f4b95550 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Entropy accumulator implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_ENTROPY_C)
 
 #include "polarssl/entropy.h"
 #include "polarssl/entropy_poll.h"
 
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
 #if defined(POLARSSL_HAVEGE_C)
 #include "polarssl/havege.h"
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */
 
 void entropy_init( entropy_context *ctx )
@@ -70,7 +83,10 @@ void entropy_init( entropy_context *ctx )
 
 void entropy_free( entropy_context *ctx )
 {
-    ((void) ctx);
+#if defined(POLARSSL_HAVEGE_C)
+    havege_free( &ctx->havege_data );
+#endif
+    polarssl_zeroize( ctx, sizeof( entropy_context ) );
 #if defined(POLARSSL_THREADING_C)
     polarssl_mutex_free( &ctx->mutex );
 #endif
@@ -80,10 +96,19 @@ int entropy_add_source( entropy_context *ctx,
                         f_source_ptr f_source, void *p_source,
                         size_t threshold )
 {
-    int index = ctx->source_count;
+    int index, ret = 0;
+
+#if defined(POLARSSL_THREADING_C)
+    if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
 
+    index = ctx->source_count;
     if( index >= ENTROPY_MAX_SOURCES )
-        return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
+    {
+        ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES;
+        goto exit;
+    }
 
     ctx->source[index].f_source = f_source;
     ctx->source[index].p_source = p_source;
@@ -91,7 +116,13 @@ int entropy_add_source( entropy_context *ctx,
 
     ctx->source_count++;
 
-    return( 0 );
+exit:
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
 }
 
 /*
@@ -133,18 +164,32 @@ static int entropy_update( entropy_context *ctx, unsigned char source_id,
 int entropy_update_manual( entropy_context *ctx,
                            const unsigned char *data, size_t len )
 {
-    return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
+    int ret;
+
+#if defined(POLARSSL_THREADING_C)
+    if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
+
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
 }
 
 /*
  * Run through the different sources to add entropy to our accumulator
  */
-int entropy_gather( entropy_context *ctx )
+static int entropy_gather_internal( entropy_context *ctx )
 {
     int ret, i;
     unsigned char buf[ENTROPY_MAX_GATHER];
     size_t olen;
-    
+
     if( ctx->source_count == 0 )
         return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
 
@@ -154,7 +199,7 @@ int entropy_gather( entropy_context *ctx )
     for( i = 0; i < ctx->source_count; i++ )
     {
         olen = 0;
-        if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
+        if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
                         buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
         {
             return( ret );
@@ -173,6 +218,28 @@ int entropy_gather( entropy_context *ctx )
     return( 0 );
 }
 
+/*
+ * Thread-safe wrapper for entropy_gather_internal()
+ */
+int entropy_gather( entropy_context *ctx )
+{
+    int ret;
+
+#if defined(POLARSSL_THREADING_C)
+    if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    ret = entropy_gather_internal( ctx );
+
+#if defined(POLARSSL_THREADING_C)
+    if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
+        return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
+}
+
 int entropy_func( void *data, unsigned char *output, size_t len )
 {
     int ret, count = 0, i, reached;
@@ -198,7 +265,7 @@ int entropy_func( void *data, unsigned char *output, size_t len )
             goto exit;
         }
 
-        if( ( ret = entropy_gather( ctx ) ) != 0 )
+        if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
             goto exit;
 
         reached = 0;
@@ -214,24 +281,19 @@ int entropy_func( void *data, unsigned char *output, size_t len )
 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
     sha512_finish( &ctx->accumulator, buf );
 
-    /*
-     * Perform second SHA-512 on entropy
-     */
-    sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
-
     /*
      * Reset accumulator and counters and recycle existing entropy
      */
     memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
     sha512_starts( &ctx->accumulator, 0 );
     sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
-#else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
-    sha256_finish( &ctx->accumulator, buf );
 
     /*
-     * Perform second SHA-256 on entropy
+     * Perform second SHA-512 on entropy
      */
-    sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
+    sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
+#else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
+    sha256_finish( &ctx->accumulator, buf );
 
     /*
      * Reset accumulator and counters and recycle existing entropy
@@ -239,6 +301,11 @@ int entropy_func( void *data, unsigned char *output, size_t len )
     memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
     sha256_starts( &ctx->accumulator, 0 );
     sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
+
+    /*
+     * Perform second SHA-256 on entropy
+     */
+    sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
 #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
 
     for( i = 0; i < ctx->source_count; i++ )
@@ -257,4 +324,154 @@ exit:
     return( ret );
 }
 
+#if defined(POLARSSL_FS_IO)
+int entropy_write_seed_file( entropy_context *ctx, const char *path )
+{
+    int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
+    FILE *f;
+    unsigned char buf[ENTROPY_BLOCK_SIZE];
+
+    if( ( f = fopen( path, "wb" ) ) == NULL )
+        return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
+
+    if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 )
+        goto exit;
+
+    if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE )
+    {
+        ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
+        goto exit;
+    }
+
+    ret = 0;
+
+exit:
+    fclose( f );
+    return( ret );
+}
+
+int entropy_update_seed_file( entropy_context *ctx, const char *path )
+{
+    FILE *f;
+    size_t n;
+    unsigned char buf[ ENTROPY_MAX_SEED_SIZE ];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    n = (size_t) ftell( f );
+    fseek( f, 0, SEEK_SET );
+
+    if( n > ENTROPY_MAX_SEED_SIZE )
+        n = ENTROPY_MAX_SEED_SIZE;
+
+    if( fread( buf, 1, n, f ) != n )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    entropy_update_manual( ctx, buf, n );
+
+    return( entropy_write_seed_file( ctx, path ) );
+}
+#endif /* POLARSSL_FS_IO */
+
+#if defined(POLARSSL_SELF_TEST)
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf     printf
 #endif
+
+/*
+ * Dummy source function
+ */
+static int entropy_dummy_source( void *data, unsigned char *output,
+                                 size_t len, size_t *olen )
+{
+    ((void) data);
+
+    memset( output, 0x2a, len );
+    *olen = len;
+
+    return( 0 );
+}
+
+/*
+ * The actual entropy quality is hard to test, but we can at least
+ * test that the functions don't cause errors and write the correct
+ * amount of data to buffers.
+ */
+int entropy_self_test( int verbose )
+{
+    int ret = 0;
+    entropy_context ctx;
+    unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 };
+    unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 };
+    size_t i, j;
+
+    if( verbose != 0 )
+        polarssl_printf( "  ENTROPY test: " );
+
+    entropy_init( &ctx );
+
+    ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 );
+    if( ret != 0 )
+        goto cleanup;
+
+    if( ( ret = entropy_gather( &ctx ) ) != 0 )
+        goto cleanup;
+
+    if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
+        goto cleanup;
+
+    /*
+     * To test that entropy_func writes correct number of bytes:
+     * - use the whole buffer and rely on ASan to detect overruns
+     * - collect entropy 8 times and OR the result in an accumulator:
+     *   any byte should then be 0 with probably 2^(-64), so requiring
+     *   each of the 32 or 64 bytes to be non-zero has a false failure rate
+     *   of at most 2^(-58) which is acceptable.
+     */
+    for( i = 0; i < 8; i++ )
+    {
+        if( ( ret = entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
+            goto cleanup;
+
+        for( j = 0; j < sizeof( buf ); j++ )
+            acc[j] |= buf[j];
+    }
+
+    for( j = 0; j < sizeof( buf ); j++ )
+    {
+        if( acc[j] == 0 )
+        {
+            ret = 1;
+            goto cleanup;
+        }
+    }
+
+cleanup:
+    entropy_free( &ctx );
+
+    if( verbose != 0 )
+    {
+        if( ret != 0 )
+            polarssl_printf( "failed\n" );
+        else
+            polarssl_printf( "passed\n" );
+
+        polarssl_printf( "\n" );
+    }
+
+    return( ret != 0 );
+}
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_ENTROPY_C */
index badcfac5cc1b256814571c9b540027ef6b47865c..9ca9e95199d931da358ae39c80734ade1a993647 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Platform-specific and custom entropy polling functions
  *
- *  Copyright (C) 2006-2011, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_ENTROPY_C)
 
@@ -56,18 +60,18 @@ int platform_entropy_poll( void *data, unsigned char *output, size_t len,
     if( CryptAcquireContext( &provider, NULL, NULL,
                               PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
     {
-        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+        return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
     }
 
     if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
-        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+        return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
 
     CryptReleaseContext( provider, 0 );
     *olen = len;
 
     return( 0 );
 }
-#else
+#else /* _WIN32 && !EFIX64 && !EFI32 */
 
 #include <stdio.h>
 
@@ -82,13 +86,13 @@ int platform_entropy_poll( void *data,
 
     file = fopen( "/dev/urandom", "rb" );
     if( file == NULL )
-        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
-    
+        return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+
     ret = fread( output, 1, len, file );
     if( ret != len )
     {
         fclose( file );
-        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+        return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
     }
 
     fclose( file );
@@ -96,8 +100,8 @@ int platform_entropy_poll( void *data,
 
     return( 0 );
 }
-#endif
-#endif
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+#endif /* !POLARSSL_NO_PLATFORM_ENTROPY */
 
 #if defined(POLARSSL_TIMING_C)
 int hardclock_poll( void *data,
@@ -115,7 +119,7 @@ int hardclock_poll( void *data,
 
     return( 0 );
 }
-#endif
+#endif /* POLARSSL_TIMING_C */
 
 #if defined(POLARSSL_HAVEGE_C)
 int havege_poll( void *data,
@@ -125,12 +129,12 @@ int havege_poll( void *data,
     *olen = 0;
 
     if( havege_random( hs, output, len ) != 0 )
-        return POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+        return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
 
     *olen = len;
 
     return( 0 );
 }
-#endif
+#endif /* POLARSSL_HAVEGE_C */
 
 #endif /* POLARSSL_ENTROPY_C */
index 9d76f194c5657f852799d7bf6f514708835a9469..22234cf28dfa4ffc6904cbc3b875dcfdaeb5e2af 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Error message information
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
-#if defined(POLARSSL_ERROR_C)
-
+#if defined(POLARSSL_ERROR_C) || defined(POLARSSL_ERROR_STRERROR_DUMMY)
 #include "polarssl/error.h"
+#endif
+
+#if defined(POLARSSL_ERROR_C)
 
 #if defined(POLARSSL_AES_C)
 #include "polarssl/aes.h"
 #include "polarssl/camellia.h"
 #endif
 
+#if defined(POLARSSL_CCM_C)
+#include "polarssl/ccm.h"
+#endif
+
 #if defined(POLARSSL_CIPHER_C)
 #include "polarssl/cipher.h"
 #endif
 #include "polarssl/gcm.h"
 #endif
 
+#if defined(POLARSSL_HMAC_DRBG_C)
+#include "polarssl/hmac_drbg.h"
+#endif
+
 #if defined(POLARSSL_MD_C)
 #include "polarssl/md.h"
 #endif
 #include "polarssl/pkcs5.h"
 #endif
 
+#if defined(POLARSSL_RIPEMD160_C)
+#include "polarssl/ripemd160.h"
+#endif
+
 #if defined(POLARSSL_RSA_C)
 #include "polarssl/rsa.h"
 #endif
@@ -186,6 +204,7 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
 
         // High level error codes
         //
+        // BEGIN generated code
 #if defined(POLARSSL_CIPHER_C)
         if( use_ret == -(POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE) )
             snprintf( buf, buflen, "CIPHER - The selected feature is not available" );
@@ -237,6 +256,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
             snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" );
         if( use_ret == -(POLARSSL_ERR_ECP_INVALID_KEY) )
             snprintf( buf, buflen, "ECP - Invalid private or public key" );
+        if( use_ret == -(POLARSSL_ERR_ECP_SIG_LEN_MISMATCH) )
+            snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" );
 #endif /* POLARSSL_ECP_C */
 
 #if defined(POLARSSL_MD_C)
@@ -298,6 +319,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
             snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" );
         if( use_ret == -(POLARSSL_ERR_PK_FEATURE_UNAVAILABLE) )
             snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" );
+        if( use_ret == -(POLARSSL_ERR_PK_SIG_LEN_MISMATCH) )
+            snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" );
 #endif /* POLARSSL_PK_C */
 
 #if defined(POLARSSL_PKCS12_C)
@@ -358,8 +381,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
             snprintf( buf, buflen, "SSL - An unknown cipher was received" );
         if( use_ret == -(POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN) )
             snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" );
-        if( use_ret == -(POLARSSL_ERR_SSL_NO_SESSION_FOUND) )
-            snprintf( buf, buflen, "SSL - No session to recover was found" );
+        if( use_ret == -(POLARSSL_ERR_SSL_NO_RNG) )
+            snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" );
         if( use_ret == -(POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE) )
             snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" );
         if( use_ret == -(POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE) )
@@ -422,9 +445,11 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
         if( use_ret == -(POLARSSL_ERR_SSL_PK_TYPE_MISMATCH) )
             snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" );
         if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_IDENTITY) )
-            snprintf( buf, buflen, "SSL - Unkown identity received (eg, PSK identity)" );
+            snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" );
         if( use_ret == -(POLARSSL_ERR_SSL_INTERNAL_ERROR) )
             snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" );
+        if( use_ret == -(POLARSSL_ERR_SSL_COUNTER_WRAPPING) )
+            snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" );
 #endif /* POLARSSL_SSL_TLS_C */
 
 #if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C)
@@ -465,6 +490,7 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
         if( use_ret == -(POLARSSL_ERR_X509_FILE_IO_ERROR) )
             snprintf( buf, buflen, "X509 - Read/write of file failed" );
 #endif /* POLARSSL_X509_USE,X509_CREATE_C */
+        // END generated code
 
         if( strlen( buf ) == 0 )
             snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
@@ -493,6 +519,7 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
 
     // Low level error codes
     //
+    // BEGIN generated code
 #if defined(POLARSSL_AES_C)
     if( use_ret == -(POLARSSL_ERR_AES_INVALID_KEY_LENGTH) )
         snprintf( buf, buflen, "AES - Invalid key length" );
@@ -557,6 +584,13 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
         snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
 #endif /* POLARSSL_CAMELLIA_C */
 
+#if defined(POLARSSL_CCM_C)
+    if( use_ret == -(POLARSSL_ERR_CCM_BAD_INPUT) )
+        snprintf( buf, buflen, "CCM - Bad input parameters to function" );
+    if( use_ret == -(POLARSSL_ERR_CCM_AUTH_FAILED) )
+        snprintf( buf, buflen, "CCM - Authenticated decryption failed" );
+#endif /* POLARSSL_CCM_C */
+
 #if defined(POLARSSL_CTR_DRBG_C)
     if( use_ret == -(POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) )
         snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" );
@@ -580,6 +614,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
         snprintf( buf, buflen, "ENTROPY - No more sources can be added" );
     if( use_ret == -(POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED) )
         snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" );
+    if( use_ret == -(POLARSSL_ERR_ENTROPY_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "ENTROPY - Read/write error in file" );
 #endif /* POLARSSL_ENTROPY_C */
 
 #if defined(POLARSSL_GCM_C)
@@ -589,6 +625,17 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
         snprintf( buf, buflen, "GCM - Bad input parameters to function" );
 #endif /* POLARSSL_GCM_C */
 
+#if defined(POLARSSL_HMAC_DRBG_C)
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG) )
+        snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG) )
+        snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" );
+    if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) )
+        snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" );
+#endif /* POLARSSL_HMAC_DRBG_C */
+
 #if defined(POLARSSL_MD2_C)
     if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) )
         snprintf( buf, buflen, "MD2 - Read/write error in file" );
@@ -632,6 +679,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
 #if defined(POLARSSL_OID_C)
     if( use_ret == -(POLARSSL_ERR_OID_NOT_FOUND) )
         snprintf( buf, buflen, "OID - OID is not found" );
+    if( use_ret == -(POLARSSL_ERR_OID_BUF_TOO_SMALL) )
+        snprintf( buf, buflen, "OID - output buffer is too small" );
 #endif /* POLARSSL_OID_C */
 
 #if defined(POLARSSL_PADLOCK_C)
@@ -644,6 +693,11 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
         snprintf( buf, buflen, "PBKDF2 - Bad input parameters to function" );
 #endif /* POLARSSL_PBKDF2_C */
 
+#if defined(POLARSSL_RIPEMD160_C)
+    if( use_ret == -(POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR) )
+        snprintf( buf, buflen, "RIPEMD160 - Read/write error in file" );
+#endif /* POLARSSL_RIPEMD160_C */
+
 #if defined(POLARSSL_SHA1_C)
     if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) )
         snprintf( buf, buflen, "SHA1 - Read/write error in file" );
@@ -672,6 +726,7 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
     if( use_ret == -(POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH) )
         snprintf( buf, buflen, "XTEA - The data input has an invalid length" );
 #endif /* POLARSSL_XTEA_C */
+    // END generated code
 
     if( strlen( buf ) != 0 )
         return;
index a9e18c89d063a5ef19fbdef85d4251ffc841dec4..77b1e0fb68358138dc06474f3d01e66e5c2b2811 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  NIST SP800-38D compliant GCM implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+
 /*
- *  http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+ * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+ *
+ * See also:
+ * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+ *
+ * We use the algorithm described as Shoup's method with 4-bit tables in
+ * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
  */
+
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_GCM_C)
 
 #include "polarssl/gcm.h"
 
+#if defined(POLARSSL_AESNI_C)
+#include "polarssl/aesni.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
 /*
  * 32-bit integer manipulation macros (big endian)
  */
 }
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * Precompute small multiples of H, that is set
+ *      HH[i] || HL[i] = H times i,
+ * where i is seen as a field element as in [MGV], ie high-order bits
+ * correspond to low powers of P. The result is stored in the same way, that
+ * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
+ * corresponds to P^127.
+ */
 static int gcm_gen_table( gcm_context *ctx )
 {
     int ret, i, j;
@@ -66,9 +101,7 @@ static int gcm_gen_table( gcm_context *ctx )
     if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
         return( ret );
 
-    ctx->HH[0] = 0;
-    ctx->HL[0] = 0;
-
+    /* pack h as two 64-bits ints, big-endian */
     GET_UINT32_BE( hi, h,  0  );
     GET_UINT32_BE( lo, h,  4  );
     vh = (uint64_t) hi << 32 | lo;
@@ -77,9 +110,20 @@ static int gcm_gen_table( gcm_context *ctx )
     GET_UINT32_BE( lo, h,  12 );
     vl = (uint64_t) hi << 32 | lo;
 
+    /* 8 = 1000 corresponds to 1 in GF(2^128) */
     ctx->HL[8] = vl;
     ctx->HH[8] = vh;
 
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    /* With CLMUL support, we need only h, not the rest of the table */
+    if( aesni_supports( POLARSSL_AESNI_CLMUL ) )
+        return( 0 );
+#endif
+
+    /* 0 corresponds to 0 in GF(2^128) */
+    ctx->HH[0] = 0;
+    ctx->HL[0] = 0;
+
     for( i = 4; i > 0; i >>= 1 )
     {
         uint32_t T = ( vl & 1 ) * 0xe1000000U;
@@ -90,7 +134,7 @@ static int gcm_gen_table( gcm_context *ctx )
         ctx->HH[i] = vh;
     }
 
-    for (i = 2; i < 16; i <<= 1 )
+    fori = 2; i < 16; i <<= 1 )
     {
         uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
         vh = *HiH;
@@ -113,6 +157,8 @@ int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
 
     memset( ctx, 0, sizeof(gcm_context) );
 
+    cipher_init( &ctx->cipher_ctx );
+
     cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
     if( cipher_info == NULL )
         return( POLARSSL_ERR_GCM_BAD_INPUT );
@@ -135,6 +181,11 @@ int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
     return( 0 );
 }
 
+/*
+ * Shoup's method for multiplication use this table with
+ *      last4[x] = x times P^128
+ * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
+ */
 static const uint64_t last4[16] =
 {
     0x0000, 0x1c20, 0x3840, 0x2460,
@@ -143,15 +194,30 @@ static const uint64_t last4[16] =
     0x9180, 0x8da0, 0xa9c0, 0xb5e0
 };
 
+/*
+ * Sets output to x times H using the precomputed tables.
+ * x and output are seen as elements of GF(2^128) as in [MGV].
+ */
 static void gcm_mult( gcm_context *ctx, const unsigned char x[16],
                       unsigned char output[16] )
 {
     int i = 0;
-    unsigned char z[16];
     unsigned char lo, hi, rem;
     uint64_t zh, zl;
 
-    memset( z, 0x00, 16 );
+#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
+    if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) {
+        unsigned char h[16];
+
+        PUT_UINT32_BE( ctx->HH[8] >> 32, h,  0 );
+        PUT_UINT32_BE( ctx->HH[8],       h,  4 );
+        PUT_UINT32_BE( ctx->HL[8] >> 32, h,  8 );
+        PUT_UINT32_BE( ctx->HL[8],       h, 12 );
+
+        aesni_gcm_mult( output, x, h );
+        return;
+    }
+#endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
 
     lo = x[15] & 0xf;
     hi = x[15] >> 4;
@@ -202,6 +268,13 @@ int gcm_starts( gcm_context *ctx,
     const unsigned char *p;
     size_t use_len, olen = 0;
 
+    /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
+    if( ( (uint64_t) iv_len  ) >> 61 != 0 ||
+        ( (uint64_t) add_len ) >> 61 != 0 )
+    {
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+    }
+
     memset( ctx->y, 0x00, sizeof(ctx->y) );
     memset( ctx->buf, 0x00, sizeof(ctx->buf) );
 
@@ -278,6 +351,14 @@ int gcm_update( gcm_context *ctx,
     if( output > input && (size_t) ( output - input ) < length )
         return( POLARSSL_ERR_GCM_BAD_INPUT );
 
+    /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
+     * Also check for possible overflow */
+    if( ctx->len + length < ctx->len ||
+        (uint64_t) ctx->len + length > 0x03FFFFE0llu )
+    {
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+    }
+
     ctx->len += length;
 
     p = input;
@@ -323,7 +404,7 @@ int gcm_finish( gcm_context *ctx,
     uint64_t orig_len = ctx->len * 8;
     uint64_t orig_add_len = ctx->add_len * 8;
 
-    if( tag_len > 16 )
+    if( tag_len > 16 || tag_len < 4 )
         return( POLARSSL_ERR_GCM_BAD_INPUT );
 
     if( tag_len != 0 )
@@ -387,11 +468,17 @@ int gcm_auth_decrypt( gcm_context *ctx,
                       const unsigned char *input,
                       unsigned char *output )
 {
+    int ret;
     unsigned char check_tag[16];
     size_t i;
     int diff;
 
-    gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag );
+    if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
+                                   iv, iv_len, add, add_len,
+                                   input, output, tag_len, check_tag ) ) != 0 )
+    {
+        return( ret );
+    }
 
     /* Check tag in "constant-time" */
     for( diff = 0, i = 0; i < tag_len; i++ )
@@ -399,7 +486,7 @@ int gcm_auth_decrypt( gcm_context *ctx,
 
     if( diff != 0 )
     {
-        memset( output, 0, length );
+        polarssl_zeroize( output, length );
         return( POLARSSL_ERR_GCM_AUTH_FAILED );
     }
 
@@ -408,8 +495,8 @@ int gcm_auth_decrypt( gcm_context *ctx,
 
 void gcm_free( gcm_context *ctx )
 {
-    (void) cipher_free_ctx( &ctx->cipher_ctx );
-    memset( ctx, 0, sizeof( gcm_context ) );
+    cipher_free( &ctx->cipher_ctx );
+    polarssl_zeroize( ctx, sizeof( gcm_context ) );
 }
 
 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
@@ -658,7 +745,8 @@ int gcm_self_test( int verbose )
         for( i = 0; i < MAX_TESTS; i++ )
         {
             if( verbose != 0 )
-                printf( "  AES-GCM-%3d #%d (%s): ", key_len, i, "enc" );
+                polarssl_printf( "  AES-GCM-%3d #%d (%s): ",
+                                 key_len, i, "enc" );
 
             gcm_init( &ctx, cipher, key[key_index[i]], key_len );
 
@@ -673,7 +761,7 @@ int gcm_self_test( int verbose )
                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
                 return( 1 );
             }
@@ -681,10 +769,11 @@ int gcm_self_test( int verbose )
             gcm_free( &ctx );
 
             if( verbose != 0 )
-                printf( "passed\n" );
+                polarssl_printf( "passed\n" );
 
             if( verbose != 0 )
-                printf( "  AES-GCM-%3d #%d (%s): ", key_len, i, "dec" );
+                polarssl_printf( "  AES-GCM-%3d #%d (%s): ",
+                                 key_len, i, "dec" );
 
             gcm_init( &ctx, cipher, key[key_index[i]], key_len );
 
@@ -699,7 +788,7 @@ int gcm_self_test( int verbose )
                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
                 return( 1 );
             }
@@ -707,10 +796,11 @@ int gcm_self_test( int verbose )
             gcm_free( &ctx );
 
             if( verbose != 0 )
-                printf( "passed\n" );
+                polarssl_printf( "passed\n" );
 
             if( verbose != 0 )
-                printf( "  AES-GCM-%3d #%d split (%s): ", key_len, i, "enc" );
+                polarssl_printf( "  AES-GCM-%3d #%d split (%s): ",
+                                 key_len, i, "enc" );
 
             gcm_init( &ctx, cipher, key[key_index[i]], key_len );
 
@@ -720,7 +810,7 @@ int gcm_self_test( int verbose )
             if( ret != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
                 return( 1 );
             }
@@ -732,16 +822,17 @@ int gcm_self_test( int verbose )
                 if( ret != 0 )
                 {
                     if( verbose != 0 )
-                        printf( "failed\n" );
+                        polarssl_printf( "failed\n" );
 
                     return( 1 );
                 }
 
-                ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, buf + 32 );
+                ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
+                                  buf + 32 );
                 if( ret != 0 )
                 {
                     if( verbose != 0 )
-                        printf( "failed\n" );
+                        polarssl_printf( "failed\n" );
 
                     return( 1 );
                 }
@@ -752,7 +843,7 @@ int gcm_self_test( int verbose )
                 if( ret != 0 )
                 {
                     if( verbose != 0 )
-                        printf( "failed\n" );
+                        polarssl_printf( "failed\n" );
 
                     return( 1 );
                 }
@@ -764,7 +855,7 @@ int gcm_self_test( int verbose )
                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
                 return( 1 );
             }
@@ -772,10 +863,11 @@ int gcm_self_test( int verbose )
             gcm_free( &ctx );
 
             if( verbose != 0 )
-                printf( "passed\n" );
+                polarssl_printf( "passed\n" );
 
             if( verbose != 0 )
-                printf( "  AES-GCM-%3d #%d split (%s): ", key_len, i, "dec" );
+                polarssl_printf( "  AES-GCM-%3d #%d split (%s): ",
+                                 key_len, i, "dec" );
 
             gcm_init( &ctx, cipher, key[key_index[i]], key_len );
 
@@ -785,7 +877,7 @@ int gcm_self_test( int verbose )
             if( ret != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
                 return( 1 );
             }
@@ -797,16 +889,17 @@ int gcm_self_test( int verbose )
                 if( ret != 0 )
                 {
                     if( verbose != 0 )
-                        printf( "failed\n" );
+                        polarssl_printf( "failed\n" );
 
                     return( 1 );
                 }
 
-                ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, buf + 32 );
+                ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
+                                  buf + 32 );
                 if( ret != 0 )
                 {
                     if( verbose != 0 )
-                        printf( "failed\n" );
+                        polarssl_printf( "failed\n" );
 
                     return( 1 );
                 }
@@ -817,7 +910,7 @@ int gcm_self_test( int verbose )
                 if( ret != 0 )
                 {
                     if( verbose != 0 )
-                        printf( "failed\n" );
+                        polarssl_printf( "failed\n" );
 
                     return( 1 );
                 }
@@ -829,7 +922,7 @@ int gcm_self_test( int verbose )
                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
             {
                 if( verbose != 0 )
-                    printf( "failed\n" );
+                    polarssl_printf( "failed\n" );
 
                 return( 1 );
             }
@@ -837,13 +930,13 @@ int gcm_self_test( int verbose )
             gcm_free( &ctx );
 
             if( verbose != 0 )
-                printf( "passed\n" );
+                polarssl_printf( "passed\n" );
 
         }
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     return( 0 );
 }
@@ -852,4 +945,4 @@ int gcm_self_test( int verbose )
 
 #endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
 
-#endif
+#endif /* POLARSSL_GCM_C */
index 4d6f418ec98d1c7b017dab4a7d9bb45d8bd96fa9..3acd5bca106d6a58129fd3c4284a636ae224ef6d 100644 (file)
@@ -1,7 +1,7 @@
 /**
  *  \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_HAVEGE_C)
 
 
 #include <string.h>
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /* ------------------------------------------------------------------------
  * On average, one iteration accesses two 8-word blocks in the havege WALK
  * table, and generates 16 words in the RES array.
     *C = (*C >> (15)) ^ (*C << (17)) ^ CLK;             \
     *D = (*D >> (16)) ^ (*D << (16)) ^ CLK;             \
                                                         \
-    PT1 = ( RES[(i - 8) ^ PTX] ^                        \
+    PT1 = ( RES[( i - 8 ) ^ PTX] ^                      \
             WALK[PT1 ^ PTX ^ 7] ) & (~1);               \
     PT1 ^= (PT2 ^ 0x10) & 0x10;                         \
                                                         \
@@ -196,6 +205,14 @@ void havege_init( havege_state *hs )
     havege_fill( hs );
 }
 
+void havege_free( havege_state *hs )
+{
+    if( hs == NULL )
+        return;
+
+    polarssl_zeroize( hs, sizeof( havege_state ) );
+}
+
 /*
  * HAVEGE rand function
  */
@@ -219,7 +236,7 @@ int havege_random( void *p_rng, unsigned char *buf, size_t len )
         val ^= hs->pool[hs->offset[1]++];
 
         memcpy( p, &val, use_len );
-        
+
         len -= use_len;
         p += use_len;
     }
@@ -227,4 +244,4 @@ int havege_random( void *p_rng, unsigned char *buf, size_t len )
     return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_HAVEGE_C */
diff --git a/pdns/ext/polarssl/library/hmac_drbg.c b/pdns/ext/polarssl/library/hmac_drbg.c
new file mode 100644 (file)
index 0000000..d691be1
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ *  HMAC_DRBG implementation (NIST SP 800-90)
+ *
+ *  Copyright (C) 2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ *  The NIST SP 800-90A DRBGs are described in the following publication.
+ *  http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
+ *  References below are based on rev. 1 (January 2012).
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_HMAC_DRBG_C)
+
+#include "polarssl/hmac_drbg.h"
+
+#if defined(POLARSSL_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * HMAC_DRBG update, using optional additional data (10.1.2.2)
+ */
+void hmac_drbg_update( hmac_drbg_context *ctx,
+                       const unsigned char *additional, size_t add_len )
+{
+    size_t md_len = ctx->md_ctx.md_info->size;
+    unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
+    unsigned char sep[1];
+    unsigned char K[POLARSSL_MD_MAX_SIZE];
+
+    for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
+    {
+        /* Step 1 or 4 */
+        md_hmac_reset( &ctx->md_ctx );
+        md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+        md_hmac_update( &ctx->md_ctx, sep, 1 );
+        if( rounds == 2 )
+            md_hmac_update( &ctx->md_ctx, additional, add_len );
+        md_hmac_finish( &ctx->md_ctx, K );
+
+        /* Step 2 or 5 */
+        md_hmac_starts( &ctx->md_ctx, K, md_len );
+        md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+        md_hmac_finish( &ctx->md_ctx, ctx->V );
+    }
+}
+
+/*
+ * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
+ */
+int hmac_drbg_init_buf( hmac_drbg_context *ctx,
+                        const md_info_t * md_info,
+                        const unsigned char *data, size_t data_len )
+{
+    int ret;
+
+    memset( ctx, 0, sizeof( hmac_drbg_context ) );
+
+    md_init( &ctx->md_ctx );
+
+    if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
+        return( ret );
+
+    /*
+     * Set initial working state.
+     * Use the V memory location, which is currently all 0, to initialize the
+     * MD context with an all-zero key. Then set V to its initial value.
+     */
+    md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
+    memset( ctx->V, 0x01, md_info->size );
+
+    hmac_drbg_update( ctx, data, data_len );
+
+    return( 0 );
+}
+
+/*
+ * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
+ */
+int hmac_drbg_reseed( hmac_drbg_context *ctx,
+                      const unsigned char *additional, size_t len )
+{
+    unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
+    size_t seedlen;
+
+    /* III. Check input length */
+    if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
+        ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
+    {
+        return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+    }
+
+    memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
+
+    /* IV. Gather entropy_len bytes of entropy for the seed */
+    if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
+        return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
+
+    seedlen = ctx->entropy_len;
+
+    /* 1. Concatenate entropy and additional data if any */
+    if( additional != NULL && len != 0 )
+    {
+        memcpy( seed + seedlen, additional, len );
+        seedlen += len;
+    }
+
+    /* 2. Update state */
+    hmac_drbg_update( ctx, seed, seedlen );
+
+    /* 3. Reset reseed_counter */
+    ctx->reseed_counter = 1;
+
+    /* 4. Done */
+    return( 0 );
+}
+
+/*
+ * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
+ */
+int hmac_drbg_init( hmac_drbg_context *ctx,
+                    const md_info_t * md_info,
+                    int (*f_entropy)(void *, unsigned char *, size_t),
+                    void *p_entropy,
+                    const unsigned char *custom,
+                    size_t len )
+{
+    int ret;
+    size_t entropy_len;
+
+    memset( ctx, 0, sizeof( hmac_drbg_context ) );
+
+    md_init( &ctx->md_ctx );
+
+    if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
+        return( ret );
+
+    /*
+     * Set initial working state.
+     * Use the V memory location, which is currently all 0, to initialize the
+     * MD context with an all-zero key. Then set V to its initial value.
+     */
+    md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
+    memset( ctx->V, 0x01, md_info->size );
+
+    ctx->f_entropy = f_entropy;
+    ctx->p_entropy = p_entropy;
+
+    ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
+
+    /*
+     * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
+     * each hash function, then according to SP800-90A rev1 10.1 table 2,
+     * min_entropy_len (in bits) is security_strength.
+     *
+     * (This also matches the sizes used in the NIST test vectors.)
+     */
+    entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+                  md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+                                        32;  /* better (256+) -> 256 bits */
+
+    /*
+     * For initialisation, use more entropy to emulate a nonce
+     * (Again, matches test vectors.)
+     */
+    ctx->entropy_len = entropy_len * 3 / 2;
+
+    if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
+        return( ret );
+
+    ctx->entropy_len = entropy_len;
+
+    return( 0 );
+}
+
+/*
+ * Set prediction resistance
+ */
+void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
+                                          int resistance )
+{
+    ctx->prediction_resistance = resistance;
+}
+
+/*
+ * Set entropy length grabbed for reseeds
+ */
+void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
+{
+    ctx->entropy_len = len;
+}
+
+/*
+ * Set reseed interval
+ */
+void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
+{
+    ctx->reseed_interval = interval;
+}
+
+/*
+ * HMAC_DRBG random function with optional additional data:
+ * 10.1.2.5 (arabic) + 9.3 (Roman)
+ */
+int hmac_drbg_random_with_add( void *p_rng,
+                               unsigned char *output, size_t out_len,
+                               const unsigned char *additional, size_t add_len )
+{
+    int ret;
+    hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
+    size_t md_len = md_get_size( ctx->md_ctx.md_info );
+    size_t left = out_len;
+    unsigned char *out = output;
+
+    /* II. Check request length */
+    if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
+        return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
+
+    /* III. Check input length */
+    if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
+        return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+
+    /* 1. (aka VII and IX) Check reseed counter and PR */
+    if( ctx->f_entropy != NULL && /* For no-reseeding instances */
+        ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
+          ctx->reseed_counter > ctx->reseed_interval ) )
+    {
+        if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+            return( ret );
+
+        add_len = 0; /* VII.4 */
+    }
+
+    /* 2. Use additional data if any */
+    if( additional != NULL && add_len != 0 )
+        hmac_drbg_update( ctx, additional, add_len );
+
+    /* 3, 4, 5. Generate bytes */
+    while( left != 0 )
+    {
+        size_t use_len = left > md_len ? md_len : left;
+
+        md_hmac_reset( &ctx->md_ctx );
+        md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+        md_hmac_finish( &ctx->md_ctx, ctx->V );
+
+        memcpy( out, ctx->V, use_len );
+        out += use_len;
+        left -= use_len;
+    }
+
+    /* 6. Update */
+    hmac_drbg_update( ctx, additional, add_len );
+
+    /* 7. Update reseed counter */
+    ctx->reseed_counter++;
+
+    /* 8. Done */
+    return( 0 );
+}
+
+/*
+ * HMAC_DRBG random function
+ */
+int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
+{
+    return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
+}
+
+/*
+ * Free an HMAC_DRBG context
+ */
+void hmac_drbg_free( hmac_drbg_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    md_free_ctx( &ctx->md_ctx );
+
+    polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) );
+}
+
+#if defined(POLARSSL_FS_IO)
+int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
+{
+    int ret;
+    FILE *f;
+    unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
+
+    if( ( f = fopen( path, "wb" ) ) == NULL )
+        return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
+
+    if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
+        goto exit;
+
+    if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
+    {
+        ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
+        goto exit;
+    }
+
+    ret = 0;
+
+exit:
+    fclose( f );
+    return( ret );
+}
+
+int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
+{
+    FILE *f;
+    size_t n;
+    unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    n = (size_t) ftell( f );
+    fseek( f, 0, SEEK_SET );
+
+    if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+    }
+
+    if( fread( buf, 1, n, f ) != n )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    hmac_drbg_update( ctx, buf, n );
+
+    return( hmac_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* POLARSSL_FS_IO */
+
+
+#if defined(POLARSSL_SELF_TEST)
+
+#include <stdio.h>
+
+#if !defined(POLARSSL_SHA1_C)
+/* Dummy checkup routine */
+int hmac_drbg_self_test( int verbose )
+{
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+#else
+
+#define OUTPUT_LEN  80
+
+/* From a NIST PR=true test vector */
+static unsigned char entropy_pr[] = {
+    0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
+    0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
+    0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
+    0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
+    0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
+static const unsigned char result_pr[OUTPUT_LEN] = {
+    0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
+    0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
+    0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
+    0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
+    0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
+    0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
+    0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
+
+/* From a NIST PR=false test vector */
+static unsigned char entropy_nopr[] = {
+    0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
+    0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
+    0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
+    0xe9, 0x9d, 0xfe, 0xdf };
+static const unsigned char result_nopr[OUTPUT_LEN] = {
+    0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
+    0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
+    0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
+    0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
+    0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
+    0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
+    0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
+
+/* "Entropy" from buffer */
+static size_t test_offset;
+static int hmac_drbg_self_test_entropy( void *data,
+                                        unsigned char *buf, size_t len )
+{
+    const unsigned char *p = data;
+    memcpy( buf, p + test_offset, len );
+    test_offset += len;
+    return( 0 );
+}
+
+#define CHK( c )    if( (c) != 0 )                          \
+                    {                                       \
+                        if( verbose != 0 )                  \
+                            polarssl_printf( "failed\n" );  \
+                        return( 1 );                        \
+                    }
+
+/*
+ * Checkup routine for HMAC_DRBG with SHA-1
+ */
+int hmac_drbg_self_test( int verbose )
+{
+    hmac_drbg_context ctx;
+    unsigned char buf[OUTPUT_LEN];
+    const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
+
+    /*
+     * PR = True
+     */
+    if( verbose != 0 )
+        polarssl_printf( "  HMAC_DRBG (PR = True) : " );
+
+    test_offset = 0;
+    CHK( hmac_drbg_init( &ctx, md_info,
+                         hmac_drbg_self_test_entropy, entropy_pr,
+                         NULL, 0 ) );
+    hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
+    CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+    CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+    CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
+    hmac_drbg_free( &ctx );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    /*
+     * PR = False
+     */
+    if( verbose != 0 )
+        polarssl_printf( "  HMAC_DRBG (PR = False) : " );
+
+    test_offset = 0;
+    CHK( hmac_drbg_init( &ctx, md_info,
+                         hmac_drbg_self_test_entropy, entropy_nopr,
+                         NULL, 0 ) );
+    CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
+    CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+    CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+    CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
+    hmac_drbg_free( &ctx );
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_HMAC_DRBG_C */
index af6675661490ff8aef0d03da6d38c32973216096..7f9c5dc843d52b9f314ae6414504d58315c6b059 100644 (file)
@@ -1,11 +1,11 @@
 /**
  * \file md.c
- * 
+ *
  * \brief Generic message digest wrapper for PolarSSL
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_MD_C)
 
 #define strcasecmp  _stricmp
 #endif
 
-static const int supported_digests[] = {
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
 
-#if defined(POLARSSL_MD2_C)
-        POLARSSL_MD_MD2,
-#endif
+static const int supported_digests[] = {
 
-#if defined(POLARSSL_MD4_C)
-        POLARSSL_MD_MD4,
+#if defined(POLARSSL_SHA512_C)
+        POLARSSL_MD_SHA384,
+        POLARSSL_MD_SHA512,
 #endif
 
-#if defined(POLARSSL_MD5_C)
-        POLARSSL_MD_MD5,
+#if defined(POLARSSL_SHA256_C)
+        POLARSSL_MD_SHA224,
+        POLARSSL_MD_SHA256,
 #endif
 
 #if defined(POLARSSL_SHA1_C)
         POLARSSL_MD_SHA1,
 #endif
 
-#if defined(POLARSSL_SHA256_C)
-        POLARSSL_MD_SHA224,
-        POLARSSL_MD_SHA256,
+#if defined(POLARSSL_RIPEMD160_C)
+        POLARSSL_MD_RIPEMD160,
 #endif
 
-#if defined(POLARSSL_SHA512_C)
-        POLARSSL_MD_SHA384,
-        POLARSSL_MD_SHA512,
+#if defined(POLARSSL_MD5_C)
+        POLARSSL_MD_MD5,
 #endif
 
-        0
+#if defined(POLARSSL_MD4_C)
+        POLARSSL_MD_MD4,
+#endif
+
+#if defined(POLARSSL_MD2_C)
+        POLARSSL_MD_MD2,
+#endif
+
+        POLARSSL_MD_NONE
 };
 
 const int *md_list( void )
 {
-    return supported_digests;
+    return( supported_digests );
 }
 
 const md_info_t *md_info_from_string( const char *md_name )
 {
     if( NULL == md_name )
-        return NULL;
+        return( NULL );
 
     /* Get the appropriate digest information */
 #if defined(POLARSSL_MD2_C)
@@ -95,6 +108,10 @@ const md_info_t *md_info_from_string( const char *md_name )
     if( !strcasecmp( "MD5", md_name ) )
         return md_info_from_type( POLARSSL_MD_MD5 );
 #endif
+#if defined(POLARSSL_RIPEMD160_C)
+    if( !strcasecmp( "RIPEMD160", md_name ) )
+        return md_info_from_type( POLARSSL_MD_RIPEMD160 );
+#endif
 #if defined(POLARSSL_SHA1_C)
     if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) )
         return md_info_from_type( POLARSSL_MD_SHA1 );
@@ -111,7 +128,7 @@ const md_info_t *md_info_from_string( const char *md_name )
     if( !strcasecmp( "SHA512", md_name ) )
         return md_info_from_type( POLARSSL_MD_SHA512 );
 #endif
-    return NULL;
+    return( NULL );
 }
 
 const md_info_t *md_info_from_type( md_type_t md_type )
@@ -120,104 +137,120 @@ const md_info_t *md_info_from_type( md_type_t md_type )
     {
 #if defined(POLARSSL_MD2_C)
         case POLARSSL_MD_MD2:
-            return &md2_info;
+            return( &md2_info );
 #endif
 #if defined(POLARSSL_MD4_C)
         case POLARSSL_MD_MD4:
-            return &md4_info;
+            return( &md4_info );
 #endif
 #if defined(POLARSSL_MD5_C)
         case POLARSSL_MD_MD5:
-            return &md5_info;
+            return( &md5_info );
+#endif
+#if defined(POLARSSL_RIPEMD160_C)
+        case POLARSSL_MD_RIPEMD160:
+            return( &ripemd160_info );
 #endif
 #if defined(POLARSSL_SHA1_C)
         case POLARSSL_MD_SHA1:
-            return &sha1_info;
+            return( &sha1_info );
 #endif
 #if defined(POLARSSL_SHA256_C)
         case POLARSSL_MD_SHA224:
-            return &sha224_info;
+            return( &sha224_info );
         case POLARSSL_MD_SHA256:
-            return &sha256_info;
+            return( &sha256_info );
 #endif
 #if defined(POLARSSL_SHA512_C)
         case POLARSSL_MD_SHA384:
-            return &sha384_info;
+            return( &sha384_info );
         case POLARSSL_MD_SHA512:
-            return &sha512_info;
+            return( &sha512_info );
 #endif
         default:
-            return NULL;
+            return( NULL );
     }
 }
 
+void md_init( md_context_t *ctx )
+{
+    memset( ctx, 0, sizeof( md_context_t ) );
+}
+
+void md_free( md_context_t *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    if( ctx->md_ctx )
+        ctx->md_info->ctx_free_func( ctx->md_ctx );
+
+    polarssl_zeroize( ctx, sizeof( md_context_t ) );
+}
+
 int md_init_ctx( md_context_t *ctx, const md_info_t *md_info )
 {
     if( md_info == NULL || ctx == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
     memset( ctx, 0, sizeof( md_context_t ) );
 
     if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
-        return POLARSSL_ERR_MD_ALLOC_FAILED;
+        return( POLARSSL_ERR_MD_ALLOC_FAILED );
 
     ctx->md_info = md_info;
 
     md_info->starts_func( ctx->md_ctx );
 
-    return 0;
+    return( 0 );
 }
 
 int md_free_ctx( md_context_t *ctx )
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
-
-    ctx->md_info->ctx_free_func( ctx->md_ctx );
-    ctx->md_ctx = NULL;
+    md_free( ctx );
 
-    return 0;
+    return( 0 );
 }
 
 int md_starts( md_context_t *ctx )
 {
     if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
     ctx->md_info->starts_func( ctx->md_ctx );
 
-    return 0;
+    return( 0 );
 }
 
 int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
 {
     if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
     ctx->md_info->update_func( ctx->md_ctx, input, ilen );
 
-    return 0;
+    return( 0 );
 }
 
 int md_finish( md_context_t *ctx, unsigned char *output )
 {
     if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
     ctx->md_info->finish_func( ctx->md_ctx, output );
 
-    return 0;
+    return( 0 );
 }
 
 int md( const md_info_t *md_info, const unsigned char *input, size_t ilen,
             unsigned char *output )
 {
-    if ( md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+    if( md_info == NULL )
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
     md_info->digest_func( input, ilen, output );
 
-    return 0;
+    return( 0 );
 }
 
 int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
@@ -227,7 +260,7 @@ int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
 #endif
 
     if( md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
 #if defined(POLARSSL_FS_IO)
     ret = md_info->file_func( path, output );
@@ -239,48 +272,48 @@ int md_file( const md_info_t *md_info, const char *path, unsigned char *output )
     ((void) path);
     ((void) output);
 
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
-#endif
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
+#endif /* POLARSSL_FS_IO */
 }
 
 int md_hmac_starts( md_context_t *ctx, const unsigned char *key, size_t keylen )
 {
     if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
-    ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen);
+    ctx->md_info->hmac_starts_func( ctx->md_ctx, key, keylen );
 
-    return 0;
+    return( 0 );
 }
 
 int md_hmac_update( md_context_t *ctx, const unsigned char *input, size_t ilen )
 {
     if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
     ctx->md_info->hmac_update_func( ctx->md_ctx, input, ilen );
 
-    return 0;
+    return( 0 );
 }
 
-int md_hmac_finish( md_context_t *ctx, unsigned char *output)
+int md_hmac_finish( md_context_t *ctx, unsigned char *output )
 {
     if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
-    ctx->md_info->hmac_finish_func( ctx->md_ctx, output);
+    ctx->md_info->hmac_finish_func( ctx->md_ctx, output );
 
-    return 0;
+    return( 0 );
 }
 
 int md_hmac_reset( md_context_t *ctx )
 {
     if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
-    ctx->md_info->hmac_reset_func( ctx->md_ctx);
+    ctx->md_info->hmac_reset_func( ctx->md_ctx );
 
-    return 0;
+    return( 0 );
 }
 
 int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
@@ -288,21 +321,21 @@ int md_hmac( const md_info_t *md_info, const unsigned char *key, size_t keylen,
                 unsigned char *output )
 {
     if( md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
     md_info->hmac_func( key, keylen, input, ilen, output );
 
-    return 0;
+    return( 0 );
 }
 
 int md_process( md_context_t *ctx, const unsigned char *data )
 {
     if( ctx == NULL || ctx->md_info == NULL )
-        return POLARSSL_ERR_MD_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_MD_BAD_INPUT_DATA );
 
     ctx->md_info->process_func( ctx->md_ctx, data );
 
-    return 0;
+    return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_MD_C */
index 93e77d2f6a31657f271f3dcc752189d882448b04..45bce371c7ee82234c331aa85aec9f24c4d8be64 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  RFC 1115/1319 compliant MD2 implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://www.ietf.org/rfc/rfc1319.txt
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_MD2_C)
 
 #include <stdio.h>
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if !defined(POLARSSL_MD2_ALT)
 
 static const unsigned char PI_SUBST[256] =
@@ -71,6 +86,19 @@ static const unsigned char PI_SUBST[256] =
     0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
 };
 
+void md2_init( md2_context *ctx )
+{
+    memset( ctx, 0, sizeof( md2_context ) );
+}
+
+void md2_free( md2_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( md2_context ) );
+}
+
 /*
  * MD2 context setup
  */
@@ -174,11 +202,11 @@ void md2( const unsigned char *input, size_t ilen, unsigned char output[16] )
 {
     md2_context ctx;
 
+    md2_init( &ctx );
     md2_starts( &ctx );
     md2_update( &ctx, input, ilen );
     md2_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md2_context ) );
+    md2_free( &ctx );
 }
 
 #if defined(POLARSSL_FS_IO)
@@ -195,14 +223,14 @@ int md2_file( const char *path, unsigned char output[16] )
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
 
+    md2_init( &ctx );
     md2_starts( &ctx );
 
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         md2_update( &ctx, buf, n );
 
     md2_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md2_context ) );
+    md2_free( &ctx );
 
     if( ferror( f ) != 0 )
     {
@@ -218,7 +246,8 @@ int md2_file( const char *path, unsigned char output[16] )
 /*
  * MD2 HMAC context setup
  */
-void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen )
+void md2_hmac_starts( md2_context *ctx, const unsigned char *key,
+                      size_t keylen )
 {
     size_t i;
     unsigned char sum[16];
@@ -242,13 +271,14 @@ void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen
     md2_starts( ctx );
     md2_update( ctx, ctx->ipad, 16 );
 
-    memset( sum, 0, sizeof( sum ) );
+    polarssl_zeroize( sum, sizeof( sum ) );
 }
 
 /*
  * MD2 HMAC process buffer
  */
-void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen )
+void md2_hmac_update( md2_context *ctx, const unsigned char *input,
+                      size_t ilen )
 {
     md2_update( ctx, input, ilen );
 }
@@ -266,7 +296,7 @@ void md2_hmac_finish( md2_context *ctx, unsigned char output[16] )
     md2_update( ctx, tmpbuf, 16 );
     md2_finish( ctx, output );
 
-    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
 }
 
 /*
@@ -287,11 +317,11 @@ void md2_hmac( const unsigned char *key, size_t keylen,
 {
     md2_context ctx;
 
+    md2_init( &ctx );
     md2_hmac_starts( &ctx, key, keylen );
     md2_hmac_update( &ctx, input, ilen );
     md2_hmac_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md2_context ) );
+    md2_free( &ctx );
 }
 
 #if defined(POLARSSL_SELF_TEST)
@@ -340,7 +370,7 @@ int md2_self_test( int verbose )
     for( i = 0; i < 7; i++ )
     {
         if( verbose != 0 )
-            printf( "  MD2 test #%d: ", i + 1 );
+            polarssl_printf( "  MD2 test #%d: ", i + 1 );
 
         md2( (unsigned char *) md2_test_str[i],
              strlen( md2_test_str[i] ), md2sum );
@@ -348,21 +378,21 @@ int md2_self_test( int verbose )
         if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
             return( 1 );
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_MD2_C */
index e14c83dc2451e11e2f89103df8568d9ef36def57..f6b71d56e575a9933d341162dcfceab472a2bddf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  RFC 1186/1320 compliant MD4 implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://www.ietf.org/rfc/rfc1320.txt
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_MD4_C)
 
 #include <stdio.h>
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if !defined(POLARSSL_MD4_ALT)
 
 /*
 }
 #endif
 
+void md4_init( md4_context *ctx )
+{
+    memset( ctx, 0, sizeof( md4_context ) );
+}
+
+void md4_free( md4_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( md4_context ) );
+}
+
 /*
  * MD4 context setup
  */
@@ -189,7 +217,7 @@ void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
     size_t fill;
     uint32_t left;
 
-    if( ilen <= 0 )
+    if( ilen == 0 )
         return;
 
     left = ctx->total[0] & 0x3F;
@@ -270,11 +298,11 @@ void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
 {
     md4_context ctx;
 
+    md4_init( &ctx );
     md4_starts( &ctx );
     md4_update( &ctx, input, ilen );
     md4_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md4_context ) );
+    md4_free( &ctx );
 }
 
 #if defined(POLARSSL_FS_IO)
@@ -291,14 +319,14 @@ int md4_file( const char *path, unsigned char output[16] )
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
 
+    md4_init( &ctx );
     md4_starts( &ctx );
 
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         md4_update( &ctx, buf, n );
 
     md4_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md4_context ) );
+    md4_free( &ctx );
 
     if( ferror( f ) != 0 )
     {
@@ -314,7 +342,8 @@ int md4_file( const char *path, unsigned char output[16] )
 /*
  * MD4 HMAC context setup
  */
-void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen )
+void md4_hmac_starts( md4_context *ctx, const unsigned char *key,
+                      size_t keylen )
 {
     size_t i;
     unsigned char sum[16];
@@ -338,13 +367,14 @@ void md4_hmac_starts( md4_context *ctx, const unsigned char *key, size_t keylen
     md4_starts( ctx );
     md4_update( ctx, ctx->ipad, 64 );
 
-    memset( sum, 0, sizeof( sum ) );
+    polarssl_zeroize( sum, sizeof( sum ) );
 }
 
 /*
  * MD4 HMAC process buffer
  */
-void md4_hmac_update( md4_context *ctx, const unsigned char *input, size_t ilen )
+void md4_hmac_update( md4_context *ctx, const unsigned char *input,
+                      size_t ilen )
 {
     md4_update( ctx, input, ilen );
 }
@@ -362,7 +392,7 @@ void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
     md4_update( ctx, tmpbuf, 16 );
     md4_finish( ctx, output );
 
-    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
 }
 
 /*
@@ -383,11 +413,11 @@ void md4_hmac( const unsigned char *key, size_t keylen,
 {
     md4_context ctx;
 
+    md4_init( &ctx );
     md4_hmac_starts( &ctx, key, keylen );
     md4_hmac_update( &ctx, input, ilen );
     md4_hmac_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md4_context ) );
+    md4_free( &ctx );
 }
 
 #if defined(POLARSSL_SELF_TEST)
@@ -397,7 +427,7 @@ void md4_hmac( const unsigned char *key, size_t keylen,
  */
 static const char md4_test_str[7][81] =
 {
-    { "" }, 
+    { "" },
     { "a" },
     { "abc" },
     { "message digest" },
@@ -436,7 +466,7 @@ int md4_self_test( int verbose )
     for( i = 0; i < 7; i++ )
     {
         if( verbose != 0 )
-            printf( "  MD4 test #%d: ", i + 1 );
+            polarssl_printf( "  MD4 test #%d: ", i + 1 );
 
         md4( (unsigned char *) md4_test_str[i],
              strlen( md4_test_str[i] ), md4sum );
@@ -444,21 +474,21 @@ int md4_self_test( int verbose )
         if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
             return( 1 );
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_MD4_C */
index b28461e9b2b56b711144f02f96f0932bec37d819..89354bc7d3ae22a663fc6af01d359fe2848fb71f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  RFC 1321 compliant MD5 implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://www.ietf.org/rfc/rfc1321.txt
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_MD5_C)
 
 #include <stdio.h>
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if !defined(POLARSSL_MD5_ALT)
 
 /*
 }
 #endif
 
+void md5_init( md5_context *ctx )
+{
+    memset( ctx, 0, sizeof( md5_context ) );
+}
+
+void md5_free( md5_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( md5_context ) );
+}
+
 /*
  * MD5 context setup
  */
@@ -151,7 +179,7 @@ void md5_process( md5_context *ctx, const unsigned char data[64] )
     P( B, C, D, A, 12, 20, 0x8D2A4C8A );
 
 #undef F
-    
+
 #define F(x,y,z) (x ^ y ^ z)
 
     P( A, B, C, D,  5,  4, 0xFFFA3942 );
@@ -208,7 +236,7 @@ void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
     size_t fill;
     uint32_t left;
 
-    if( ilen <= 0 )
+    if( ilen == 0 )
         return;
 
     left = ctx->total[0] & 0x3F;
@@ -287,11 +315,11 @@ void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
 {
     md5_context ctx;
 
+    md5_init( &ctx );
     md5_starts( &ctx );
     md5_update( &ctx, input, ilen );
     md5_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md5_context ) );
+    md5_free( &ctx );
 }
 
 #if defined(POLARSSL_FS_IO)
@@ -308,14 +336,14 @@ int md5_file( const char *path, unsigned char output[16] )
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
 
+    md5_init( &ctx );
     md5_starts( &ctx );
 
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         md5_update( &ctx, buf, n );
 
     md5_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md5_context ) );
+    md5_free( &ctx );
 
     if( ferror( f ) != 0 )
     {
@@ -331,7 +359,8 @@ int md5_file( const char *path, unsigned char output[16] )
 /*
  * MD5 HMAC context setup
  */
-void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen )
+void md5_hmac_starts( md5_context *ctx, const unsigned char *key,
+                      size_t keylen )
 {
     size_t i;
     unsigned char sum[16];
@@ -355,13 +384,14 @@ void md5_hmac_starts( md5_context *ctx, const unsigned char *key, size_t keylen
     md5_starts( ctx );
     md5_update( ctx, ctx->ipad, 64 );
 
-    memset( sum, 0, sizeof( sum ) );
+    polarssl_zeroize( sum, sizeof( sum ) );
 }
 
 /*
  * MD5 HMAC process buffer
  */
-void md5_hmac_update( md5_context *ctx, const unsigned char *input, size_t ilen )
+void md5_hmac_update( md5_context *ctx, const unsigned char *input,
+                      size_t ilen )
 {
     md5_update( ctx, input, ilen );
 }
@@ -379,7 +409,7 @@ void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
     md5_update( ctx, tmpbuf, 16 );
     md5_finish( ctx, output );
 
-    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
 }
 
 /*
@@ -400,11 +430,11 @@ void md5_hmac( const unsigned char *key, size_t keylen,
 {
     md5_context ctx;
 
+    md5_init( &ctx );
     md5_hmac_starts( &ctx, key, keylen );
     md5_hmac_update( &ctx, input, ilen );
     md5_hmac_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( md5_context ) );
+    md5_free( &ctx );
 }
 
 #if defined(POLARSSL_SELF_TEST)
@@ -413,7 +443,7 @@ void md5_hmac( const unsigned char *key, size_t keylen,
  */
 static unsigned char md5_test_buf[7][81] =
 {
-    { "" }, 
+    { "" },
     { "a" },
     { "abc" },
     { "message digest" },
@@ -522,29 +552,29 @@ int md5_self_test( int verbose )
     for( i = 0; i < 7; i++ )
     {
         if( verbose != 0 )
-            printf( "  MD5 test #%d: ", i + 1 );
+            polarssl_printf( "  MD5 test #%d: ", i + 1 );
 
         md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
 
         if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
             return( 1 );
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     for( i = 0; i < 7; i++ )
     {
         if( verbose != 0 )
-            printf( "  HMAC-MD5 test #%d: ", i + 1 );
+            polarssl_printf( "  HMAC-MD5 test #%d: ", i + 1 );
 
         if( i == 5 || i == 6 )
         {
@@ -565,21 +595,21 @@ int md5_self_test( int verbose )
         if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
             return( 1 );
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_MD5_C */
index 038b13272b60cf8b450c9ce2e255379461fc854c..de701d319a64669cc17768992d4f0bc25e22f294 100644 (file)
@@ -5,7 +5,7 @@
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_MD_C)
 
 #include "polarssl/md5.h"
 #endif
 
+#if defined(POLARSSL_RIPEMD160_C)
+#include "polarssl/ripemd160.h"
+#endif
+
 #if defined(POLARSSL_SHA1_C)
 #include "polarssl/sha1.h"
 #endif
@@ -57,8 +65,8 @@
 #include "polarssl/sha512.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 
 #include <stdlib.h>
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if defined(POLARSSL_MD2_C)
 
 static void md2_starts_wrap( void *ctx )
@@ -73,7 +86,8 @@ static void md2_starts_wrap( void *ctx )
     md2_starts( (md2_context *) ctx );
 }
 
-static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void md2_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
 {
     md2_update( (md2_context *) ctx, input, ilen );
 }
@@ -90,16 +104,18 @@ static int md2_file_wrap( const char *path, unsigned char *output )
 #else
     ((void) path);
     ((void) output);
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
 }
 
-static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+static void md2_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                  size_t keylen )
 {
     md2_hmac_starts( (md2_context *) ctx, key, keylen );
 }
 
-static void md2_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void md2_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                  size_t ilen )
 {
     md2_hmac_update( (md2_context *) ctx, input, ilen );
 }
@@ -121,6 +137,7 @@ static void * md2_ctx_alloc( void )
 
 static void md2_ctx_free( void *ctx )
 {
+    polarssl_zeroize( ctx, sizeof( md2_context ) );
     polarssl_free( ctx );
 }
 
@@ -150,7 +167,7 @@ const md_info_t md2_info = {
     md2_process_wrap,
 };
 
-#endif
+#endif /* POLARSSL_MD2_C */
 
 #if defined(POLARSSL_MD4_C)
 
@@ -159,7 +176,8 @@ static void md4_starts_wrap( void *ctx )
     md4_starts( (md4_context *) ctx );
 }
 
-static void md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void md4_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
 {
     md4_update( (md4_context *) ctx, input, ilen );
 }
@@ -176,16 +194,18 @@ static int md4_file_wrap( const char *path, unsigned char *output )
 #else
     ((void) path);
     ((void) output);
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
 }
 
-static void md4_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+static void md4_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                  size_t keylen )
 {
     md4_hmac_starts( (md4_context *) ctx, key, keylen );
 }
 
-static void md4_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void md4_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                  size_t ilen )
 {
     md4_hmac_update( (md4_context *) ctx, input, ilen );
 }
@@ -207,6 +227,7 @@ static void *md4_ctx_alloc( void )
 
 static void md4_ctx_free( void *ctx )
 {
+    polarssl_zeroize( ctx, sizeof( md4_context ) );
     polarssl_free( ctx );
 }
 
@@ -234,7 +255,7 @@ const md_info_t md4_info = {
     md4_process_wrap,
 };
 
-#endif
+#endif /* POLARSSL_MD4_C */
 
 #if defined(POLARSSL_MD5_C)
 
@@ -243,7 +264,8 @@ static void md5_starts_wrap( void *ctx )
     md5_starts( (md5_context *) ctx );
 }
 
-static void md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void md5_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
 {
     md5_update( (md5_context *) ctx, input, ilen );
 }
@@ -260,16 +282,18 @@ static int md5_file_wrap( const char *path, unsigned char *output )
 #else
     ((void) path);
     ((void) output);
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
 }
 
-static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+static void md5_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                  size_t keylen )
 {
     md5_hmac_starts( (md5_context *) ctx, key, keylen );
 }
 
-static void md5_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void md5_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                  size_t ilen )
 {
     md5_hmac_update( (md5_context *) ctx, input, ilen );
 }
@@ -291,6 +315,7 @@ static void * md5_ctx_alloc( void )
 
 static void md5_ctx_free( void *ctx )
 {
+    polarssl_zeroize( ctx, sizeof( md5_context ) );
     polarssl_free( ctx );
 }
 
@@ -318,7 +343,103 @@ const md_info_t md5_info = {
     md5_process_wrap,
 };
 
+#endif /* POLARSSL_MD5_C */
+
+#if defined(POLARSSL_RIPEMD160_C)
+
+static void ripemd160_starts_wrap( void *ctx )
+{
+    ripemd160_starts( (ripemd160_context *) ctx );
+}
+
+static void ripemd160_update_wrap( void *ctx, const unsigned char *input,
+                                   size_t ilen )
+{
+    ripemd160_update( (ripemd160_context *) ctx, input, ilen );
+}
+
+static void ripemd160_finish_wrap( void *ctx, unsigned char *output )
+{
+    ripemd160_finish( (ripemd160_context *) ctx, output );
+}
+
+static int ripemd160_file_wrap( const char *path, unsigned char *output )
+{
+#if defined(POLARSSL_FS_IO)
+    return ripemd160_file( path, output );
+#else
+    ((void) path);
+    ((void) output);
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
+}
+
+static void ripemd160_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                        size_t keylen )
+{
+    ripemd160_hmac_starts( (ripemd160_context *) ctx, key, keylen );
+}
+
+static void ripemd160_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                        size_t ilen )
+{
+    ripemd160_hmac_update( (ripemd160_context *) ctx, input, ilen );
+}
+
+static void ripemd160_hmac_finish_wrap( void *ctx, unsigned char *output )
+{
+    ripemd160_hmac_finish( (ripemd160_context *) ctx, output );
+}
+
+static void ripemd160_hmac_reset_wrap( void *ctx )
+{
+    ripemd160_hmac_reset( (ripemd160_context *) ctx );
+}
+
+static void * ripemd160_ctx_alloc( void )
+{
+    ripemd160_context *ctx;
+    ctx = (ripemd160_context *) polarssl_malloc( sizeof( ripemd160_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    ripemd160_init( ctx );
+
+    return( ctx );
+}
+
+static void ripemd160_ctx_free( void *ctx )
+{
+    ripemd160_free( (ripemd160_context *) ctx );
+    polarssl_free( ctx );
+}
+
+static void ripemd160_process_wrap( void *ctx, const unsigned char *data )
+{
+    ripemd160_process( (ripemd160_context *) ctx, data );
+}
+
+const md_info_t ripemd160_info = {
+    POLARSSL_MD_RIPEMD160,
+    "RIPEMD160",
+    20,
+    ripemd160_starts_wrap,
+    ripemd160_update_wrap,
+    ripemd160_finish_wrap,
+    ripemd160,
+    ripemd160_file_wrap,
+    ripemd160_hmac_starts_wrap,
+    ripemd160_hmac_update_wrap,
+    ripemd160_hmac_finish_wrap,
+    ripemd160_hmac_reset_wrap,
+    ripemd160_hmac,
+    ripemd160_ctx_alloc,
+    ripemd160_ctx_free,
+    ripemd160_process_wrap,
+};
+
+#endif /* POLARSSL_RIPEMD160_C */
 
 #if defined(POLARSSL_SHA1_C)
 
@@ -327,7 +448,8 @@ static void sha1_starts_wrap( void *ctx )
     sha1_starts( (sha1_context *) ctx );
 }
 
-static void sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha1_update_wrap( void *ctx, const unsigned char *input,
+                              size_t ilen )
 {
     sha1_update( (sha1_context *) ctx, input, ilen );
 }
@@ -344,16 +466,18 @@ static int sha1_file_wrap( const char *path, unsigned char *output )
 #else
     ((void) path);
     ((void) output);
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
 }
 
-static void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+static void sha1_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                   size_t keylen )
 {
     sha1_hmac_starts( (sha1_context *) ctx, key, keylen );
 }
 
-static void sha1_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha1_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                   size_t ilen )
 {
     sha1_hmac_update( (sha1_context *) ctx, input, ilen );
 }
@@ -370,11 +494,20 @@ static void sha1_hmac_reset_wrap( void *ctx )
 
 static void * sha1_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( sha1_context ) );
+    sha1_context *ctx;
+    ctx = (sha1_context *) polarssl_malloc( sizeof( sha1_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    sha1_init( ctx );
+
+    return( ctx );
 }
 
 static void sha1_ctx_free( void *ctx )
 {
+    sha1_free( (sha1_context *) ctx );
     polarssl_free( ctx );
 }
 
@@ -402,7 +535,7 @@ const md_info_t sha1_info = {
     sha1_process_wrap,
 };
 
-#endif
+#endif /* POLARSSL_SHA1_C */
 
 /*
  * Wrappers for generic message digests
@@ -414,7 +547,8 @@ static void sha224_starts_wrap( void *ctx )
     sha256_starts( (sha256_context *) ctx, 1 );
 }
 
-static void sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha224_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
 {
     sha256_update( (sha256_context *) ctx, input, ilen );
 }
@@ -437,16 +571,18 @@ static int sha224_file_wrap( const char *path, unsigned char *output )
 #else
     ((void) path);
     ((void) output);
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
 }
 
-static void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+static void sha224_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                     size_t keylen )
 {
     sha256_hmac_starts( (sha256_context *) ctx, key, keylen, 1 );
 }
 
-static void sha224_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha224_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                     size_t ilen )
 {
     sha256_hmac_update( (sha256_context *) ctx, input, ilen );
 }
@@ -475,6 +611,7 @@ static void * sha224_ctx_alloc( void )
 
 static void sha224_ctx_free( void *ctx )
 {
+    polarssl_zeroize( ctx, sizeof( sha256_context ) );
     polarssl_free( ctx );
 }
 
@@ -507,7 +644,8 @@ static void sha256_starts_wrap( void *ctx )
     sha256_starts( (sha256_context *) ctx, 0 );
 }
 
-static void sha256_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha256_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
 {
     sha256_update( (sha256_context *) ctx, input, ilen );
 }
@@ -530,16 +668,18 @@ static int sha256_file_wrap( const char *path, unsigned char *output )
 #else
     ((void) path);
     ((void) output);
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
 }
 
-static void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+static void sha256_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                     size_t keylen )
 {
     sha256_hmac_starts( (sha256_context *) ctx, key, keylen, 0 );
 }
 
-static void sha256_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha256_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                     size_t ilen )
 {
     sha256_hmac_update( (sha256_context *) ctx, input, ilen );
 }
@@ -563,11 +703,20 @@ static void sha256_hmac_wrap( const unsigned char *key, size_t keylen,
 
 static void * sha256_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( sha256_context ) );
+    sha256_context *ctx;
+    ctx = (sha256_context *) polarssl_malloc( sizeof( sha256_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    sha256_init( ctx );
+
+    return( ctx );
 }
 
 static void sha256_ctx_free( void *ctx )
 {
+    sha256_free( (sha256_context *) ctx );
     polarssl_free( ctx );
 }
 
@@ -595,7 +744,7 @@ const md_info_t sha256_info = {
     sha256_process_wrap,
 };
 
-#endif
+#endif /* POLARSSL_SHA256_C */
 
 #if defined(POLARSSL_SHA512_C)
 
@@ -604,7 +753,8 @@ static void sha384_starts_wrap( void *ctx )
     sha512_starts( (sha512_context *) ctx, 1 );
 }
 
-static void sha384_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha384_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
 {
     sha512_update( (sha512_context *) ctx, input, ilen );
 }
@@ -627,16 +777,18 @@ static int sha384_file_wrap( const char *path, unsigned char *output )
 #else
     ((void) path);
     ((void) output);
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
 }
 
-static void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+static void sha384_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                     size_t keylen )
 {
     sha512_hmac_starts( (sha512_context *) ctx, key, keylen, 1 );
 }
 
-static void sha384_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha384_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                     size_t ilen )
 {
     sha512_hmac_update( (sha512_context *) ctx, input, ilen );
 }
@@ -665,6 +817,7 @@ static void * sha384_ctx_alloc( void )
 
 static void sha384_ctx_free( void *ctx )
 {
+    polarssl_zeroize( ctx, sizeof( sha512_context ) );
     polarssl_free( ctx );
 }
 
@@ -697,7 +850,8 @@ static void sha512_starts_wrap( void *ctx )
     sha512_starts( (sha512_context *) ctx, 0 );
 }
 
-static void sha512_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha512_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
 {
     sha512_update( (sha512_context *) ctx, input, ilen );
 }
@@ -720,16 +874,18 @@ static int sha512_file_wrap( const char *path, unsigned char *output )
 #else
     ((void) path);
     ((void) output);
-    return POLARSSL_ERR_MD_FEATURE_UNAVAILABLE;
+    return( POLARSSL_ERR_MD_FEATURE_UNAVAILABLE );
 #endif
 }
 
-static void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key, size_t keylen )
+static void sha512_hmac_starts_wrap( void *ctx, const unsigned char *key,
+                                     size_t keylen )
 {
     sha512_hmac_starts( (sha512_context *) ctx, key, keylen, 0 );
 }
 
-static void sha512_hmac_update_wrap( void *ctx, const unsigned char *input, size_t ilen )
+static void sha512_hmac_update_wrap( void *ctx, const unsigned char *input,
+                                     size_t ilen )
 {
     sha512_hmac_update( (sha512_context *) ctx, input, ilen );
 }
@@ -753,11 +909,20 @@ static void sha512_hmac_wrap( const unsigned char *key, size_t keylen,
 
 static void * sha512_ctx_alloc( void )
 {
-    return polarssl_malloc( sizeof( sha512_context ) );
+    sha512_context *ctx;
+    ctx = (sha512_context *) polarssl_malloc( sizeof( sha512_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    sha512_init( ctx );
+
+    return( ctx );
 }
 
 static void sha512_ctx_free( void *ctx )
 {
+    sha512_free( (sha512_context *) ctx );
     polarssl_free( ctx );
 }
 
@@ -785,6 +950,6 @@ const md_info_t sha512_info = {
     sha512_process_wrap,
 };
 
-#endif
+#endif /* POLARSSL_SHA512_C */
 
-#endif
+#endif /* POLARSSL_MD_C */
index 7ec6498de0a25e6f2d5a4e07cb4f91c3146a1a7d..7710ba52b13cfd6a36fe63b0866c798b6227b932 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Buffer-based memory allocator
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
-#if defined(POLARSSL_MEMORY_C) && defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
 
-#include "polarssl/memory.h"
+#include "polarssl/memory_buffer_alloc.h"
 
 #include <string.h>
 
 #include "polarssl/threading.h"
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_fprintf fprintf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #define MAGIC1       0xFF00AA55
 #define MAGIC2       0xEE119966
 #define MAX_BT 20
@@ -77,6 +92,7 @@ typedef struct
     size_t          total_used;
     size_t          maximum_used;
     size_t          header_count;
+    size_t          maximum_header_count;
 #endif
 #if defined(POLARSSL_THREADING_C)
     threading_mutex_t   mutex;
@@ -93,17 +109,18 @@ static void debug_header( memory_header *hdr )
     size_t i;
 #endif
 
-    fprintf( stderr, "HDR:  PTR(%10u), PREV(%10u), NEXT(%10u), ALLOC(%u), SIZE(%10u)\n",
-            (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
-            hdr->alloc, hdr->size );
-    fprintf( stderr, "      FPREV(%10u), FNEXT(%10u)\n",
-            (size_t) hdr->prev_free, (size_t) hdr->next_free );
+    polarssl_fprintf( stderr, "HDR:  PTR(%10u), PREV(%10u), NEXT(%10u), "
+                              "ALLOC(%u), SIZE(%10u)\n",
+                      (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
+                      hdr->alloc, hdr->size );
+    polarssl_fprintf( stderr, "      FPREV(%10u), FNEXT(%10u)\n",
+                      (size_t) hdr->prev_free, (size_t) hdr->next_free );
 
 #if defined(POLARSSL_MEMORY_BACKTRACE)
-    fprintf( stderr, "TRACE: \n" );
+    polarssl_fprintf( stderr, "TRACE: \n" );
     for( i = 0; i < hdr->trace_count; i++ )
-        fprintf( stderr, "%s\n", hdr->trace[i] );
-    fprintf( stderr, "\n" );
+        polarssl_fprintf( stderr, "%s\n", hdr->trace[i] );
+    polarssl_fprintf( stderr, "\n" );
 #endif
 }
 
@@ -111,14 +128,14 @@ static void debug_chain()
 {
     memory_header *cur = heap.first;
 
-    fprintf( stderr, "\nBlock list\n" );
+    polarssl_fprintf( stderr, "\nBlock list\n" );
     while( cur != NULL )
     {
         debug_header( cur );
         cur = cur->next;
     }
 
-    fprintf( stderr, "Free list\n" );
+    polarssl_fprintf( stderr, "Free list\n" );
     cur = heap.first_free;
 
     while( cur != NULL )
@@ -134,7 +151,7 @@ static int verify_header( memory_header *hdr )
     if( hdr->magic1 != MAGIC1 )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
+        polarssl_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
 #endif
         return( 1 );
     }
@@ -142,7 +159,7 @@ static int verify_header( memory_header *hdr )
     if( hdr->magic2 != MAGIC2 )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
+        polarssl_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
 #endif
         return( 1 );
     }
@@ -150,7 +167,7 @@ static int verify_header( memory_header *hdr )
     if( hdr->alloc > 1 )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: alloc has illegal value\n" );
+        polarssl_fprintf( stderr, "FATAL: alloc has illegal value\n" );
 #endif
         return( 1 );
     }
@@ -158,7 +175,7 @@ static int verify_header( memory_header *hdr )
     if( hdr->prev != NULL && hdr->prev == hdr->next )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: prev == next\n" );
+        polarssl_fprintf( stderr, "FATAL: prev == next\n" );
 #endif
         return( 1 );
     }
@@ -166,7 +183,7 @@ static int verify_header( memory_header *hdr )
     if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: prev_free == next_free\n" );
+        polarssl_fprintf( stderr, "FATAL: prev_free == next_free\n" );
 #endif
         return( 1 );
     }
@@ -181,7 +198,8 @@ static int verify_chain()
     if( verify_header( heap.first ) != 0 )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: verification of first header failed\n" );
+        polarssl_fprintf( stderr, "FATAL: verification of first header "
+                                  "failed\n" );
 #endif
         return( 1 );
     }
@@ -189,7 +207,8 @@ static int verify_chain()
     if( heap.first->prev != NULL )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: verification failed: first->prev != NULL\n" );
+        polarssl_fprintf( stderr, "FATAL: verification failed: "
+                                  "first->prev != NULL\n" );
 #endif
         return( 1 );
     }
@@ -199,7 +218,8 @@ static int verify_chain()
         if( verify_header( cur ) != 0 )
         {
 #if defined(POLARSSL_MEMORY_DEBUG)
-            fprintf( stderr, "FATAL: verification of header failed\n" );
+            polarssl_fprintf( stderr, "FATAL: verification of header "
+                                      "failed\n" );
 #endif
             return( 1 );
         }
@@ -207,7 +227,8 @@ static int verify_chain()
         if( cur->prev != prv )
         {
 #if defined(POLARSSL_MEMORY_DEBUG)
-            fprintf( stderr, "FATAL: verification failed: cur->prev != prv\n" );
+            polarssl_fprintf( stderr, "FATAL: verification failed: "
+                                      "cur->prev != prv\n" );
 #endif
             return( 1 );
         }
@@ -253,7 +274,8 @@ static void *buffer_alloc_malloc( size_t len )
     if( cur->alloc != 0 )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: block in free_list but allocated data\n" );
+        polarssl_fprintf( stderr, "FATAL: block in free_list but allocated "
+                                  "data\n" );
 #endif
         exit( 1 );
     }
@@ -264,7 +286,8 @@ static void *buffer_alloc_malloc( size_t len )
 
     // Found location, split block if > memory_header + 4 room left
     //
-    if( cur->size - len < sizeof(memory_header) + POLARSSL_MEMORY_ALIGN_MULTIPLE )
+    if( cur->size - len < sizeof(memory_header) +
+                          POLARSSL_MEMORY_ALIGN_MULTIPLE )
     {
         cur->alloc = 1;
 
@@ -283,7 +306,7 @@ static void *buffer_alloc_malloc( size_t len )
 
 #if defined(POLARSSL_MEMORY_DEBUG)
         heap.total_used += cur->size;
-        if( heap.total_used > heap.maximum_used)
+        if( heap.total_used > heap.maximum_used )
             heap.maximum_used = heap.total_used;
 #endif
 #if defined(POLARSSL_MEMORY_BACKTRACE)
@@ -295,7 +318,7 @@ static void *buffer_alloc_malloc( size_t len )
         if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
             exit( 1 );
 
-        return ( (unsigned char *) cur ) + sizeof(memory_header);
+        return( ( (unsigned char *) cur ) + sizeof(memory_header) );
     }
 
     p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
@@ -335,8 +358,10 @@ static void *buffer_alloc_malloc( size_t len )
 
 #if defined(POLARSSL_MEMORY_DEBUG)
     heap.header_count++;
+    if( heap.header_count > heap.maximum_header_count )
+        heap.maximum_header_count = heap.header_count;
     heap.total_used += cur->size;
-    if( heap.total_used > heap.maximum_used)
+    if( heap.total_used > heap.maximum_used )
         heap.maximum_used = heap.total_used;
 #endif
 #if defined(POLARSSL_MEMORY_BACKTRACE)
@@ -348,7 +373,7 @@ static void *buffer_alloc_malloc( size_t len )
     if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
         exit( 1 );
 
-    return ( (unsigned char *) cur ) + sizeof(memory_header);
+    return( ( (unsigned char *) cur ) + sizeof(memory_header) );
 }
 
 static void buffer_alloc_free( void *ptr )
@@ -362,7 +387,8 @@ static void buffer_alloc_free( void *ptr )
     if( p < heap.buf || p > heap.buf + heap.len )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: polarssl_free() outside of managed space\n" );
+        polarssl_fprintf( stderr, "FATAL: polarssl_free() outside of managed "
+                                  "space\n" );
 #endif
         exit( 1 );
     }
@@ -376,7 +402,8 @@ static void buffer_alloc_free( void *ptr )
     if( hdr->alloc != 1 )
     {
 #if defined(POLARSSL_MEMORY_DEBUG)
-        fprintf( stderr, "FATAL: polarssl_free() on unallocated data\n" );
+        polarssl_fprintf( stderr, "FATAL: polarssl_free() on unallocated "
+                                  "data\n" );
 #endif
         exit( 1 );
     }
@@ -483,20 +510,24 @@ int memory_buffer_alloc_verify()
 #if defined(POLARSSL_MEMORY_DEBUG)
 void memory_buffer_alloc_status()
 {
-    fprintf( stderr,
-             "Current use: %u blocks / %u bytes, max: %u bytes, malloc / free: %u / %u\n",
-             heap.header_count, heap.total_used, heap.maximum_used,
-             heap.malloc_count, heap.free_count );
+    polarssl_fprintf( stderr,
+                      "Current use: %u blocks / %u bytes, max: %u blocks / "
+                      "%u bytes (total %u bytes), malloc / free: %u / %u\n",
+                      heap.header_count, heap.total_used,
+                      heap.maximum_header_count, heap.maximum_used,
+                      heap.maximum_header_count * sizeof( memory_header )
+                      + heap.maximum_used,
+                      heap.malloc_count, heap.free_count );
 
     if( heap.first->next == NULL )
-        fprintf( stderr, "All memory de-allocated in stack buffer\n" );
+        polarssl_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
     else
     {
-        fprintf( stderr, "Memory currently allocated:\n" );
+        polarssl_fprintf( stderr, "Memory currently allocated:\n" );
         debug_chain();
     }
 }
-#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_DEBUG */
+#endif /* POLARSSL_MEMORY_DEBUG */
 
 #if defined(POLARSSL_THREADING_C)
 static void *buffer_alloc_malloc_mutexed( size_t len )
@@ -514,7 +545,7 @@ static void buffer_alloc_free_mutexed( void *ptr )
     buffer_alloc_free( ptr );
     polarssl_mutex_unlock( &heap.mutex );
 }
-#endif
+#endif /* POLARSSL_THREADING_C */
 
 int memory_buffer_alloc_init( unsigned char *buf, size_t len )
 {
@@ -523,13 +554,19 @@ int memory_buffer_alloc_init( unsigned char *buf, size_t len )
 
 #if defined(POLARSSL_THREADING_C)
     polarssl_mutex_init( &heap.mutex );
-    polarssl_malloc = buffer_alloc_malloc_mutexed;
-    polarssl_free = buffer_alloc_free_mutexed;
+    platform_set_malloc_free( buffer_alloc_malloc_mutexed,
+                              buffer_alloc_free_mutexed );
 #else
-    polarssl_malloc = buffer_alloc_malloc;
-    polarssl_free = buffer_alloc_free;
+    platform_set_malloc_free( buffer_alloc_malloc, buffer_alloc_free );
 #endif
 
+    if( (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE )
+    {
+        buf += POLARSSL_MEMORY_ALIGN_MULTIPLE
+             - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
+        len -= (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
+    }
+
     heap.buf = buf;
     heap.len = len;
 
@@ -546,7 +583,7 @@ void memory_buffer_alloc_free()
 #if defined(POLARSSL_THREADING_C)
     polarssl_mutex_free( &heap.mutex );
 #endif
-    memset( &heap, 0, sizeof(buffer_alloc_ctx) );
+    polarssl_zeroize( &heap, sizeof(buffer_alloc_ctx) );
 }
 
-#endif /* POLARSSL_MEMORY_C && POLARSSL_MEMORY_BUFFER_ALLOC_C */
+#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */
index be2785d98da041a9e0e8eca51c75971101e7a733..ad4b8921c57100f7fccb1d48f0eb12c510084034 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  TCP networking functions
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_NET_C)
 
 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
     !defined(EFI32)
 
+#if defined(POLARSSL_HAVE_IPV6)
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+/* Enables getaddrinfo() & Co */
+#define _WIN32_WINNT 0x0501
+#include <ws2tcpip.h>
+#endif
+
 #include <winsock2.h>
 #include <windows.h>
 
+#if defined(_MSC_VER)
 #if defined(_WIN32_WCE)
 #pragma comment( lib, "ws2.lib" )
 #else
 #pragma comment( lib, "ws2_32.lib" )
 #endif
+#endif /* _MSC_VER */
 
 #define read(fd,buf,len)        recv(fd,(char*)buf,(int) len,0)
 #define write(fd,buf,len)       send(fd,(char*)buf,(int) len,0)
@@ -47,7 +62,7 @@
 
 static int wsa_init_done = 0;
 
-#else
+#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -63,7 +78,7 @@ static int wsa_init_done = 0;
 #include <errno.h>
 
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) ||  \
-    defined(__DragonflyBSD__)
+    defined(__DragonFly__)
 #include <sys/endian.h>
 #elif defined(__APPLE__) || defined(HAVE_MACHINE_ENDIAN_H) ||   \
       defined(EFIX64) || defined(EFI32)
@@ -76,11 +91,16 @@ static int wsa_init_done = 0;
 #include <endian.h>
 #endif
 
-#endif
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
 
 #include <stdlib.h>
 #include <stdio.h>
 
+#if defined(_MSC_VER) && !defined  snprintf && !defined(EFIX64) && \
+    !defined(EFI32)
+#define  snprintf  _snprintf
+#endif
+
 #if defined(POLARSSL_HAVE_TIME)
 #include <time.h>
 #endif
@@ -94,10 +114,11 @@ typedef UINT32 uint32_t;
 
 /*
  * htons() is not always available.
- * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and __BIG_ENDIAN
- * to help determine endianness.
+ * By default go for LITTLE_ENDIAN variant. Otherwise hope for _BYTE_ORDER and
+ * __BIG_ENDIAN to help determine endianness.
  */
-#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN
+#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) &&                   \
+    __BYTE_ORDER == __BIG_ENDIAN
 #define POLARSSL_HTONS(n) (n)
 #define POLARSSL_HTONL(n) (n)
 #else
@@ -109,27 +130,23 @@ typedef UINT32 uint32_t;
                            (((unsigned long )(n) & 0xFF000000) >> 24))
 #endif
 
-unsigned short net_htons(unsigned short n);
-unsigned long  net_htonl(unsigned long  n);
+unsigned short net_htons( unsigned short n );
+unsigned long  net_htonl( unsigned long  n );
 #define net_htons(n) POLARSSL_HTONS(n)
 #define net_htonl(n) POLARSSL_HTONL(n)
 
 /*
- * Initiate a TCP connection with host:port
+ * Prepare for using the sockets interface
  */
-int net_connect( int *fd, const char *host, int port )
+static int net_prepare( void )
 {
-    struct sockaddr_in server_addr;
-    struct hostent *server_host;
-
 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
     !defined(EFI32)
-
     WSADATA wsaData;
 
     if( wsa_init_done == 0 )
     {
-        if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
+        if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
             return( POLARSSL_ERR_NET_SOCKET_FAILED );
 
         wsa_init_done = 1;
@@ -139,6 +156,70 @@ int net_connect( int *fd, const char *host, int port )
     signal( SIGPIPE, SIG_IGN );
 #endif
 #endif
+    return( 0 );
+}
+
+/*
+ * Initiate a TCP connection with host:port
+ */
+int net_connect( int *fd, const char *host, int port )
+{
+#if defined(POLARSSL_HAVE_IPV6)
+    int ret;
+    struct addrinfo hints, *addr_list, *cur;
+    char port_str[6];
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
+
+    /* getaddrinfo expects port as a string */
+    memset( port_str, 0, sizeof( port_str ) );
+    snprintf( port_str, sizeof( port_str ), "%d", port );
+
+    /* Do name resolution with both IPv6 and IPv4, but only TCP */
+    memset( &hints, 0, sizeof( hints ) );
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+
+    if( getaddrinfo( host, port_str, &hints, &addr_list ) != 0 )
+        return( POLARSSL_ERR_NET_UNKNOWN_HOST );
+
+    /* Try the sockaddrs until a connection succeeds */
+    ret = POLARSSL_ERR_NET_UNKNOWN_HOST;
+    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+    {
+        *fd = (int) socket( cur->ai_family, cur->ai_socktype,
+                            cur->ai_protocol );
+        if( *fd < 0 )
+        {
+            ret = POLARSSL_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        if( connect( *fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
+        {
+            ret = 0;
+            break;
+        }
+
+        close( *fd );
+        ret = POLARSSL_ERR_NET_CONNECT_FAILED;
+    }
+
+    freeaddrinfo( addr_list );
+
+    return( ret );
+
+#else
+    /* Legacy IPv4-only version */
+
+    int ret;
+    struct sockaddr_in server_addr;
+    struct hostent *server_host;
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
 
     if( ( server_host = gethostbyname( host ) ) == NULL )
         return( POLARSSL_ERR_NET_UNKNOWN_HOST );
@@ -161,6 +242,7 @@ int net_connect( int *fd, const char *host, int port )
     }
 
     return( 0 );
+#endif /* POLARSSL_HAVE_IPV6 */
 }
 
 /*
@@ -168,25 +250,81 @@ int net_connect( int *fd, const char *host, int port )
  */
 int net_bind( int *fd, const char *bind_ip, int port )
 {
-    int n, c[4];
-    struct sockaddr_in server_addr;
-
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
-    !defined(EFI32)
-    WSADATA wsaData;
+#if defined(POLARSSL_HAVE_IPV6)
+    int n, ret;
+    struct addrinfo hints, *addr_list, *cur;
+    char port_str[6];
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
+
+    /* getaddrinfo expects port as a string */
+    memset( port_str, 0, sizeof( port_str ) );
+    snprintf( port_str, sizeof( port_str ), "%d", port );
+
+    /* Bind to IPv6 and/or IPv4, but only in TCP */
+    memset( &hints, 0, sizeof( hints ) );
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+    if( bind_ip == NULL )
+        hints.ai_flags = AI_PASSIVE;
+
+    if( getaddrinfo( bind_ip, port_str, &hints, &addr_list ) != 0 )
+        return( POLARSSL_ERR_NET_UNKNOWN_HOST );
 
-    if( wsa_init_done == 0 )
+    /* Try the sockaddrs until a binding succeeds */
+    ret = POLARSSL_ERR_NET_UNKNOWN_HOST;
+    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
     {
-        if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
-            return( POLARSSL_ERR_NET_SOCKET_FAILED );
-
-        wsa_init_done = 1;
+        *fd = (int) socket( cur->ai_family, cur->ai_socktype,
+                            cur->ai_protocol );
+        if( *fd < 0 )
+        {
+            ret = POLARSSL_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        n = 1;
+        if( setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
+                        (const char *) &n, sizeof( n ) ) != 0 )
+        {
+            close( *fd );
+            ret = POLARSSL_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        if( bind( *fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
+        {
+            close( *fd );
+            ret = POLARSSL_ERR_NET_BIND_FAILED;
+            continue;
+        }
+
+        if( listen( *fd, POLARSSL_NET_LISTEN_BACKLOG ) != 0 )
+        {
+            close( *fd );
+            ret = POLARSSL_ERR_NET_LISTEN_FAILED;
+            continue;
+        }
+
+        /* I we ever get there, it's a success */
+        ret = 0;
+        break;
     }
+
+    freeaddrinfo( addr_list );
+
+    return( ret );
+
 #else
-#if !defined(EFIX64) && !defined(EFI32)
-    signal( SIGPIPE, SIG_IGN );
-#endif
-#endif
+    /* Legacy IPv4-only version */
+
+    int ret, n, c[4];
+    struct sockaddr_in server_addr;
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
 
     if( ( *fd = (int) socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
         return( POLARSSL_ERR_NET_SOCKET_FAILED );
@@ -230,17 +368,35 @@ int net_bind( int *fd, const char *bind_ip, int port )
     }
 
     return( 0 );
+#endif /* POLARSSL_HAVE_IPV6 */
 }
 
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
 /*
- * Check if the current operation is blocking
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
  */
-static int net_is_blocking( void )
+static int net_would_block( int fd )
 {
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
-    !defined(EFI32)
+    ((void) fd);
     return( WSAGetLastError() == WSAEWOULDBLOCK );
+}
 #else
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ *
+ * Note: on a blocking socket this function always returns 0!
+ */
+static int net_would_block( int fd )
+{
+    /*
+     * Never return 'WOULD BLOCK' on a non-blocking socket
+     */
+    if( ( fcntl( fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
+        return( 0 );
+
     switch( errno )
     {
 #if defined EAGAIN
@@ -252,15 +408,19 @@ static int net_is_blocking( void )
             return( 1 );
     }
     return( 0 );
-#endif
 }
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
 
 /*
  * Accept a connection from a remote client
  */
 int net_accept( int bind_fd, int *client_fd, void *client_ip )
 {
+#if defined(POLARSSL_HAVE_IPV6)
+    struct sockaddr_storage client_addr;
+#else
     struct sockaddr_in client_addr;
+#endif
 
 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
     defined(_SOCKLEN_T_DECLARED)
@@ -274,15 +434,32 @@ int net_accept( int bind_fd, int *client_fd, void *client_ip )
 
     if( *client_fd < 0 )
     {
-        if( net_is_blocking() != 0 )
+        if( net_would_block( *client_fd ) != 0 )
             return( POLARSSL_ERR_NET_WANT_READ );
 
         return( POLARSSL_ERR_NET_ACCEPT_FAILED );
     }
 
     if( client_ip != NULL )
+    {
+#if defined(POLARSSL_HAVE_IPV6)
+        if( client_addr.ss_family == AF_INET )
+        {
+            struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
+            memcpy( client_ip, &addr4->sin_addr.s_addr,
+                        sizeof( addr4->sin_addr.s_addr ) );
+        }
+        else
+        {
+            struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
+            memcpy( client_ip, &addr6->sin6_addr.s6_addr,
+                        sizeof( addr6->sin6_addr.s6_addr ) );
+        }
+#else
         memcpy( client_ip, &client_addr.sin_addr.s_addr,
                     sizeof( client_addr.sin_addr.s_addr ) );
+#endif /* POLARSSL_HAVE_IPV6 */
+    }
 
     return( 0 );
 }
@@ -330,11 +507,12 @@ void net_usleep( unsigned long usec )
  */
 int net_recv( void *ctx, unsigned char *buf, size_t len )
 {
-    int ret = read( *((int *) ctx), buf, len );
+    int fd = *((int *) ctx);
+    int ret = read( fd, buf, len );
 
     if( ret < 0 )
     {
-        if( net_is_blocking() != 0 )
+        if( net_would_block( fd ) != 0 )
             return( POLARSSL_ERR_NET_WANT_READ );
 
 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
@@ -360,11 +538,12 @@ int net_recv( void *ctx, unsigned char *buf, size_t len )
  */
 int net_send( void *ctx, const unsigned char *buf, size_t len )
 {
-    int ret = write( *((int *) ctx), buf, len );
+    int fd = *((int *) ctx);
+    int ret = write( fd, buf, len );
 
     if( ret < 0 )
     {
-        if( net_is_blocking() != 0 )
+        if( net_would_block( fd ) != 0 )
             return( POLARSSL_ERR_NET_WANT_WRITE );
 
 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
@@ -394,4 +573,4 @@ void net_close( int fd )
     close( fd );
 }
 
-#endif
+#endif /* POLARSSL_NET_C */
index b0b551dea95ea779e61303760f4bdf65084ddf35..7b54054de2875e5642e087c64a7187a99d15698e 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief Object Identifier (OID) database
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_OID_C)
 
@@ -72,7 +76,7 @@ static const TYPE_T * oid_ ## NAME ## _from_asn1( const asn1_buf *oid )     \
 int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 )                  \
 {                                                                       \
     const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );        \
-    if( data == NULL ) return ( POLARSSL_ERR_OID_NOT_FOUND );           \
+    if( data == NULL ) return( POLARSSL_ERR_OID_NOT_FOUND );            \
     *ATTR1 = data->descriptor.ATTR1;                                    \
     return( 0 );                                                        \
 }
@@ -85,7 +89,7 @@ int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 )                  \
 int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 )                  \
 {                                                                       \
     const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );        \
-    if( data == NULL ) return ( POLARSSL_ERR_OID_NOT_FOUND );           \
+    if( data == NULL ) return( POLARSSL_ERR_OID_NOT_FOUND );            \
     *ATTR1 = data->ATTR1;                                               \
     return( 0 );                                                        \
 }
@@ -99,7 +103,7 @@ int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1 )                  \
 int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 )  \
 {                                                                           \
     const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );            \
-    if( data == NULL ) return ( POLARSSL_ERR_OID_NOT_FOUND );               \
+    if( data == NULL ) return( POLARSSL_ERR_OID_NOT_FOUND );                \
     *ATTR1 = data->ATTR1;                                                   \
     *ATTR2 = data->ATTR2;                                                   \
     return( 0 );                                                            \
@@ -195,6 +199,38 @@ static const oid_x520_attr_t oid_x520_attr_type[] =
         { ADD_LEN( OID_AT_POSTAL_CODE ), "id-at-postalCode",               "Postal code" },
         "postalCode",
     },
+    {
+        { ADD_LEN( OID_AT_SUR_NAME ),    "id-at-surName",                  "Surname" },
+        "SN",
+    },
+    {
+        { ADD_LEN( OID_AT_GIVEN_NAME ),  "id-at-givenName",                "Given name" },
+        "GN",
+    },
+    {
+        { ADD_LEN( OID_AT_INITIALS ),    "id-at-initials",                 "Initials" },
+        "initials",
+    },
+    {
+        { ADD_LEN( OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" },
+        "generationQualifier",
+    },
+    {
+        { ADD_LEN( OID_AT_TITLE ),       "id-at-title",                    "Title" },
+        "title",
+    },
+    {
+        { ADD_LEN( OID_AT_DN_QUALIFIER ),"id-at-dnQualifier",              "Distinguished Name qualifier" },
+        "dnQualifier",
+    },
+    {
+        { ADD_LEN( OID_AT_PSEUDONYM ),   "id-at-pseudonym",                "Pseudonym" },
+        "pseudonym",
+    },
+    {
+        { ADD_LEN( OID_DOMAIN_COMPONENT ), "id-domainComponent",           "Domain component" },
+        "DC",
+    },
     {
         { NULL, 0, NULL, NULL },
         NULL,
@@ -327,6 +363,10 @@ static const oid_sig_alg_t oid_sig_alg[] =
         { ADD_LEN( OID_ECDSA_SHA512 ),     "ecdsa-with-SHA512",    "ECDSA with SHA512" },
         POLARSSL_MD_SHA512,   POLARSSL_PK_ECDSA,
     },
+    {
+        { ADD_LEN( OID_RSASSA_PSS ),        "RSASSA-PSS",           "RSASSA-PSS" },
+        POLARSSL_MD_NONE,     POLARSSL_PK_RSASSA_PSS,
+    },
     {
         { NULL, 0, NULL, NULL },
         0, 0,
@@ -402,6 +442,18 @@ static const oid_ecp_grp_t oid_ecp_grp[] =
         { ADD_LEN( OID_EC_GRP_SECP521R1 ), "secp521r1",    "secp521r1" },
         POLARSSL_ECP_DP_SECP521R1,
     },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP192K1 ), "secp192k1",    "secp192k1" },
+        POLARSSL_ECP_DP_SECP192K1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP224K1 ), "secp224k1",    "secp224k1" },
+        POLARSSL_ECP_DP_SECP224K1,
+    },
+    {
+        { ADD_LEN( OID_EC_GRP_SECP256K1 ), "secp256k1",    "secp256k1" },
+        POLARSSL_ECP_DP_SECP256K1,
+    },
     {
         { ADD_LEN( OID_EC_GRP_BP256R1 ),   "brainpoolP256r1","brainpool256r1" },
         POLARSSL_ECP_DP_BP256R1,
@@ -481,10 +533,6 @@ static const oid_md_alg_t oid_md_alg[] =
         { ADD_LEN( OID_DIGEST_ALG_SHA1 ),      "id-sha1",      "SHA-1" },
         POLARSSL_MD_SHA1,
     },
-    {
-        { ADD_LEN( OID_DIGEST_ALG_SHA1 ),      "id-sha1",      "SHA-1" },
-        POLARSSL_MD_SHA1,
-    },
     {
         { ADD_LEN( OID_DIGEST_ALG_SHA224 ),    "id-sha224",    "SHA-224" },
         POLARSSL_MD_SHA224,
@@ -557,7 +605,7 @@ FN_OID_GET_ATTR2(oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, m
  * This fuction tries to 'fix' this by at least suggesting enlarging the
  * size by 20.
  */
-static int compat_snprintf(char *str, size_t size, const char *format, ...)
+static int compat_snprintf( char *str, size_t size, const char *format, ... )
 {
     va_list ap;
     int res = -1;
@@ -569,29 +617,27 @@ static int compat_snprintf(char *str, size_t size, const char *format, ...)
     va_end( ap );
 
     // No quick fix possible
-    if ( res < 0 )
+    if( res < 0 )
         return( (int) size + 20 );
 
-    return res;
+    return( res );
 }
 
 #define snprintf compat_snprintf
-#endif
-
-#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
-
-#define SAFE_SNPRINTF()                         \
-{                                               \
-    if( ret == -1 )                             \
-        return( -1 );                           \
-                                                \
-    if ( (unsigned int) ret > n ) {             \
-        p[n - 1] = '\0';                        \
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
-    }                                           \
-                                                \
-    n -= (unsigned int) ret;                    \
-    p += (unsigned int) ret;                    \
+#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
+
+#define SAFE_SNPRINTF()                             \
+{                                                   \
+    if( ret == -1 )                                 \
+        return( POLARSSL_ERR_OID_BUF_TOO_SMALL );   \
+                                                    \
+    if( (unsigned int) ret >= n ) {                 \
+        p[n - 1] = '\0';                            \
+        return( POLARSSL_ERR_OID_BUF_TOO_SMALL );   \
+    }                                               \
+                                                    \
+    n -= (unsigned int) ret;                        \
+    p += (unsigned int) ret;                        \
 }
 
 /* Return the x.y.z.... style numeric string for the given OID */
@@ -617,8 +663,8 @@ int oid_get_numeric_string( char *buf, size_t size,
     for( i = 1; i < oid->len; i++ )
     {
         /* Prevent overflow in value. */
-        if ( ( ( value << 7 ) >> 7 ) != value )
-            return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL );
+        if( ( ( value << 7 ) >> 7 ) != value )
+            return( POLARSSL_ERR_OID_BUF_TOO_SMALL );
 
         value <<= 7;
         value += oid->p[i] & 0x7F;
index a7b4c0c77b85725ac0bf8068db71fd23372afc9c..5d06390cada142f1567f6f3ee55578fcfd632fab 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  VIA PadLock support functions
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  programming_guide.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PADLOCK_C)
 
 int padlock_supports( int feature )
 {
     static int flags = -1;
-    int ebx, edx;
+    int ebx = 0, edx = 0;
 
     if( flags == -1 )
     {
-        asm( "movl  %%ebx, %0           \n"     \
-             "movl  $0xC0000000, %%eax  \n"     \
-             "cpuid                     \n"     \
-             "cmpl  $0xC0000001, %%eax  \n"     \
-             "movl  $0, %%edx           \n"     \
-             "jb    unsupported         \n"     \
-             "movl  $0xC0000001, %%eax  \n"     \
-             "cpuid                     \n"     \
-             "unsupported:              \n"     \
-             "movl  %%edx, %1           \n"     \
-             "movl  %2, %%ebx           \n"
+        asm( "movl  %%ebx, %0           \n\t"
+             "movl  $0xC0000000, %%eax  \n\t"
+             "cpuid                     \n\t"
+             "cmpl  $0xC0000001, %%eax  \n\t"
+             "movl  $0, %%edx           \n\t"
+             "jb    unsupported         \n\t"
+             "movl  $0xC0000001, %%eax  \n\t"
+             "cpuid                     \n\t"
+             "unsupported:              \n\t"
+             "movl  %%edx, %1           \n\t"
+             "movl  %2, %%ebx           \n\t"
              : "=m" (ebx), "=m" (edx)
              :  "m" (ebx)
              : "eax", "ecx", "edx" );
@@ -76,7 +80,7 @@ int padlock_xcryptecb( aes_context *ctx,
                        const unsigned char input[16],
                        unsigned char output[16] )
 {
-    int ebx;
+    int ebx = 0;
     uint32_t *rk;
     uint32_t *blk;
     uint32_t *ctrl;
@@ -89,15 +93,16 @@ int padlock_xcryptecb( aes_context *ctx,
      ctrl = blk + 4;
     *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
 
-    asm( "pushfl; popfl         \n"     \
-         "movl    %%ebx, %0     \n"     \
-         "movl    $1, %%ecx     \n"     \
-         "movl    %2, %%edx     \n"     \
-         "movl    %3, %%ebx     \n"     \
-         "movl    %4, %%esi     \n"     \
-         "movl    %4, %%edi     \n"     \
-         ".byte  0xf3,0x0f,0xa7,0xc8\n" \
-         "movl    %1, %%ebx     \n"
+    asm( "pushfl                        \n\t"
+         "popfl                         \n\t"
+         "movl    %%ebx, %0             \n\t"
+         "movl    $1, %%ecx             \n\t"
+         "movl    %2, %%edx             \n\t"
+         "movl    %3, %%ebx             \n\t"
+         "movl    %4, %%esi             \n\t"
+         "movl    %4, %%edi             \n\t"
+         ".byte  0xf3,0x0f,0xa7,0xc8    \n\t"
+         "movl    %1, %%ebx             \n\t"
          : "=m" (ebx)
          :  "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
          : "ecx", "edx", "esi", "edi" );
@@ -117,7 +122,7 @@ int padlock_xcryptcbc( aes_context *ctx,
                        const unsigned char *input,
                        unsigned char *output )
 {
-    int ebx;
+    int ebx = 0;
     size_t count;
     uint32_t *rk;
     uint32_t *iw;
@@ -133,20 +138,21 @@ int padlock_xcryptcbc( aes_context *ctx,
     memcpy( iw, iv, 16 );
 
      ctrl = iw + 4;
-    *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + (mode^1) - 10 ) << 9 );
-
-    count = (length + 15) >> 4;
-
-    asm( "pushfl; popfl         \n"     \
-         "movl    %%ebx, %0     \n"     \
-         "movl    %2, %%ecx     \n"     \
-         "movl    %3, %%edx     \n"     \
-         "movl    %4, %%ebx     \n"     \
-         "movl    %5, %%esi     \n"     \
-         "movl    %6, %%edi     \n"     \
-         "movl    %7, %%eax     \n"     \
-         ".byte  0xf3,0x0f,0xa7,0xd0\n" \
-         "movl    %1, %%ebx     \n"
+    *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 );
+
+    count = ( length + 15 ) >> 4;
+
+    asm( "pushfl                        \n\t"
+         "popfl                         \n\t"
+         "movl    %%ebx, %0             \n\t"
+         "movl    %2, %%ecx             \n\t"
+         "movl    %3, %%edx             \n\t"
+         "movl    %4, %%ebx             \n\t"
+         "movl    %5, %%esi             \n\t"
+         "movl    %6, %%edi             \n\t"
+         "movl    %7, %%eax             \n\t"
+         ".byte  0xf3,0x0f,0xa7,0xd0    \n\t"
+         "movl    %1, %%ebx             \n\t"
          : "=m" (ebx)
          :  "m" (ebx), "m" (count), "m" (ctrl),
             "m"  (rk), "m" (input), "m" (output), "m" (iw)
@@ -157,6 +163,6 @@ int padlock_xcryptcbc( aes_context *ctx,
     return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_HAVE_X86 */
 
-#endif
+#endif /* POLARSSL_PADLOCK_C */
index 09e56dfa3ce0c22222c8955afaaa5dc94e50ce83..e76f066421645f0db4fd5735dae862a4e5f32e0e 100644 (file)
@@ -6,7 +6,7 @@
  *
  * \author Mathias Olsson <mathias@kompetensum.com>
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  * http://tools.ietf.org/html/rfc6070 (Test vectors)
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PBKDF2_C)
 
index d602d8aa25899dd992bb1050579f928412a1fa8c..485d829c08317db81887949570988ac20d444c58 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Privacy Enhanced Mail (PEM) decoding
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
 #include "polarssl/pem.h"
@@ -33,8 +37,8 @@
 #include "polarssl/md5.h"
 #include "polarssl/cipher.h"
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 
 #include <stdlib.h>
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if defined(POLARSSL_PEM_PARSE_C)
 void pem_init( pem_context *ctx )
 {
@@ -53,7 +62,8 @@ void pem_init( pem_context *ctx )
 /*
  * Read a 16-byte hex string and convert it to binary
  */
-static int pem_get_iv( const unsigned char *s, unsigned char *iv, size_t iv_len )
+static int pem_get_iv( const unsigned char *s, unsigned char *iv,
+                       size_t iv_len )
 {
     size_t i, j, k;
 
@@ -82,6 +92,8 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen,
     unsigned char md5sum[16];
     size_t use_len;
 
+    md5_init( &md5_ctx );
+
     /*
      * key[ 0..15] = MD5(pwd || IV)
      */
@@ -94,8 +106,8 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen,
     {
         memcpy( key, md5sum, keylen );
 
-        memset( &md5_ctx, 0, sizeof(  md5_ctx ) );
-        memset( md5sum, 0, 16 );
+        md5_free( &md5_ctx );
+        polarssl_zeroize( md5sum, 16 );
         return;
     }
 
@@ -116,8 +128,8 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen,
 
     memcpy( key + 16, md5sum, use_len );
 
-    memset( &md5_ctx, 0, sizeof(  md5_ctx ) );
-    memset( md5sum, 0, 16 );
+    md5_free( &md5_ctx );
+    polarssl_zeroize( md5sum, 16 );
 }
 
 #if defined(POLARSSL_DES_C)
@@ -131,14 +143,16 @@ static void pem_des_decrypt( unsigned char des_iv[8],
     des_context des_ctx;
     unsigned char des_key[8];
 
+    des_init( &des_ctx );
+
     pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
 
     des_setkey_dec( &des_ctx, des_key );
     des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen,
                      des_iv, buf, buf );
 
-    memset( &des_ctx, 0, sizeof( des_ctx ) );
-    memset( des_key, 0, 8 );
+    des_free( &des_ctx );
+    polarssl_zeroize( des_key, 8 );
 }
 
 /*
@@ -151,14 +165,16 @@ static void pem_des3_decrypt( unsigned char des3_iv[8],
     des3_context des3_ctx;
     unsigned char des3_key[24];
 
+    des3_init( &des3_ctx );
+
     pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
 
     des3_set3key_dec( &des3_ctx, des3_key );
     des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
                      des3_iv, buf, buf );
 
-    memset( &des3_ctx, 0, sizeof( des3_ctx ) );
-    memset( des3_key, 0, 24 );
+    des3_free( &des3_ctx );
+    polarssl_zeroize( des3_key, 24 );
 }
 #endif /* POLARSSL_DES_C */
 
@@ -173,14 +189,16 @@ static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
     aes_context aes_ctx;
     unsigned char aes_key[32];
 
+    aes_init( &aes_ctx );
+
     pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
 
     aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
     aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen,
                      aes_iv, buf, buf );
 
-    memset( &aes_ctx, 0, sizeof( aes_ctx ) );
-    memset( aes_key, 0, keylen );
+    aes_free( &aes_ctx );
+    polarssl_zeroize( aes_key, keylen );
 }
 #endif /* POLARSSL_AES_C */
 
@@ -365,13 +383,10 @@ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer,
 
 void pem_free( pem_context *ctx )
 {
-    if( ctx->buf )
-        polarssl_free( ctx->buf );
-
-    if( ctx->info )
-        polarssl_free( ctx->info );
+    polarssl_free( ctx->buf );
+    polarssl_free( ctx->info );
 
-    memset( ctx, 0, sizeof( pem_context ) );
+    polarssl_zeroize( ctx, sizeof( pem_context ) );
 }
 #endif /* POLARSSL_PEM_PARSE_C */
 
@@ -382,10 +397,11 @@ int pem_write_buffer( const char *header, const char *footer,
 {
     int ret;
     unsigned char *encode_buf, *c, *p = buf;
-    size_t len = 0, use_len = 0;
-    size_t add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
+    size_t len = 0, use_len = 0, add_len = 0;
 
     base64_encode( NULL, &use_len, der_data, der_len );
+    add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
+
     if( use_len + add_len > buf_len )
     {
         *olen = use_len + add_len;
index 80eccc911b107c48643e28e37d76031b414962f5..11faf3c8d96622317fd2a7b3d0fcdb84a15ba67e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Public Key abstraction layer
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PK_C)
 
 #include "polarssl/ecdsa.h"
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * Initialise a pk_context
  */
@@ -57,13 +66,12 @@ void pk_init( pk_context *ctx )
  */
 void pk_free( pk_context *ctx )
 {
-    if( ctx == NULL || ctx->pk_info == NULL)
+    if( ctx == NULL || ctx->pk_info == NULL )
         return;
 
     ctx->pk_info->ctx_free_func( ctx->pk_ctx );
-    ctx->pk_ctx = NULL;
 
-    ctx->pk_info = NULL;
+    polarssl_zeroize( ctx, sizeof( pk_context ) );
 }
 
 /*
@@ -74,21 +82,21 @@ const pk_info_t * pk_info_from_type( pk_type_t pk_type )
     switch( pk_type ) {
 #if defined(POLARSSL_RSA_C)
         case POLARSSL_PK_RSA:
-            return &rsa_info;
+            return( &rsa_info );
 #endif
 #if defined(POLARSSL_ECP_C)
         case POLARSSL_PK_ECKEY:
-            return &eckey_info;
+            return( &eckey_info );
         case POLARSSL_PK_ECKEY_DH:
-            return &eckeydh_info;
+            return( &eckeydh_info );
 #endif
 #if defined(POLARSSL_ECDSA_C)
         case POLARSSL_PK_ECDSA:
-            return &ecdsa_info;
+            return( &ecdsa_info );
 #endif
-        /* POLARSSL_PK_RSA_ALT ommited on purpose */
+        /* POLARSSL_PK_RSA_ALT omitted on purpose */
         default:
-            return NULL;
+            return( NULL );
     }
 }
 
@@ -184,6 +192,59 @@ int pk_verify( pk_context *ctx, md_type_t md_alg,
                                        sig, sig_len ) );
 }
 
+/*
+ * Verify a signature with options
+ */
+int pk_verify_ext( pk_type_t type, const void *options,
+                   pk_context *ctx, md_type_t md_alg,
+                   const unsigned char *hash, size_t hash_len,
+                   const unsigned char *sig, size_t sig_len )
+{
+    if( ctx == NULL || ctx->pk_info == NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    if( ! pk_can_do( ctx, type ) )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
+    if( type == POLARSSL_PK_RSASSA_PSS )
+    {
+#if defined(POLARSSL_RSA_C) && defined(POLARSSL_PKCS1_V21)
+        int ret;
+        const pk_rsassa_pss_options *pss_opts;
+
+        if( options == NULL )
+            return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+        pss_opts = (const pk_rsassa_pss_options *) options;
+
+        if( sig_len < pk_get_len( ctx ) )
+            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+        ret = rsa_rsassa_pss_verify_ext( pk_rsa( *ctx ),
+                NULL, NULL, RSA_PUBLIC,
+                md_alg, hash_len, hash,
+                pss_opts->mgf1_hash_id,
+                pss_opts->expected_salt_len,
+                sig );
+        if( ret != 0 )
+            return( ret );
+
+        if( sig_len > pk_get_len( ctx ) )
+            return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH );
+
+        return( 0 );
+#else
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+#endif
+    }
+
+    /* General case: no options */
+    if( options != NULL )
+        return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
+
+    return( pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
+}
+
 /*
  * Make a signature
  */
@@ -258,6 +319,9 @@ int pk_debug( const pk_context *ctx, pk_debug_item *items )
     if( ctx == NULL || ctx->pk_info == NULL )
         return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
 
+    if( ctx->pk_info->debug_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
     ctx->pk_info->debug_func( ctx->pk_ctx, items );
     return( 0 );
 }
index 6f22b095fff9cb664866a9280a0ecd4f3bf8094e..5e9ff605eeb40220baa82268f2f883d6304b018b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Public Key abstraction layer: wrapper functions
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PK_C)
 
 #include "polarssl/ecdsa.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #include <stdlib.h>
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #endif
 
-/* Used by RSA-alt too */
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#if defined(POLARSSL_RSA_C)
 static int rsa_can_do( pk_type_t type )
 {
-    return( type == POLARSSL_PK_RSA );
+    return( type == POLARSSL_PK_RSA ||
+            type == POLARSSL_PK_RSASSA_PSS );
 }
 
-#if defined(POLARSSL_RSA_C)
 static size_t rsa_get_size( const void *ctx )
 {
-    return( 8 * ((rsa_context *) ctx)->len );
+    return( 8 * ((const rsa_context *) ctx)->len );
 }
 
 static int rsa_verify_wrap( void *ctx, md_type_t md_alg,
                    const unsigned char *hash, size_t hash_len,
                    const unsigned char *sig, size_t sig_len )
 {
-    if( sig_len != ((rsa_context *) ctx)->len )
+    int ret;
+
+    if( sig_len < ((rsa_context *) ctx)->len )
         return( POLARSSL_ERR_RSA_VERIFY_FAILED );
 
-    return( rsa_pkcs1_verify( (rsa_context *) ctx, NULL, NULL,
-                RSA_PUBLIC, md_alg, (unsigned int) hash_len, hash, sig ) );
+    if( ( ret = rsa_pkcs1_verify( (rsa_context *) ctx, NULL, NULL,
+                                  RSA_PUBLIC, md_alg,
+                                  (unsigned int) hash_len, hash, sig ) ) != 0 )
+        return( ret );
+
+    if( sig_len > ((rsa_context *) ctx)->len )
+        return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH );
+
+    return( 0 );
 }
 
 static int rsa_sign_wrap( void *ctx, md_type_t md_alg,
@@ -114,7 +132,7 @@ static void *rsa_alloc_wrap( void )
     if( ctx != NULL )
         rsa_init( (rsa_context *) ctx, 0, 0 );
 
-    return ctx;
+    return( ctx );
 }
 
 static void rsa_free_wrap( void *ctx )
@@ -259,7 +277,7 @@ const pk_info_t eckey_info = {
 };
 
 /*
- * EC key resticted to ECDH
+ * EC key restricted to ECDH
  */
 static int eckeydh_can_do( pk_type_t type )
 {
@@ -292,10 +310,16 @@ static int ecdsa_verify_wrap( void *ctx, md_type_t md_alg,
                        const unsigned char *hash, size_t hash_len,
                        const unsigned char *sig, size_t sig_len )
 {
+    int ret;
     ((void) md_alg);
 
-    return( ecdsa_read_signature( (ecdsa_context *) ctx,
-                hash, hash_len, sig, sig_len ) );
+    ret = ecdsa_read_signature( (ecdsa_context *) ctx,
+                                hash, hash_len, sig, sig_len );
+
+    if( ret == POLARSSL_ERR_ECP_SIG_LEN_MISMATCH )
+        return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH );
+
+    return( ret );
 }
 
 static int ecdsa_sign_wrap( void *ctx, md_type_t md_alg,
@@ -303,10 +327,19 @@ static int ecdsa_sign_wrap( void *ctx, md_type_t md_alg,
                    unsigned char *sig, size_t *sig_len,
                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
+    /* Use deterministic ECDSA by default if available */
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+    ((void) f_rng);
+    ((void) p_rng);
+
+    return( ecdsa_write_signature_det( (ecdsa_context *) ctx,
+                hash, hash_len, sig, sig_len, md_alg ) );
+#else
     ((void) md_alg);
 
     return( ecdsa_write_signature( (ecdsa_context *) ctx,
                 hash, hash_len, sig, sig_len, f_rng, p_rng ) );
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
 }
 
 static void *ecdsa_alloc_wrap( void )
@@ -344,11 +377,16 @@ const pk_info_t ecdsa_info = {
  * Support for alternative RSA-private implementations
  */
 
+static int rsa_alt_can_do( pk_type_t type )
+{
+    return( type == POLARSSL_PK_RSA );
+}
+
 static size_t rsa_alt_get_size( const void *ctx )
 {
-    rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx;
+    const rsa_alt_context *rsa_alt = (const rsa_alt_context *) ctx;
 
-    return( rsa_alt->key_len_func( rsa_alt->key ) );
+    return( 8 * rsa_alt->key_len_func( rsa_alt->key ) );
 }
 
 static int rsa_alt_sign_wrap( void *ctx, md_type_t md_alg,
@@ -388,11 +426,12 @@ static void *rsa_alt_alloc_wrap( void )
     if( ctx != NULL )
         memset( ctx, 0, sizeof( rsa_alt_context ) );
 
-    return ctx;
+    return( ctx );
 }
 
 static void rsa_alt_free_wrap( void *ctx )
 {
+    polarssl_zeroize( ctx, sizeof( rsa_alt_context ) );
     polarssl_free( ctx );
 }
 
@@ -400,7 +439,7 @@ const pk_info_t rsa_alt_info = {
     POLARSSL_PK_RSA_ALT,
     "RSA-alt",
     rsa_alt_get_size,
-    rsa_can_do,
+    rsa_alt_can_do,
     NULL,
     rsa_alt_sign_wrap,
     rsa_alt_decrypt_wrap,
index 9f68d782a369fb4e76d656b3dc28f2db722afca5..64e7ce37950eaf739edfecf6730322244da9fb51 100644 (file)
@@ -5,7 +5,7 @@
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 #include "polarssl/pkcs11.h"
 
 #if defined(POLARSSL_PKCS11_C)
+#include "polarssl/md.h"
+#include "polarssl/oid.h"
+#include "polarssl/x509_crt.h"
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
+#include <stdlib.h>
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #endif
 
-#include <stdlib.h>
-
 int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11_cert )
 {
     int ret = 1;
@@ -52,7 +54,8 @@ int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11_cert )
         goto cleanup;
     }
 
-    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, &cert_blob_size ) != CKR_OK )
+    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL,
+                                                &cert_blob_size ) != CKR_OK )
     {
         ret = 3;
         goto cleanup;
@@ -65,13 +68,14 @@ int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11_cert )
         goto cleanup;
     }
 
-    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, &cert_blob_size ) != CKR_OK )
+    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob,
+                                                &cert_blob_size ) != CKR_OK )
     {
         ret = 5;
         goto cleanup;
     }
 
-    if( 0 != x509_crt_parse(cert, cert_blob, cert_blob_size ) )
+    if( 0 != x509_crt_parse( cert, cert_blob, cert_blob_size ) )
     {
         ret = 6;
         goto cleanup;
@@ -83,7 +87,7 @@ cleanup:
     if( NULL != cert_blob )
         polarssl_free( cert_blob );
 
-    return ret;
+    return( ret );
 }
 
 
@@ -101,7 +105,7 @@ int pkcs11_priv_key_init( pkcs11_context *priv_key,
     if( 0 != pkcs11_x509_cert_init( &cert, pkcs11_cert ) )
         goto cleanup;
 
-    priv_key->len = cert.rsa.len;
+    priv_key->len = pk_get_len( &cert.pk );
     priv_key->pkcs11h_cert = pkcs11_cert;
 
     ret = 0;
@@ -109,7 +113,7 @@ int pkcs11_priv_key_init( pkcs11_context *priv_key,
 cleanup:
     x509_crt_free( &cert );
 
-    return ret;
+    return( ret );
 }
 
 void pkcs11_priv_key_free( pkcs11_context *priv_key )
@@ -129,7 +133,7 @@ int pkcs11_decrypt( pkcs11_context *ctx,
     if( NULL == ctx )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
-    if( RSA_PUBLIC == mode )
+    if( RSA_PRIVATE != mode )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     output_len = input_len = ctx->len;
@@ -158,83 +162,70 @@ int pkcs11_decrypt( pkcs11_context *ctx,
 
 int pkcs11_sign( pkcs11_context *ctx,
                     int mode,
-                    int hash_id,
+                    md_type_t md_alg,
                     unsigned int hashlen,
                     const unsigned char *hash,
                     unsigned char *sig )
 {
-    size_t olen, asn_len;
+    size_t sig_len = 0, asn_len = 0, oid_size = 0;
     unsigned char *p = sig;
+    const char *oid;
 
     if( NULL == ctx )
-        return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
-
-    if( RSA_PUBLIC == mode )
-        return POLARSSL_ERR_RSA_BAD_INPUT_DATA;
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
-    olen = ctx->len;
+    if( RSA_PRIVATE != mode )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
-    switch( hash_id )
+    if( md_alg != POLARSSL_MD_NONE )
     {
-        case SIG_RSA_RAW:
-            asn_len = 0;
-            memcpy( p, hash, hashlen );
-            break;
-
-        case SIG_RSA_MD2:
-            asn_len = OID_SIZE(ASN1_HASH_MDX);
-            memcpy( p, ASN1_HASH_MDX, asn_len );
-            memcpy( p + asn_len, hash, hashlen );
-            p[13] = 2; break;
-
-        case SIG_RSA_MD4:
-            asn_len = OID_SIZE(ASN1_HASH_MDX);
-            memcpy( p, ASN1_HASH_MDX, asn_len );
-            memcpy( p + asn_len, hash, hashlen );
-            p[13] = 4; break;
-
-        case SIG_RSA_MD5:
-            asn_len = OID_SIZE(ASN1_HASH_MDX);
-            memcpy( p, ASN1_HASH_MDX, asn_len );
-            memcpy( p + asn_len, hash, hashlen );
-            p[13] = 5; break;
-
-        case SIG_RSA_SHA1:
-            asn_len = OID_SIZE(ASN1_HASH_SHA1);
-            memcpy( p, ASN1_HASH_SHA1, asn_len );
-            memcpy( p + 15, hash, hashlen );
-            break;
-
-        case SIG_RSA_SHA224:
-            asn_len = OID_SIZE(ASN1_HASH_SHA2X);
-            memcpy( p, ASN1_HASH_SHA2X, asn_len );
-            memcpy( p + asn_len, hash, hashlen );
-            p[1] += hashlen; p[14] = 4; p[18] += hashlen; break;
-
-        case SIG_RSA_SHA256:
-            asn_len = OID_SIZE(ASN1_HASH_SHA2X);
-            memcpy( p, ASN1_HASH_SHA2X, asn_len );
-            memcpy( p + asn_len, hash, hashlen );
-            p[1] += hashlen; p[14] = 1; p[18] += hashlen; break;
-
-        case SIG_RSA_SHA384:
-            asn_len = OID_SIZE(ASN1_HASH_SHA2X);
-            memcpy( p, ASN1_HASH_SHA2X, asn_len );
-            memcpy( p + asn_len, hash, hashlen );
-            p[1] += hashlen; p[14] = 2; p[18] += hashlen; break;
-
-        case SIG_RSA_SHA512:
-            asn_len = OID_SIZE(ASN1_HASH_SHA2X);
-            memcpy( p, ASN1_HASH_SHA2X, asn_len );
-            memcpy( p + asn_len, hash, hashlen );
-            p[1] += hashlen; p[14] = 3; p[18] += hashlen; break;
-
-        default:
+        const md_info_t *md_info = md_info_from_type( md_alg );
+        if( md_info == NULL )
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+        if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
             return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+        hashlen = md_get_size( md_info );
+        asn_len = 10 + oid_size;
     }
 
+    sig_len = ctx->len;
+    if( hashlen > sig_len || asn_len > sig_len ||
+        hashlen + asn_len > sig_len )
+    {
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    if( md_alg != POLARSSL_MD_NONE )
+    {
+        /*
+         * DigestInfo ::= SEQUENCE {
+         *   digestAlgorithm DigestAlgorithmIdentifier,
+         *   digest Digest }
+         *
+         * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+         *
+         * Digest ::= OCTET STRING
+         */
+        *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED;
+        *p++ = (unsigned char) ( 0x08 + oid_size + hashlen );
+        *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED;
+        *p++ = (unsigned char) ( 0x04 + oid_size );
+        *p++ = ASN1_OID;
+        *p++ = oid_size & 0xFF;
+        memcpy( p, oid, oid_size );
+        p += oid_size;
+        *p++ = ASN1_NULL;
+        *p++ = 0x00;
+        *p++ = ASN1_OCTET_STRING;
+        *p++ = hashlen;
+    }
+
+    memcpy( p, hash, hashlen );
+
     if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
-            asn_len + hashlen, sig, &olen ) != CKR_OK )
+            asn_len + hashlen, sig, &sig_len ) != CKR_OK )
     {
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
     }
index 16821b03bed20a40cff64a75904b7b31fccd02cc..0cf2edf1029841f9fdaf7c42c36582887818c510 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  PKCS#12 Personal Information Exchange Syntax
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PKCS12_C)
 
 #include "polarssl/des.h"
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 static int pkcs12_parse_pbe_params( asn1_buf *params,
                                     asn1_buf *salt, int *iterations )
 {
@@ -89,13 +98,14 @@ static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
     size_t i;
     unsigned char unipwd[258];
 
-    memset(&salt, 0, sizeof(asn1_buf));
-    memset(&unipwd, 0, sizeof(unipwd));
+    memset( &salt, 0, sizeof(asn1_buf) );
+    memset( &unipwd, 0, sizeof(unipwd) );
 
-    if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, &iterations ) ) != 0 )
+    if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt,
+                                         &iterations ) ) != 0 )
         return( ret );
 
-    for(i = 0; i < pwdlen; i++)
+    for( i = 0; i < pwdlen; i++ )
         unipwd[i * 2 + 1] = pwd[i];
 
     if( ( ret = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
@@ -137,6 +147,8 @@ int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
     arc4_context ctx;
     ((void) mode);
 
+    arc4_init( &ctx );
+
     if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1,
                                           pwd, pwdlen,
                                           key, 16, NULL, 0 ) ) != 0 )
@@ -146,9 +158,13 @@ int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
 
     arc4_setup( &ctx, key, 16 );
     if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 )
-        return( ret );
+        goto exit;
 
-    return( 0 );
+exit:
+    polarssl_zeroize( key, sizeof( key ) );
+    arc4_free( &ctx );
+
+    return( ret );
 #endif /* POLARSSL_ARC4_C */
 }
 
@@ -178,6 +194,8 @@ int pkcs12_pbe( asn1_buf *pbe_params, int mode,
         return( ret );
     }
 
+    cipher_init( &cipher_ctx );
+
     if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
         goto exit;
 
@@ -200,7 +218,9 @@ int pkcs12_pbe( asn1_buf *pbe_params, int mode,
         ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH;
 
 exit:
-    cipher_free_ctx( &cipher_ctx );
+    polarssl_zeroize( key, sizeof( key ) );
+    polarssl_zeroize( iv,  sizeof( iv  ) );
+    cipher_free( &cipher_ctx );
 
     return( ret );
 }
@@ -247,7 +267,9 @@ int pkcs12_derivation( unsigned char *data, size_t datalen,
     if( md_info == NULL )
         return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
 
-    if ( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
+    md_init( &md_ctx );
+
+    if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
         return( ret );
     hlen = md_get_size( md_info );
 
@@ -325,7 +347,12 @@ int pkcs12_derivation( unsigned char *data, size_t datalen,
     ret = 0;
 
 exit:
-    md_free_ctx( &md_ctx );
+    polarssl_zeroize( salt_block, sizeof( salt_block ) );
+    polarssl_zeroize( pwd_block, sizeof( pwd_block ) );
+    polarssl_zeroize( hash_block, sizeof( hash_block ) );
+    polarssl_zeroize( hash_output, sizeof( hash_output ) );
+
+    md_free( &md_ctx );
 
     return( ret );
 }
index 39aa5b96e6303aefc008d87e52e285ee6ca1d068..e769783eef44e513f2e71fbb8db99772a77a8525 100644 (file)
@@ -5,7 +5,7 @@
  *
  * \author Mathias Olsson <mathias@kompetensum.com>
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  * http://tools.ietf.org/html/rfc6070 (Test vectors)
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PKCS5_C)
 
 #include "polarssl/cipher.h"
 #include "polarssl/oid.h"
 
-static int pkcs5_parse_pbkdf2_params( asn1_buf *params,
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+static int pkcs5_parse_pbkdf2_params( const asn1_buf *params,
                                       asn1_buf *salt, int *iterations,
                                       int *keylen, md_type_t *md_type )
 {
     int ret;
     asn1_buf prf_alg_oid;
-    unsigned char **p = &params->p;
+    unsigned char *p = params->p;
     const unsigned char *end = params->p + params->len;
 
     if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
@@ -63,28 +73,28 @@ static int pkcs5_parse_pbkdf2_params( asn1_buf *params,
      *  }
      *
      */
-    if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
+    if( ( ret = asn1_get_tag( &p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
         return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
 
-    salt->p = *p;
-    *p += salt->len;
+    salt->p = p;
+    p += salt->len;
 
-    if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 )
+    if( ( ret = asn1_get_int( &p, end, iterations ) ) != 0 )
         return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
 
-    if( *p == end )
+    if( p == end )
         return( 0 );
 
-    if( ( ret = asn1_get_int( p, end, keylen ) ) != 0 )
+    if( ( ret = asn1_get_int( &p, end, keylen ) ) != 0 )
     {
         if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
             return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
     }
 
-    if( *p == end )
+    if( p == end )
         return( 0 );
 
-    if( ( ret = asn1_get_alg_null( p, end, &prf_alg_oid ) ) != 0 )
+    if( ( ret = asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
         return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
 
     if( !OID_CMP( OID_HMAC_SHA1, &prf_alg_oid ) )
@@ -92,7 +102,7 @@ static int pkcs5_parse_pbkdf2_params( asn1_buf *params,
 
     *md_type = POLARSSL_MD_SHA1;
 
-    if( *p != end )
+    if( p != end )
         return( POLARSSL_ERR_PKCS5_INVALID_FORMAT +
                 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
 
@@ -120,9 +130,6 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode,
     p = pbe_params->p;
     end = p + pbe_params->len;
 
-    memset( &md_ctx, 0, sizeof(md_context_t) );
-    memset( &cipher_ctx, 0, sizeof(cipher_context_t) );
-
     /*
      *  PBES2-params ::= SEQUENCE {
      *    keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
@@ -152,16 +159,23 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode,
     if( md_info == NULL )
         return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
-    if( ( ret = asn1_get_alg( &p, end, &enc_scheme_oid, &enc_scheme_params ) ) != 0 )
+    if( ( ret = asn1_get_alg( &p, end, &enc_scheme_oid,
+                              &enc_scheme_params ) ) != 0 )
+    {
         return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret );
+    }
 
-    if ( oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
+    if( oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
         return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
     cipher_info = cipher_info_from_type( cipher_alg );
     if( cipher_info == NULL )
         return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
+    /*
+     * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
+     * since it is optional and we don't know if it was set or not
+     */
     keylen = cipher_info->key_length / 8;
 
     if( enc_scheme_params.tag != ASN1_OCTET_STRING ||
@@ -170,13 +184,16 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode,
         return( POLARSSL_ERR_PKCS5_INVALID_FORMAT );
     }
 
+    md_init( &md_ctx );
+    cipher_init( &cipher_ctx );
+
     memcpy( iv, enc_scheme_params.p, enc_scheme_params.len );
 
     if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
         goto exit;
 
-    if ( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
-                                    iterations, keylen, key ) ) != 0 )
+    if( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
+                                   iterations, keylen, key ) ) != 0 )
     {
         goto exit;
     }
@@ -187,24 +204,13 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode,
     if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, mode ) ) != 0 )
         goto exit;
 
-    if( ( ret = cipher_set_iv( &cipher_ctx, iv, enc_scheme_params.len ) ) != 0 )
-        goto exit;
-
-    if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 )
-        goto exit;
-
-    if( ( ret = cipher_update( &cipher_ctx, data, datalen,
-                                output, &olen ) ) != 0 )
-    {
-        goto exit;
-    }
-
-    if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+    if( ( ret = cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
+                              data, datalen, output, &olen ) ) != 0 )
         ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH;
 
 exit:
-    md_free_ctx( &md_ctx );
-    cipher_free_ctx( &cipher_ctx );
+    md_free( &md_ctx );
+    cipher_free( &cipher_ctx );
 
     return( ret );
 }
@@ -247,7 +253,7 @@ int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password,
 
         memcpy( md1, work, md_size );
 
-        for ( i = 1; i < iteration_count; i++ )
+        for( i = 1; i < iteration_count; i++ )
         {
             // U2 ends up in md1
             //
@@ -282,6 +288,16 @@ int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password,
 
 #if defined(POLARSSL_SELF_TEST)
 
+#if !defined(POLARSSL_SHA1_C)
+int pkcs5_self_test( int verbose )
+{
+    if( verbose != 0 )
+        polarssl_printf( "  PBKDF2 (SHA1): skipped\n\n" );
+
+    return( 0 );
+}
+#else
+
 #include <stdio.h>
 
 #define MAX_TESTS   6
@@ -319,7 +335,7 @@ uint32_t key_len[MAX_TESTS] =
     { 20, 20, 20, 20, 25, 16 };
 
 
-unsigned char result_key[MAX_TESTS][32] = 
+unsigned char result_key[MAX_TESTS][32] =
 {
     { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
       0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
@@ -348,16 +364,28 @@ int pkcs5_self_test( int verbose )
     int ret, i;
     unsigned char key[64];
 
+    md_init( &sha1_ctx );
+
     info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 );
     if( info_sha1 == NULL )
-        return( 1 );
+    {
+        ret = 1;
+        goto exit;
+    }
 
     if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 )
-        return( 1 );
+    {
+        ret = 1;
+        goto exit;
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "  PBKDF2 note: test #3 may be slow!\n" );
 
     for( i = 0; i < MAX_TESTS; i++ )
     {
-        printf( "  PBKDF2 (SHA1) #%d: ", i );
+        if( verbose != 0 )
+            polarssl_printf( "  PBKDF2 (SHA1) #%d: ", i );
 
         ret = pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
                                   slen[i], it_cnt[i], key_len[i], key );
@@ -365,22 +393,24 @@ int pkcs5_self_test( int verbose )
             memcmp( result_key[i], key, key_len[i] ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
-    printf( "\n" );
+    polarssl_printf( "\n" );
 
-    if( ( ret = md_free_ctx( &sha1_ctx ) ) != 0 )
-        return( 1 );
+exit:
+    md_free( &sha1_ctx );
 
     return( 0 );
 }
+#endif /* POLARSSL_SHA1_C */
 
 #endif /* POLARSSL_SELF_TEST */
 
index a5de20b9f5783d7f04e7e121fa3767beaa980658..29217a28a2d79d5205cc6b56dc5f73ea7855c1a2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Public Key layer for parsing key files and structures
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PK_PARSE_C)
 
@@ -50,8 +54,8 @@
 #include "polarssl/pkcs12.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #include <stdlib.h>
 #define polarssl_malloc     malloc
 #endif
 
 #if defined(POLARSSL_FS_IO)
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * Load all data from a file into a given buffer.
  */
@@ -111,7 +120,7 @@ int pk_parse_keyfile( pk_context *ctx,
     size_t n;
     unsigned char *buf;
 
-    if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+    if( ( ret = load_file( path, &buf, &n ) ) != 0 )
         return( ret );
 
     if( pwd == NULL )
@@ -120,7 +129,7 @@ int pk_parse_keyfile( pk_context *ctx,
         ret = pk_parse_key( ctx, buf, n,
                 (const unsigned char *) pwd, strlen( pwd ) );
 
-    memset( buf, 0, n + 1 );
+    polarssl_zeroize( buf, n + 1 );
     polarssl_free( buf );
 
     return( ret );
@@ -135,12 +144,12 @@ int pk_parse_public_keyfile( pk_context *ctx, const char *path )
     size_t n;
     unsigned char *buf;
 
-    if ( (ret = load_file( path, &buf, &n ) ) != 0 )
+    if( ( ret = load_file( path, &buf, &n ) ) != 0 )
         return( ret );
 
     ret = pk_parse_public_key( ctx, buf, n );
 
-    memset( buf, 0, n + 1 );
+    polarssl_zeroize( buf, n + 1 );
     polarssl_free( buf );
 
     return( ret );
@@ -148,12 +157,12 @@ int pk_parse_public_keyfile( pk_context *ctx, const char *path )
 #endif /* POLARSSL_FS_IO */
 
 #if defined(POLARSSL_ECP_C)
-/* Get an EC group id from an ECParameters buffer
+/* Minimally parse an ECParameters buffer to and asn1_buf
  *
  * ECParameters ::= CHOICE {
  *   namedCurve         OBJECT IDENTIFIER
+ *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
  *   -- implicitCurve   NULL
- *   -- specifiedCurve  SpecifiedECDomain
  * }
  */
 static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
@@ -161,10 +170,22 @@ static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
 {
     int ret;
 
+    /* Tag may be either OID or SEQUENCE */
     params->tag = **p;
+    if( params->tag != ASN1_OID
+#if defined(POLARSSL_PK_PARSE_EC_EXTENDED)
+            && params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE )
+#endif
+            )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+    }
 
-    if( ( ret = asn1_get_tag( p, end, &params->len, ASN1_OID ) ) != 0 )
+    if( ( ret = asn1_get_tag( p, end, &params->len, params->tag ) ) != 0 )
+    {
         return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
 
     params->p = *p;
     *p += params->len;
@@ -176,16 +197,262 @@ static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
     return( 0 );
 }
 
+#if defined(POLARSSL_PK_PARSE_EC_EXTENDED)
+/*
+ * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
+ * WARNING: the resulting group should only be used with
+ * pk_group_id_from_specified(), since its base point may not be set correctly
+ * if it was encoded compressed.
+ *
+ *  SpecifiedECDomain ::= SEQUENCE {
+ *      version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
+ *      fieldID FieldID {{FieldTypes}},
+ *      curve Curve,
+ *      base ECPoint,
+ *      order INTEGER,
+ *      cofactor INTEGER OPTIONAL,
+ *      hash HashAlgorithm OPTIONAL,
+ *      ...
+ *  }
+ *
+ * We only support prime-field as field type, and ignore hash and cofactor.
+ */
+static int pk_group_from_specified( const asn1_buf *params, ecp_group *grp )
+{
+    int ret;
+    unsigned char *p = params->p;
+    const unsigned char * const end = params->p + params->len;
+    const unsigned char *end_field, *end_curve;
+    size_t len;
+    int ver;
+
+    /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
+    if( ( ret = asn1_get_int( &p, end, &ver ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ver < 1 || ver > 3 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+
+    /*
+     * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
+     *       fieldType FIELD-ID.&id({IOSet}),
+     *       parameters FIELD-ID.&Type({IOSet}{@fieldType})
+     * }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( ret );
+
+    end_field = p + len;
+
+    /*
+     * FIELD-ID ::= TYPE-IDENTIFIER
+     * FieldTypes FIELD-ID ::= {
+     *       { Prime-p IDENTIFIED BY prime-field } |
+     *       { Characteristic-two IDENTIFIED BY characteristic-two-field }
+     * }
+     * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
+     */
+    if( ( ret = asn1_get_tag( &p, end_field, &len, ASN1_OID ) ) != 0 )
+        return( ret );
+
+    if( len != OID_SIZE( OID_ANSI_X9_62_PRIME_FIELD ) ||
+        memcmp( p, OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+    }
+
+    p += len;
+
+    /* Prime-p ::= INTEGER -- Field of size p. */
+    if( ( ret = asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    grp->pbits = mpi_msb( &grp->P );
+
+    if( p != end_field )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    /*
+     * Curve ::= SEQUENCE {
+     *       a FieldElement,
+     *       b FieldElement,
+     *       seed BIT STRING OPTIONAL
+     *       -- Shall be present if used in SpecifiedECDomain
+     *       -- with version equal to ecdpVer2 or ecdpVer3
+     * }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+        return( ret );
+
+    end_curve = p + len;
+
+    /*
+     * FieldElement ::= OCTET STRING
+     * containing an integer in the case of a prime field
+     */
+    if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 ||
+        ( ret = mpi_read_binary( &grp->A, p, len ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    p += len;
+
+    if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 ||
+        ( ret = mpi_read_binary( &grp->B, p, len ) ) != 0 )
+    {
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+    }
+
+    p += len;
+
+    /* Ignore seed BIT STRING OPTIONAL */
+    if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_BIT_STRING ) ) == 0 )
+        p += len;
+
+    if( p != end_curve )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    /*
+     * ECPoint ::= OCTET STRING
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    if( ( ret = ecp_point_read_binary( grp, &grp->G,
+                                      ( const unsigned char *) p, len ) ) != 0 )
+    {
+        /*
+         * If we can't read the point because it's compressed, cheat by
+         * reading only the X coordinate and the parity bit of Y.
+         */
+        if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ||
+            ( p[0] != 0x02 && p[0] != 0x03 ) ||
+            len != mpi_size( &grp->P ) + 1 ||
+            mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 ||
+            mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 ||
+            mpi_lset( &grp->G.Z, 1 ) != 0 )
+        {
+            return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+        }
+    }
+
+    p += len;
+
+    /*
+     * order INTEGER
+     */
+    if( ( ret = asn1_get_mpi( &p, end, &grp->N ) ) )
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+    grp->nbits = mpi_msb( &grp->N );
+
+    /*
+     * Allow optional elements by purposefully not enforcing p == end here.
+     */
+
+    return( 0 );
+}
+
+/*
+ * Find the group id associated with an (almost filled) group as generated by
+ * pk_group_from_specified(), or return an error if unknown.
+ */
+static int pk_group_id_from_group( const ecp_group *grp, ecp_group_id *grp_id )
+{
+    int ret = 0;
+    ecp_group ref;
+    const ecp_group_id *id;
+
+    ecp_group_init( &ref );
+
+    for( id = ecp_grp_id_list(); *id != POLARSSL_ECP_DP_NONE; id++ )
+    {
+        /* Load the group associated to that id */
+        ecp_group_free( &ref );
+        MPI_CHK( ecp_use_known_dp( &ref, *id ) );
+
+        /* Compare to the group we were given, starting with easy tests */
+        if( grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
+            mpi_cmp_mpi( &grp->P, &ref.P ) == 0 &&
+            mpi_cmp_mpi( &grp->A, &ref.A ) == 0 &&
+            mpi_cmp_mpi( &grp->B, &ref.B ) == 0 &&
+            mpi_cmp_mpi( &grp->N, &ref.N ) == 0 &&
+            mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 &&
+            mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 &&
+            /* For Y we may only know the parity bit, so compare only that */
+            mpi_get_bit( &grp->G.Y, 0 ) == mpi_get_bit( &ref.G.Y, 0 ) )
+        {
+            break;
+        }
+
+    }
+
+cleanup:
+    ecp_group_free( &ref );
+
+    *grp_id = *id;
+
+    if( ret == 0 && *id == POLARSSL_ECP_DP_NONE )
+        ret = POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE;
+
+    return( ret );
+}
+
+/*
+ * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
+ */
+static int pk_group_id_from_specified( const asn1_buf *params,
+                                       ecp_group_id *grp_id )
+{
+    int ret;
+    ecp_group grp;
+
+    ecp_group_init( &grp );
+
+    if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 )
+        goto cleanup;
+
+    ret = pk_group_id_from_group( &grp, grp_id );
+
+cleanup:
+    ecp_group_free( &grp );
+
+    return( ret );
+}
+#endif /* POLARSSL_PK_PARSE_EC_EXTENDED */
+
 /*
  * Use EC parameters to initialise an EC group
+ *
+ * ECParameters ::= CHOICE {
+ *   namedCurve         OBJECT IDENTIFIER
+ *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
+ *   -- implicitCurve   NULL
  */
 static int pk_use_ecparams( const asn1_buf *params, ecp_group *grp )
 {
     int ret;
     ecp_group_id grp_id;
 
-    if( oid_get_ec_grp( params, &grp_id ) != 0 )
-        return( POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE );
+    if( params->tag == ASN1_OID )
+    {
+        if( oid_get_ec_grp( params, &grp_id ) != 0 )
+            return( POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE );
+    }
+    else
+    {
+#if defined(POLARSSL_PK_PARSE_EC_EXTENDED)
+        if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 )
+            return( ret );
+#else
+        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+#endif
+    }
 
     /*
      * grp may already be initilialized; if so, make sure IDs match
@@ -201,6 +468,10 @@ static int pk_use_ecparams( const asn1_buf *params, ecp_group *grp )
 
 /*
  * EC public key is an EC point
+ *
+ * The caller is responsible for clearing the structure upon failure if
+ * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
+ * return code of ecp_point_read_binary() and leave p in a usable state.
  */
 static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
                             ecp_keypair *key )
@@ -208,19 +479,17 @@ static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
     int ret;
 
     if( ( ret = ecp_point_read_binary( &key->grp, &key->Q,
-                    (const unsigned char *) *p, end - *p ) ) != 0 ||
-        ( ret = ecp_check_pubkey( &key->grp, &key->Q ) ) != 0 )
+                    (const unsigned char *) *p, end - *p ) ) == 0 )
     {
-        ecp_keypair_free( key );
-        return( POLARSSL_ERR_PK_INVALID_PUBKEY );
+        ret = ecp_check_pubkey( &key->grp, &key->Q );
     }
 
     /*
-     * We know ecp_point_read_binary consumed all bytes
+     * We know ecp_point_read_binary consumed all bytes or failed
      */
     *p = (unsigned char *) end;
 
-    return( 0 );
+    return( ret );
 }
 #endif /* POLARSSL_ECP_C */
 
@@ -451,7 +720,7 @@ static int pk_parse_key_sec1_der( ecp_keypair *eck,
                                   size_t keylen )
 {
     int ret;
-    int version;
+    int version, pubkey_done;
     size_t len;
     asn1_buf params;
     unsigned char *p = (unsigned char *) key;
@@ -513,8 +782,10 @@ static int pk_parse_key_sec1_der( ecp_keypair *eck,
     }
 
     /*
-     * Is 'publickey' present? If not, create it from the private key.
+     * Is 'publickey' present? If not, or if we can't read it (eg because it
+     * is compressed), create it from the private key.
      */
+    pubkey_done = 0;
     if( ( ret = asn1_get_tag( &p, end, &len,
                     ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
     {
@@ -527,16 +798,27 @@ static int pk_parse_key_sec1_der( ecp_keypair *eck,
             return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
                     POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
 
-        if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) != 0 )
-            return( ret );
+        if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 )
+            pubkey_done = 1;
+        else
+        {
+            /*
+             * The only acceptable failure mode of pk_get_ecpubkey() above
+             * is if the point format is not recognized.
+             */
+            if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE )
+                return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
+        }
     }
-    else if ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
     {
         ecp_keypair_free( eck );
         return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
     }
-    else if( ( ret = ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G,
-                              NULL, NULL ) ) != 0 )
+
+    if( ! pubkey_done &&
+        ( ret = ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G,
+                                                      NULL, NULL ) ) != 0 )
     {
         ecp_keypair_free( eck );
         return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
@@ -548,7 +830,7 @@ static int pk_parse_key_sec1_der( ecp_keypair *eck,
         return( ret );
     }
 
-    return 0;
+    return( 0 );
 }
 #endif /* POLARSSL_ECP_C */
 
@@ -637,7 +919,7 @@ static int pk_parse_key_pkcs8_unencrypted_der(
 #endif /* POLARSSL_ECP_C */
         return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );
 
-    return 0;
+    return( 0 );
 }
 
 /*
@@ -648,7 +930,7 @@ static int pk_parse_key_pkcs8_encrypted_der(
                                     const unsigned char *key, size_t keylen,
                                     const unsigned char *pwd, size_t pwdlen )
 {
-    int ret;
+    int ret, decrypted = 0;
     size_t len;
     unsigned char buf[2048];
     unsigned char *p, *end;
@@ -712,6 +994,8 @@ static int pk_parse_key_pkcs8_encrypted_der(
 
             return( ret );
         }
+
+        decrypted = 1;
     }
     else if( OID_CMP( OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) )
     {
@@ -728,6 +1012,8 @@ static int pk_parse_key_pkcs8_encrypted_der(
         //
         if( *buf != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
             return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
+
+        decrypted = 1;
     }
     else
 #endif /* POLARSSL_PKCS12_C */
@@ -742,14 +1028,18 @@ static int pk_parse_key_pkcs8_encrypted_der(
 
             return( ret );
         }
+
+        decrypted = 1;
     }
     else
 #endif /* POLARSSL_PKCS5_C */
     {
         ((void) pwd);
-        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
     }
 
+    if( decrypted == 0 )
+        return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
+
     return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
 }
 
@@ -951,7 +1241,7 @@ int pk_parse_public_key( pk_context *ctx,
         pem_free( &pem );
         return( ret );
     }
-#endif
+#endif /* POLARSSL_PEM_PARSE_C */
     p = (unsigned char *) key;
 
     ret = pk_parse_subpubkey( &p, p + keylen, ctx );
index 8b6d7356e301b0fed93ebd5832e9eb94e6789191..3b0bbdb4e5969e921915881548b5d45d8c63e452 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Public Key layer for writing key files and structures
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_PK_WRITE_C)
 
@@ -44,8 +48,8 @@
 #include "polarssl/pem.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #include <stdlib.h>
 #define polarssl_malloc     malloc
@@ -69,7 +73,8 @@ static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
     ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) );
 
     ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
 
     return( (int) len );
 }
@@ -187,7 +192,8 @@ int pk_write_pubkey_der( pk_context *key, unsigned char *buf, size_t size )
                                                         par_len ) );
 
     ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                ASN1_SEQUENCE ) );
 
     return( (int) len );
 }
@@ -214,10 +220,11 @@ int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size )
         ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) );
 
         ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
     }
     else
-#endif
+#endif /* POLARSSL_RSA_C */
 #if defined(POLARSSL_ECP_C)
     if( pk_get_type( key ) == POLARSSL_PK_ECKEY )
     {
@@ -267,10 +274,11 @@ int pk_write_key_der( pk_context *key, unsigned char *buf, size_t size )
         ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) );
 
         ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
     }
     else
-#endif
+#endif /* POLARSSL_ECP_C */
         return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE );
 
     return( (int) len );
diff --git a/pdns/ext/polarssl/library/platform.c b/pdns/ext/polarssl/library/platform.c
new file mode 100644 (file)
index 0000000..d57cbc8
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  Platform abstraction layer
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+
+#include "polarssl/platform.h"
+
+#if defined(POLARSSL_PLATFORM_MEMORY)
+#if !defined(POLARSSL_PLATFORM_STD_MALLOC)
+static void *platform_malloc_uninit( size_t len )
+{
+    ((void) len);
+    return( NULL );
+}
+
+#define POLARSSL_PLATFORM_STD_MALLOC   platform_malloc_uninit
+#endif /* !POLARSSL_PLATFORM_STD_MALLOC */
+
+#if !defined(POLARSSL_PLATFORM_STD_FREE)
+static void platform_free_uninit( void *ptr )
+{
+    ((void) ptr);
+}
+
+#define POLARSSL_PLATFORM_STD_FREE     platform_free_uninit
+#endif /* !POLARSSL_PLATFORM_STD_FREE */
+
+void * (*polarssl_malloc)( size_t ) = POLARSSL_PLATFORM_STD_MALLOC;
+void (*polarssl_free)( void * )     = POLARSSL_PLATFORM_STD_FREE;
+
+int platform_set_malloc_free( void * (*malloc_func)( size_t ),
+                              void (*free_func)( void * ) )
+{
+    polarssl_malloc = malloc_func;
+    polarssl_free = free_func;
+    return( 0 );
+}
+#endif /* POLARSSL_PLATFORM_MEMORY */
+
+#if defined(POLARSSL_PLATFORM_PRINTF_ALT)
+#if !defined(POLARSSL_PLATFORM_STD_PRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_printf_uninit( const char *format, ... )
+{
+    ((void) format);
+    return( 0 );
+}
+
+#define POLARSSL_PLATFORM_STD_PRINTF    platform_printf_uninit
+#endif /* !POLARSSL_PLATFORM_STD_PRINTF */
+
+int (*polarssl_printf)( const char *, ... ) = POLARSSL_PLATFORM_STD_PRINTF;
+
+int platform_set_printf( int (*printf_func)( const char *, ... ) )
+{
+    polarssl_printf = printf_func;
+    return( 0 );
+}
+#endif /* POLARSSL_PLATFORM_PRINTF_ALT */
+
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+#if !defined(POLARSSL_PLATFORM_STD_FPRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_fprintf_uninit( FILE *stream, const char *format, ... )
+{
+    ((void) stream);
+    ((void) format);
+    return( 0 );
+}
+
+#define POLARSSL_PLATFORM_STD_FPRINTF   platform_fprintf_uninit
+#endif /* !POLARSSL_PLATFORM_STD_FPRINTF */
+
+int (*polarssl_fprintf)( FILE *, const char *, ... ) =
+                                        POLARSSL_PLATFORM_STD_FPRINTF;
+
+int platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) )
+{
+    polarssl_fprintf = fprintf_func;
+    return( 0 );
+}
+#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */
+
+#endif /* POLARSSL_PLATFORM_C */
diff --git a/pdns/ext/polarssl/library/ripemd160.c b/pdns/ext/polarssl/library/ripemd160.c
new file mode 100644 (file)
index 0000000..fcd7760
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+ *  RIPE MD-160 implementation
+ *
+ *  Copyright (C) 2014-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ *  The RIPEMD-160 algorithm was designed by RIPE in 1996
+ *  http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
+ *  http://ehash.iaik.tugraz.at/wiki/RIPEMD-160
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_RIPEMD160_C)
+
+#include "polarssl/ripemd160.h"
+
+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
+#include <stdio.h>
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+#include <string.h>
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ]       )             \
+        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n)       );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
+}
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+void ripemd160_init( ripemd160_context *ctx )
+{
+    memset( ctx, 0, sizeof( ripemd160_context ) );
+}
+
+void ripemd160_free( ripemd160_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( ripemd160_context ) );
+}
+
+/*
+ * RIPEMD-160 context setup
+ */
+void ripemd160_starts( ripemd160_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+    ctx->state[4] = 0xC3D2E1F0;
+}
+
+/*
+ * Process one block
+ */
+void ripemd160_process( ripemd160_context *ctx, const unsigned char data[64] )
+{
+    uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16];
+
+    GET_UINT32_LE( X[ 0], data,  0 );
+    GET_UINT32_LE( X[ 1], data,  4 );
+    GET_UINT32_LE( X[ 2], data,  8 );
+    GET_UINT32_LE( X[ 3], data, 12 );
+    GET_UINT32_LE( X[ 4], data, 16 );
+    GET_UINT32_LE( X[ 5], data, 20 );
+    GET_UINT32_LE( X[ 6], data, 24 );
+    GET_UINT32_LE( X[ 7], data, 28 );
+    GET_UINT32_LE( X[ 8], data, 32 );
+    GET_UINT32_LE( X[ 9], data, 36 );
+    GET_UINT32_LE( X[10], data, 40 );
+    GET_UINT32_LE( X[11], data, 44 );
+    GET_UINT32_LE( X[12], data, 48 );
+    GET_UINT32_LE( X[13], data, 52 );
+    GET_UINT32_LE( X[14], data, 56 );
+    GET_UINT32_LE( X[15], data, 60 );
+
+    A = Ap = ctx->state[0];
+    B = Bp = ctx->state[1];
+    C = Cp = ctx->state[2];
+    D = Dp = ctx->state[3];
+    E = Ep = ctx->state[4];
+
+#define F1( x, y, z )   ( x ^ y ^ z )
+#define F2( x, y, z )   ( ( x & y ) | ( ~x & z ) )
+#define F3( x, y, z )   ( ( x | ~y ) ^ z )
+#define F4( x, y, z )   ( ( x & z ) | ( y & ~z ) )
+#define F5( x, y, z )   ( x ^ ( y | ~z ) )
+
+#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) )
+
+#define P( a, b, c, d, e, r, s, f, k )      \
+    a += f( b, c, d ) + X[r] + k;           \
+    a = S( a, s ) + e;                      \
+    c = S( c, 10 );
+
+#define P2( a, b, c, d, e, r, s, rp, sp )   \
+    P( a, b, c, d, e, r, s, F, K );         \
+    P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp );
+
+#define F   F1
+#define K   0x00000000
+#define Fp  F5
+#define Kp  0x50A28BE6
+    P2( A, B, C, D, E,  0, 11,  5,  8 );
+    P2( E, A, B, C, D,  1, 14, 14,  9 );
+    P2( D, E, A, B, C,  2, 15,  7,  9 );
+    P2( C, D, E, A, B,  3, 12,  0, 11 );
+    P2( B, C, D, E, A,  4,  5,  9, 13 );
+    P2( A, B, C, D, E,  5,  8,  2, 15 );
+    P2( E, A, B, C, D,  6,  7, 11, 15 );
+    P2( D, E, A, B, C,  7,  9,  4,  5 );
+    P2( C, D, E, A, B,  8, 11, 13,  7 );
+    P2( B, C, D, E, A,  9, 13,  6,  7 );
+    P2( A, B, C, D, E, 10, 14, 15,  8 );
+    P2( E, A, B, C, D, 11, 15,  8, 11 );
+    P2( D, E, A, B, C, 12,  6,  1, 14 );
+    P2( C, D, E, A, B, 13,  7, 10, 14 );
+    P2( B, C, D, E, A, 14,  9,  3, 12 );
+    P2( A, B, C, D, E, 15,  8, 12,  6 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F   F2
+#define K   0x5A827999
+#define Fp  F4
+#define Kp  0x5C4DD124
+    P2( E, A, B, C, D,  7,  7,  6,  9 );
+    P2( D, E, A, B, C,  4,  6, 11, 13 );
+    P2( C, D, E, A, B, 13,  8,  3, 15 );
+    P2( B, C, D, E, A,  1, 13,  7,  7 );
+    P2( A, B, C, D, E, 10, 11,  0, 12 );
+    P2( E, A, B, C, D,  6,  9, 13,  8 );
+    P2( D, E, A, B, C, 15,  7,  5,  9 );
+    P2( C, D, E, A, B,  3, 15, 10, 11 );
+    P2( B, C, D, E, A, 12,  7, 14,  7 );
+    P2( A, B, C, D, E,  0, 12, 15,  7 );
+    P2( E, A, B, C, D,  9, 15,  8, 12 );
+    P2( D, E, A, B, C,  5,  9, 12,  7 );
+    P2( C, D, E, A, B,  2, 11,  4,  6 );
+    P2( B, C, D, E, A, 14,  7,  9, 15 );
+    P2( A, B, C, D, E, 11, 13,  1, 13 );
+    P2( E, A, B, C, D,  8, 12,  2, 11 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F   F3
+#define K   0x6ED9EBA1
+#define Fp  F3
+#define Kp  0x6D703EF3
+    P2( D, E, A, B, C,  3, 11, 15,  9 );
+    P2( C, D, E, A, B, 10, 13,  5,  7 );
+    P2( B, C, D, E, A, 14,  6,  1, 15 );
+    P2( A, B, C, D, E,  4,  7,  3, 11 );
+    P2( E, A, B, C, D,  9, 14,  7,  8 );
+    P2( D, E, A, B, C, 15,  9, 14,  6 );
+    P2( C, D, E, A, B,  8, 13,  6,  6 );
+    P2( B, C, D, E, A,  1, 15,  9, 14 );
+    P2( A, B, C, D, E,  2, 14, 11, 12 );
+    P2( E, A, B, C, D,  7,  8,  8, 13 );
+    P2( D, E, A, B, C,  0, 13, 12,  5 );
+    P2( C, D, E, A, B,  6,  6,  2, 14 );
+    P2( B, C, D, E, A, 13,  5, 10, 13 );
+    P2( A, B, C, D, E, 11, 12,  0, 13 );
+    P2( E, A, B, C, D,  5,  7,  4,  7 );
+    P2( D, E, A, B, C, 12,  5, 13,  5 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F   F4
+#define K   0x8F1BBCDC
+#define Fp  F2
+#define Kp  0x7A6D76E9
+    P2( C, D, E, A, B,  1, 11,  8, 15 );
+    P2( B, C, D, E, A,  9, 12,  6,  5 );
+    P2( A, B, C, D, E, 11, 14,  4,  8 );
+    P2( E, A, B, C, D, 10, 15,  1, 11 );
+    P2( D, E, A, B, C,  0, 14,  3, 14 );
+    P2( C, D, E, A, B,  8, 15, 11, 14 );
+    P2( B, C, D, E, A, 12,  9, 15,  6 );
+    P2( A, B, C, D, E,  4,  8,  0, 14 );
+    P2( E, A, B, C, D, 13,  9,  5,  6 );
+    P2( D, E, A, B, C,  3, 14, 12,  9 );
+    P2( C, D, E, A, B,  7,  5,  2, 12 );
+    P2( B, C, D, E, A, 15,  6, 13,  9 );
+    P2( A, B, C, D, E, 14,  8,  9, 12 );
+    P2( E, A, B, C, D,  5,  6,  7,  5 );
+    P2( D, E, A, B, C,  6,  5, 10, 15 );
+    P2( C, D, E, A, B,  2, 12, 14,  8 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F   F5
+#define K   0xA953FD4E
+#define Fp  F1
+#define Kp  0x00000000
+    P2( B, C, D, E, A,  4,  9, 12,  8 );
+    P2( A, B, C, D, E,  0, 15, 15,  5 );
+    P2( E, A, B, C, D,  5,  5, 10, 12 );
+    P2( D, E, A, B, C,  9, 11,  4,  9 );
+    P2( C, D, E, A, B,  7,  6,  1, 12 );
+    P2( B, C, D, E, A, 12,  8,  5,  5 );
+    P2( A, B, C, D, E,  2, 13,  8, 14 );
+    P2( E, A, B, C, D, 10, 12,  7,  6 );
+    P2( D, E, A, B, C, 14,  5,  6,  8 );
+    P2( C, D, E, A, B,  1, 12,  2, 13 );
+    P2( B, C, D, E, A,  3, 13, 13,  6 );
+    P2( A, B, C, D, E,  8, 14, 14,  5 );
+    P2( E, A, B, C, D, 11, 11,  0, 15 );
+    P2( D, E, A, B, C,  6,  8,  3, 13 );
+    P2( C, D, E, A, B, 15,  5,  9, 11 );
+    P2( B, C, D, E, A, 13,  6, 11, 11 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+    C             = ctx->state[1] + C + Dp;
+    ctx->state[1] = ctx->state[2] + D + Ep;
+    ctx->state[2] = ctx->state[3] + E + Ap;
+    ctx->state[3] = ctx->state[4] + A + Bp;
+    ctx->state[4] = ctx->state[0] + B + Cp;
+    ctx->state[0] = C;
+}
+
+/*
+ * RIPEMD-160 process buffer
+ */
+void ripemd160_update( ripemd160_context *ctx,
+                       const unsigned char *input, size_t ilen )
+{
+    size_t fill;
+    uint32_t left;
+
+    if( ilen == 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += (uint32_t) ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (uint32_t) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, fill );
+        ripemd160_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        ripemd160_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left), input, ilen );
+    }
+}
+
+static const unsigned char ripemd160_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * RIPEMD-160 final digest
+ */
+void ripemd160_finish( ripemd160_context *ctx, unsigned char output[20] )
+{
+    uint32_t last, padn;
+    uint32_t high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT32_LE( low,  msglen, 0 );
+    PUT_UINT32_LE( high, msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    ripemd160_update( ctx, ripemd160_padding, padn );
+    ripemd160_update( ctx, msglen, 8 );
+
+    PUT_UINT32_LE( ctx->state[0], output,  0 );
+    PUT_UINT32_LE( ctx->state[1], output,  4 );
+    PUT_UINT32_LE( ctx->state[2], output,  8 );
+    PUT_UINT32_LE( ctx->state[3], output, 12 );
+    PUT_UINT32_LE( ctx->state[4], output, 16 );
+}
+
+/*
+ * output = RIPEMD-160( input buffer )
+ */
+void ripemd160( const unsigned char *input, size_t ilen,
+                unsigned char output[20] )
+{
+    ripemd160_context ctx;
+
+    ripemd160_init( &ctx );
+    ripemd160_starts( &ctx );
+    ripemd160_update( &ctx, input, ilen );
+    ripemd160_finish( &ctx, output );
+    ripemd160_free( &ctx );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * output = RIPEMD-160( file contents )
+ */
+int ripemd160_file( const char *path, unsigned char output[20] )
+{
+    FILE *f;
+    size_t n;
+    ripemd160_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR );
+
+    ripemd160_init( &ctx );
+    ripemd160_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        ripemd160_update( &ctx, buf, n );
+
+    ripemd160_finish( &ctx, output );
+    ripemd160_free( &ctx );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+#endif /* POLARSSL_FS_IO */
+
+/*
+ * RIPEMD-160 HMAC context setup
+ */
+void ripemd160_hmac_starts( ripemd160_context *ctx,
+                            const unsigned char *key, size_t keylen )
+{
+    size_t i;
+    unsigned char sum[20];
+
+    if( keylen > 64 )
+    {
+        ripemd160( key, keylen, sum );
+        keylen = 20;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    ripemd160_starts( ctx );
+    ripemd160_update( ctx, ctx->ipad, 64 );
+
+    polarssl_zeroize( sum, sizeof( sum ) );
+}
+
+/*
+ * RIPEMD-160 HMAC process buffer
+ */
+void ripemd160_hmac_update( ripemd160_context *ctx,
+                            const unsigned char *input, size_t ilen )
+{
+    ripemd160_update( ctx, input, ilen );
+}
+
+/*
+ * RIPEMD-160 HMAC final digest
+ */
+void ripemd160_hmac_finish( ripemd160_context *ctx, unsigned char output[20] )
+{
+    unsigned char tmpbuf[20];
+
+    ripemd160_finish( ctx, tmpbuf );
+    ripemd160_starts( ctx );
+    ripemd160_update( ctx, ctx->opad, 64 );
+    ripemd160_update( ctx, tmpbuf, 20 );
+    ripemd160_finish( ctx, output );
+
+    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
+}
+
+/*
+ * RIPEMD-160 HMAC context reset
+ */
+void ripemd160_hmac_reset( ripemd160_context *ctx )
+{
+    ripemd160_starts( ctx );
+    ripemd160_update( ctx, ctx->ipad, 64 );
+}
+
+/*
+ * output = HMAC-RIPEMD-160( hmac key, input buffer )
+ */
+void ripemd160_hmac( const unsigned char *key, size_t keylen,
+                     const unsigned char *input, size_t ilen,
+                     unsigned char output[20] )
+{
+    ripemd160_context ctx;
+
+    ripemd160_init( &ctx );
+    ripemd160_hmac_starts( &ctx, key, keylen );
+    ripemd160_hmac_update( &ctx, input, ilen );
+    ripemd160_hmac_finish( &ctx, output );
+    ripemd160_free( &ctx );
+}
+
+
+#if defined(POLARSSL_SELF_TEST)
+/*
+ * Test vectors from the RIPEMD-160 paper and
+ * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html#HMAC
+ */
+#define TESTS   8
+#define KEYS    2
+static const char *ripemd160_test_input[TESTS] =
+{
+    "",
+    "a",
+    "abc",
+    "message digest",
+    "abcdefghijklmnopqrstuvwxyz",
+    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+    "1234567890123456789012345678901234567890"
+        "1234567890123456789012345678901234567890",
+};
+
+static const unsigned char ripemd160_test_md[TESTS][20] =
+{
+    { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
+      0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 },
+    { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
+      0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe },
+    { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
+      0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc },
+    { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
+      0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 },
+    { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
+      0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc },
+    { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
+      0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b },
+    { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed,
+      0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 },
+    { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb,
+      0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb },
+};
+
+static const unsigned char ripemd160_test_hmac[KEYS][TESTS][20] =
+{
+  {
+    { 0xcf, 0x38, 0x76, 0x77, 0xbf, 0xda, 0x84, 0x83, 0xe6, 0x3b,
+      0x57, 0xe0, 0x6c, 0x3b, 0x5e, 0xcd, 0x8b, 0x7f, 0xc0, 0x55 },
+    { 0x0d, 0x35, 0x1d, 0x71, 0xb7, 0x8e, 0x36, 0xdb, 0xb7, 0x39,
+      0x1c, 0x81, 0x0a, 0x0d, 0x2b, 0x62, 0x40, 0xdd, 0xba, 0xfc },
+    { 0xf7, 0xef, 0x28, 0x8c, 0xb1, 0xbb, 0xcc, 0x61, 0x60, 0xd7,
+      0x65, 0x07, 0xe0, 0xa3, 0xbb, 0xf7, 0x12, 0xfb, 0x67, 0xd6 },
+    { 0xf8, 0x36, 0x62, 0xcc, 0x8d, 0x33, 0x9c, 0x22, 0x7e, 0x60,
+      0x0f, 0xcd, 0x63, 0x6c, 0x57, 0xd2, 0x57, 0x1b, 0x1c, 0x34 },
+    { 0x84, 0x3d, 0x1c, 0x4e, 0xb8, 0x80, 0xac, 0x8a, 0xc0, 0xc9,
+      0xc9, 0x56, 0x96, 0x50, 0x79, 0x57, 0xd0, 0x15, 0x5d, 0xdb },
+    { 0x60, 0xf5, 0xef, 0x19, 0x8a, 0x2d, 0xd5, 0x74, 0x55, 0x45,
+      0xc1, 0xf0, 0xc4, 0x7a, 0xa3, 0xfb, 0x57, 0x76, 0xf8, 0x81 },
+    { 0xe4, 0x9c, 0x13, 0x6a, 0x9e, 0x56, 0x27, 0xe0, 0x68, 0x1b,
+      0x80, 0x8a, 0x3b, 0x97, 0xe6, 0xa6, 0xe6, 0x61, 0xae, 0x79 },
+    { 0x31, 0xbe, 0x3c, 0xc9, 0x8c, 0xee, 0x37, 0xb7, 0x9b, 0x06,
+      0x19, 0xe3, 0xe1, 0xc2, 0xbe, 0x4f, 0x1a, 0xa5, 0x6e, 0x6c },
+  },
+  {
+    { 0xfe, 0x69, 0xa6, 0x6c, 0x74, 0x23, 0xee, 0xa9, 0xc8, 0xfa,
+      0x2e, 0xff, 0x8d, 0x9d, 0xaf, 0xb4, 0xf1, 0x7a, 0x62, 0xf5 },
+    { 0x85, 0x74, 0x3e, 0x89, 0x9b, 0xc8, 0x2d, 0xbf, 0xa3, 0x6f,
+      0xaa, 0xa7, 0xa2, 0x5b, 0x7c, 0xfd, 0x37, 0x24, 0x32, 0xcd },
+    { 0x6e, 0x4a, 0xfd, 0x50, 0x1f, 0xa6, 0xb4, 0xa1, 0x82, 0x3c,
+      0xa3, 0xb1, 0x0b, 0xd9, 0xaa, 0x0b, 0xa9, 0x7b, 0xa1, 0x82 },
+    { 0x2e, 0x06, 0x6e, 0x62, 0x4b, 0xad, 0xb7, 0x6a, 0x18, 0x4c,
+      0x8f, 0x90, 0xfb, 0xa0, 0x53, 0x33, 0x0e, 0x65, 0x0e, 0x92 },
+    { 0x07, 0xe9, 0x42, 0xaa, 0x4e, 0x3c, 0xd7, 0xc0, 0x4d, 0xed,
+      0xc1, 0xd4, 0x6e, 0x2e, 0x8c, 0xc4, 0xc7, 0x41, 0xb3, 0xd9 },
+    { 0xb6, 0x58, 0x23, 0x18, 0xdd, 0xcf, 0xb6, 0x7a, 0x53, 0xa6,
+      0x7d, 0x67, 0x6b, 0x8a, 0xd8, 0x69, 0xad, 0xed, 0x62, 0x9a },
+    { 0xf1, 0xbe, 0x3e, 0xe8, 0x77, 0x70, 0x31, 0x40, 0xd3, 0x4f,
+      0x97, 0xea, 0x1a, 0xb3, 0xa0, 0x7c, 0x14, 0x13, 0x33, 0xe2 },
+    { 0x85, 0xf1, 0x64, 0x70, 0x3e, 0x61, 0xa6, 0x31, 0x31, 0xbe,
+      0x7e, 0x45, 0x95, 0x8e, 0x07, 0x94, 0x12, 0x39, 0x04, 0xf9 },
+  },
+};
+
+static const unsigned char ripemd160_test_key[KEYS][20] =
+{
+    { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+      0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x23, 0x45, 0x67 },
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc,
+      0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33 },
+};
+
+/*
+ * Checkup routine
+ */
+int ripemd160_self_test( int verbose )
+{
+    int i, j;
+    unsigned char output[20];
+
+    memset( output, 0, sizeof output );
+
+    for( i = 0; i < TESTS; i++ )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "  RIPEMD-160 test #%d: ", i + 1 );
+
+        ripemd160( (const unsigned char *) ripemd160_test_input[i],
+                   strlen( ripemd160_test_input[i] ),
+                   output );
+
+        if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "passed\n" );
+
+        for( j = 0; j < KEYS; j++ )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "  HMAC-RIPEMD-160 test #%d, key #%d: ",
+                                 i + 1, j + 1 );
+
+            ripemd160_hmac( ripemd160_test_key[j], 20,
+                            (const unsigned char *) ripemd160_test_input[i],
+                            strlen( ripemd160_test_input[i] ),
+                            output );
+
+            if( memcmp( output, ripemd160_test_hmac[j][i], 20 ) != 0 )
+            {
+                if( verbose != 0 )
+                    polarssl_printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            if( verbose != 0 )
+                polarssl_printf( "passed\n" );
+        }
+
+        if( verbose != 0 )
+            polarssl_printf( "\n" );
+    }
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_RIPEMD160_C */
index 210ea46e3fc81777e8f16fece1fccdf7fe367c85..0fd5199b2ab5b17f7c1af341d9bbff1547992029 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  The RSA public-key cryptosystem
  *
- *  Copyright (C) 2006-2011, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_RSA_C)
 
 #include <stdlib.h>
 #include <stdio.h>
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
 /*
  * Initialize an RSA context
  */
@@ -52,14 +62,22 @@ void rsa_init( rsa_context *ctx,
 {
     memset( ctx, 0, sizeof( rsa_context ) );
 
-    ctx->padding = padding;
-    ctx->hash_id = hash_id;
+    rsa_set_padding( ctx, padding, hash_id );
 
 #if defined(POLARSSL_THREADING_C)
     polarssl_mutex_init( &ctx->mutex );
 #endif
 }
 
+/*
+ * Set padding for an existing RSA context
+ */
+void rsa_set_padding( rsa_context *ctx, int padding, int hash_id )
+{
+    ctx->padding = padding;
+    ctx->hash_id = hash_id;
+}
+
 #if defined(POLARSSL_GENPRIME)
 
 /*
@@ -86,7 +104,7 @@ int rsa_gen_key( rsa_context *ctx,
 
     do
     {
-        MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, 
+        MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
                                 f_rng, p_rng ) );
 
         MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
@@ -135,7 +153,7 @@ cleanup:
     return( 0 );
 }
 
-#endif
+#endif /* POLARSSL_GENPRIME */
 
 /*
  * Check a public RSA key
@@ -154,7 +172,7 @@ int rsa_check_pubkey( const rsa_context *ctx )
         return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
 
     if( mpi_msb( &ctx->E ) < 2 ||
-        mpi_msb( &ctx->E ) > 64 )
+        mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 )
         return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
 
     return( 0 );
@@ -311,7 +329,7 @@ cleanup:
 
     return( ret );
 }
-#endif
+#endif /* !POLARSSL_RSA_NO_CRT */
 
 /*
  * Do an RSA private key operation
@@ -343,7 +361,7 @@ int rsa_private( rsa_context *ctx,
     Vi = &ctx->Vi;
     Vf = &ctx->Vf;
 #endif
-#endif
+#endif /* !POLARSSL_RSA_NO_CRT */
 
     mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
 
@@ -401,7 +419,7 @@ int rsa_private( rsa_context *ctx,
         MPI_CHK( mpi_mul_mpi( &T, &T, Vf ) );
         MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
     }
-#endif
+#endif /* POLARSSL_RSA_NO_CRT */
 
     olen = ctx->len;
     MPI_CHK( mpi_write_binary( &T, output, olen ) );
@@ -465,7 +483,7 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
         dlen -= use_len;
     }
 }
-#endif
+#endif /* POLARSSL_PKCS1_V21 */
 
 #if defined(POLARSSL_PKCS1_V21)
 /*
@@ -487,7 +505,10 @@ int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
     const md_info_t *md_info;
     md_context_t md_ctx;
 
-    if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL )
+    if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    if( f_rng == NULL )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     md_info = md_info_from_type( ctx->hash_id );
@@ -497,7 +518,7 @@ int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
     olen = ctx->len;
     hlen = md_get_size( md_info );
 
-    if( olen < ilen + 2 * hlen + 2 || f_rng == NULL )
+    if( olen < ilen + 2 * hlen + 2 )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     memset( output, 0, olen );
@@ -519,6 +540,7 @@ int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
     *p++ = 1;
     memcpy( p, input, ilen );
 
+    md_init( &md_ctx );
     md_init_ctx( &md_ctx, md_info );
 
     // maskedDB: Apply dbMask to DB
@@ -531,7 +553,7 @@ int rsa_rsaes_oaep_encrypt( rsa_context *ctx,
     mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
                &md_ctx );
 
-    md_free_ctx( &md_ctx );
+    md_free( &md_ctx );
 
     return( ( mode == RSA_PUBLIC )
             ? rsa_public(  ctx, output, output )
@@ -554,7 +576,10 @@ int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx,
     int ret;
     unsigned char *p = output;
 
-    if( ctx->padding != RSA_PKCS_V15 || f_rng == NULL )
+    if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    if( f_rng == NULL )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     olen = ctx->len;
@@ -579,8 +604,8 @@ int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx,
 
             // Check if RNG failed to generate data
             //
-            if( rng_dl == 0 || ret != 0)
-                return POLARSSL_ERR_RSA_RNG_FAILED + ret;
+            if( rng_dl == 0 || ret != 0 )
+                return( POLARSSL_ERR_RSA_RNG_FAILED + ret );
 
             p++;
         }
@@ -646,15 +671,18 @@ int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
                             size_t output_max_len )
 {
     int ret;
-    size_t ilen;
-    unsigned char *p;
+    size_t ilen, i, pad_len;
+    unsigned char *p, bad, pad_done;
     unsigned char buf[POLARSSL_MPI_MAX_SIZE];
     unsigned char lhash[POLARSSL_MD_MAX_SIZE];
     unsigned int hlen;
     const md_info_t *md_info;
     md_context_t md_ctx;
 
-    if( ctx->padding != RSA_PKCS_V21 )
+    /*
+     * Parameters sanity checks
+     */
+    if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     ilen = ctx->len;
@@ -662,6 +690,13 @@ int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
     if( ilen < 16 || ilen > sizeof( buf ) )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
+    md_info = md_info_from_type( ctx->hash_id );
+    if( md_info == NULL )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    /*
+     * RSA operation
+     */
     ret = ( mode == RSA_PUBLIC )
           ? rsa_public(  ctx, input, buf )
           : rsa_private( ctx, f_rng, p_rng, input, buf );
@@ -669,53 +704,64 @@ int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
     if( ret != 0 )
         return( ret );
 
-    p = buf;
-
-    if( *p++ != 0 )
-        return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
-    md_info = md_info_from_type( ctx->hash_id );
-    if( md_info == NULL )
-        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
+    /*
+     * Unmask data and generate lHash
+     */
     hlen = md_get_size( md_info );
 
+    md_init( &md_ctx );
     md_init_ctx( &md_ctx, md_info );
 
-    // Generate lHash
-    //
+    /* Generate lHash */
     md( md_info, label, label_len, lhash );
 
-    // seed: Apply seedMask to maskedSeed
-    //
+    /* seed: Apply seedMask to maskedSeed */
     mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
                &md_ctx );
 
-    // DB: Apply dbMask to maskedDB
-    //
+    /* DB: Apply dbMask to maskedDB */
     mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
                &md_ctx );
 
-    p += hlen;
-    md_free_ctx( &md_ctx );
+    md_free( &md_ctx );
 
-    // Check validity
-    //
-    if( memcmp( lhash, p, hlen ) != 0 )
-        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    /*
+     * Check contents, in "constant-time"
+     */
+    p = buf;
+    bad = 0;
 
-    p += hlen;
+    bad |= *p++; /* First byte must be 0 */
 
-    while( *p == 0 && p < buf + ilen )
-        p++;
+    p += hlen; /* Skip seed */
 
-    if( p == buf + ilen )
-        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    /* Check lHash */
+    for( i = 0; i < hlen; i++ )
+        bad |= lhash[i] ^ *p++;
+
+    /* Get zero-padding len, but always read till end of buffer
+     * (minus one, for the 01 byte) */
+    pad_len = 0;
+    pad_done = 0;
+    for( i = 0; i < ilen - 2 * hlen - 2; i++ )
+    {
+        pad_done |= p[i];
+        pad_len += ( pad_done == 0 );
+    }
 
-    if( *p++ != 0x01 )
+    p += pad_len;
+    bad |= *p++ ^ 0x01;
+
+    /*
+     * The only information "leaked" is whether the padding was correct or not
+     * (eg, no data is copied if it was not correct). This meets the
+     * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
+     * the different error conditions.
+     */
+    if( bad != 0 )
         return( POLARSSL_ERR_RSA_INVALID_PADDING );
 
-    if (ilen - (p - buf) > output_max_len)
+    if( ilen - ( p - buf ) > output_max_len )
         return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
 
     *olen = ilen - (p - buf);
@@ -737,13 +783,12 @@ int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
                                  unsigned char *output,
                                  size_t output_max_len)
 {
-    int ret, correct = 1;
-    size_t ilen, pad_count = 0;
-    unsigned char *p, *q;
-    unsigned char bt;
+    int ret;
+    size_t ilen, pad_count = 0, i;
+    unsigned char *p, bad, pad_done = 0;
     unsigned char buf[POLARSSL_MPI_MAX_SIZE];
 
-    if( ctx->padding != RSA_PKCS_V15 )
+    if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     ilen = ctx->len;
@@ -759,60 +804,49 @@ int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
         return( ret );
 
     p = buf;
+    bad = 0;
 
-    if( *p++ != 0 )
-        correct = 0;
-
-    bt = *p++;
-    if( ( bt != RSA_CRYPT && mode == RSA_PRIVATE ) ||
-        ( bt != RSA_SIGN && mode == RSA_PUBLIC ) )
-    {
-        correct = 0;
-    }
+    /*
+     * Check and get padding len in "constant-time"
+     */
+    bad |= *p++; /* First byte must be 0 */
 
-    if( bt == RSA_CRYPT )
+    /* This test does not depend on secret data */
+    if( mode == RSA_PRIVATE )
     {
-        while( *p != 0 && p < buf + ilen - 1 )
-            pad_count += ( *p++ != 0 );
-
-        correct &= ( *p == 0 && p < buf + ilen - 1 );
-
-        q = p;
+        bad |= *p++ ^ RSA_CRYPT;
 
-        // Also pass over all other bytes to reduce timing differences
-        //
-        while ( q < buf + ilen - 1 )
-            pad_count += ( *q++ != 0 );
+        /* Get padding len, but always read till end of buffer
+         * (minus one, for the 00 byte) */
+        for( i = 0; i < ilen - 3; i++ )
+        {
+            pad_done |= ( p[i] == 0 );
+            pad_count += ( pad_done == 0 );
+        }
 
-        // Prevent compiler optimization of pad_count
-        //
-        correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */
-        p++;
+        p += pad_count;
+        bad |= *p++; /* Must be zero */
     }
     else
     {
-        while( *p == 0xFF && p < buf + ilen - 1 )
-            pad_count += ( *p++ == 0xFF );
-
-        correct &= ( *p == 0 && p < buf + ilen - 1 );
+        bad |= *p++ ^ RSA_SIGN;
 
-        q = p;
-
-        // Also pass over all other bytes to reduce timing differences
-        //
-        while ( q < buf + ilen - 1 )
-            pad_count += ( *q++ != 0 );
+        /* Get padding len, but always read till end of buffer
+         * (minus one, for the 00 byte) */
+        for( i = 0; i < ilen - 3; i++ )
+        {
+            pad_done |= ( p[i] != 0xFF );
+            pad_count += ( pad_done == 0 );
+        }
 
-        // Prevent compiler optimization of pad_count
-        //
-        correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */
-        p++;
+        p += pad_count;
+        bad |= *p++; /* Must be zero */
     }
 
-    if( correct == 0 )
+    if( bad )
         return( POLARSSL_ERR_RSA_INVALID_PADDING );
 
-    if (ilen - (p - buf) > output_max_len)
+    if( ilen - ( p - buf ) > output_max_len )
         return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
 
     *olen = ilen - (p - buf);
@@ -875,7 +909,10 @@ int rsa_rsassa_pss_sign( rsa_context *ctx,
     const md_info_t *md_info;
     md_context_t md_ctx;
 
-    if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL )
+    if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    if( f_rng == NULL )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     olen = ctx->len;
@@ -903,8 +940,6 @@ int rsa_rsassa_pss_sign( rsa_context *ctx,
 
     memset( sig, 0, olen );
 
-    msb = mpi_msb( &ctx->N ) - 1;
-
     // Generate salt of length slen
     //
     if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
@@ -918,6 +953,7 @@ int rsa_rsassa_pss_sign( rsa_context *ctx,
     memcpy( p, salt, slen );
     p += slen;
 
+    md_init( &md_ctx );
     md_init_ctx( &md_ctx, md_info );
 
     // Generate H = Hash( M' )
@@ -937,7 +973,7 @@ int rsa_rsassa_pss_sign( rsa_context *ctx,
     //
     mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
 
-    md_free_ctx( &md_ctx );
+    md_free( &md_ctx );
 
     msb = mpi_msb( &ctx->N ) - 1;
     sig[0] &= 0xFF >> ( olen * 8 - msb );
@@ -971,7 +1007,7 @@ int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx,
     unsigned char *p = sig;
     const char *oid;
 
-    if( ctx->padding != RSA_PKCS_V15 )
+    if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     olen = ctx->len;
@@ -1073,14 +1109,16 @@ int rsa_pkcs1_sign( rsa_context *ctx,
 /*
  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
  */
-int rsa_rsassa_pss_verify( rsa_context *ctx,
-                           int (*f_rng)(void *, unsigned char *, size_t),
-                           void *p_rng,
-                           int mode,
-                           md_type_t md_alg,
-                           unsigned int hashlen,
-                           const unsigned char *hash,
-                           const unsigned char *sig )
+int rsa_rsassa_pss_verify_ext( rsa_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng,
+                               int mode,
+                               md_type_t md_alg,
+                               unsigned int hashlen,
+                               const unsigned char *hash,
+                               md_type_t mgf1_hash_id,
+                               int expected_salt_len,
+                               const unsigned char *sig )
 {
     int ret;
     size_t siglen;
@@ -1093,7 +1131,7 @@ int rsa_rsassa_pss_verify( rsa_context *ctx,
     const md_info_t *md_info;
     md_context_t md_ctx;
 
-    if( ctx->padding != RSA_PKCS_V21 )
+    if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     siglen = ctx->len;
@@ -1124,12 +1162,12 @@ int rsa_rsassa_pss_verify( rsa_context *ctx,
         hashlen = md_get_size( md_info );
     }
 
-    md_info = md_info_from_type( ctx->hash_id );
+    md_info = md_info_from_type( mgf1_hash_id );
     if( md_info == NULL )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     hlen = md_get_size( md_info );
-    slen = siglen - hlen - 1;
+    slen = siglen - hlen - 1; /* Currently length of salt + padding */
 
     memset( zeros, 0, 8 );
 
@@ -1147,24 +1185,33 @@ int rsa_rsassa_pss_verify( rsa_context *ctx,
     if( buf[0] >> ( 8 - siglen * 8 + msb ) )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
+    md_init( &md_ctx );
     md_init_ctx( &md_ctx, md_info );
 
     mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );
 
     buf[0] &= 0xFF >> ( siglen * 8 - msb );
 
-    while( *p == 0 && p < buf + siglen )
+    while( p < buf + siglen && *p == 0 )
         p++;
 
     if( p == buf + siglen ||
         *p++ != 0x01 )
     {
-        md_free_ctx( &md_ctx );
+        md_free( &md_ctx );
         return( POLARSSL_ERR_RSA_INVALID_PADDING );
     }
 
+    /* Actual salt len */
     slen -= p - buf;
 
+    if( expected_salt_len != RSA_SALT_LEN_ANY &&
+        slen != (size_t) expected_salt_len )
+    {
+        md_free( &md_ctx );
+        return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
     // Generate H = Hash( M' )
     //
     md_starts( &md_ctx );
@@ -1173,13 +1220,36 @@ int rsa_rsassa_pss_verify( rsa_context *ctx,
     md_update( &md_ctx, p, slen );
     md_finish( &md_ctx, result );
 
-    md_free_ctx( &md_ctx );
+    md_free( &md_ctx );
 
     if( memcmp( p + slen, result, hlen ) == 0 )
         return( 0 );
     else
         return( POLARSSL_ERR_RSA_VERIFY_FAILED );
 }
+
+/*
+ * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function
+ */
+int rsa_rsassa_pss_verify( rsa_context *ctx,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng,
+                           int mode,
+                           md_type_t md_alg,
+                           unsigned int hashlen,
+                           const unsigned char *hash,
+                           const unsigned char *sig )
+{
+    md_type_t mgf1_hash_id = ( ctx->hash_id != POLARSSL_MD_NONE )
+                             ? (md_type_t) ctx->hash_id
+                             : md_alg;
+
+    return( rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode,
+                                       md_alg, hashlen, hash,
+                                       mgf1_hash_id, RSA_SALT_LEN_ANY,
+                                       sig ) );
+
+}
 #endif /* POLARSSL_PKCS1_V21 */
 
 #if defined(POLARSSL_PKCS1_V15)
@@ -1203,7 +1273,7 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
     const md_info_t *md_info;
     asn1_buf oid;
 
-    if( ctx->padding != RSA_PKCS_V15 )
+    if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 )
         return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
     siglen = ctx->len;
@@ -1361,7 +1431,7 @@ int rsa_copy( rsa_context *dst, const rsa_context *src )
 #endif
 
     dst->padding = src->padding;
-    dst->hash_id = src->padding;
+    dst->hash_id = src->hash_id;
 
 cleanup:
     if( ret != 0 )
@@ -1446,9 +1516,10 @@ void rsa_free( rsa_context *ctx )
 #define RSA_PT  "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
                 "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
 
-#if defined(POLARSSL_PCKS1_V15)
+#if defined(POLARSSL_PKCS1_V15)
 static int myrand( void *rng_state, unsigned char *output, size_t len )
 {
+#if !defined(__OpenBSD__)
     size_t i;
 
     if( rng_state != NULL )
@@ -1456,17 +1527,24 @@ static int myrand( void *rng_state, unsigned char *output, size_t len )
 
     for( i = 0; i < len; ++i )
         output[i] = rand();
+#else
+    if( rng_state != NULL )
+        rng_state = NULL;
+
+    arc4random_buf( output, len );
+#endif /* !OpenBSD */
 
     return( 0 );
 }
-#endif
+#endif /* POLARSSL_PKCS1_V15 */
 
 /*
  * Checkup routine
  */
 int rsa_self_test( int verbose )
 {
-#if defined(POLARSSL_PCKS1_V15)
+    int ret = 0;
+#if defined(POLARSSL_PKCS1_V15)
     size_t len;
     rsa_context rsa;
     unsigned char rsa_plaintext[PT_LEN];
@@ -1479,29 +1557,29 @@ int rsa_self_test( int verbose )
     rsa_init( &rsa, RSA_PKCS_V15, 0 );
 
     rsa.len = KEY_LEN;
-    mpi_read_string( &rsa.N , 16, RSA_N  );
-    mpi_read_string( &rsa.E , 16, RSA_E  );
-    mpi_read_string( &rsa.D , 16, RSA_D  );
-    mpi_read_string( &rsa.P , 16, RSA_P  );
-    mpi_read_string( &rsa.Q , 16, RSA_Q  );
-    mpi_read_string( &rsa.DP, 16, RSA_DP );
-    mpi_read_string( &rsa.DQ, 16, RSA_DQ );
-    mpi_read_string( &rsa.QP, 16, RSA_QP );
+    MPI_CHK( mpi_read_string( &rsa.N , 16, RSA_N  ) );
+    MPI_CHK( mpi_read_string( &rsa.E , 16, RSA_E  ) );
+    MPI_CHK( mpi_read_string( &rsa.D , 16, RSA_D  ) );
+    MPI_CHK( mpi_read_string( &rsa.P , 16, RSA_P  ) );
+    MPI_CHK( mpi_read_string( &rsa.Q , 16, RSA_Q  ) );
+    MPI_CHK( mpi_read_string( &rsa.DP, 16, RSA_DP ) );
+    MPI_CHK( mpi_read_string( &rsa.DQ, 16, RSA_DQ ) );
+    MPI_CHK( mpi_read_string( &rsa.QP, 16, RSA_QP ) );
 
     if( verbose != 0 )
-        printf( "  RSA key validation: " );
+        polarssl_printf( "  RSA key validation: " );
 
     if( rsa_check_pubkey(  &rsa ) != 0 ||
         rsa_check_privkey( &rsa ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( 1 );
     }
 
     if( verbose != 0 )
-        printf( "passed\n  PKCS#1 encryption : " );
+        polarssl_printf( "passed\n  PKCS#1 encryption : " );
 
     memcpy( rsa_plaintext, RSA_PT, PT_LEN );
 
@@ -1509,20 +1587,20 @@ int rsa_self_test( int verbose )
                            rsa_plaintext, rsa_ciphertext ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( 1 );
     }
 
     if( verbose != 0 )
-        printf( "passed\n  PKCS#1 decryption : " );
+        polarssl_printf( "passed\n  PKCS#1 decryption : " );
 
     if( rsa_pkcs1_decrypt( &rsa, myrand, NULL, RSA_PRIVATE, &len,
                            rsa_ciphertext, rsa_decrypted,
                            sizeof(rsa_decrypted) ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( 1 );
     }
@@ -1530,14 +1608,14 @@ int rsa_self_test( int verbose )
     if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( 1 );
     }
 
 #if defined(POLARSSL_SHA1_C)
     if( verbose != 0 )
-        printf( "passed\n  PKCS#1 data sign  : " );
+        polarssl_printf( "passed\n  PKCS#1 data sign  : " );
 
     sha1( rsa_plaintext, PT_LEN, sha1sum );
 
@@ -1545,34 +1623,35 @@ int rsa_self_test( int verbose )
                         sha1sum, rsa_ciphertext ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( 1 );
     }
 
     if( verbose != 0 )
-        printf( "passed\n  PKCS#1 sig. verify: " );
+        polarssl_printf( "passed\n  PKCS#1 sig. verify: " );
 
     if( rsa_pkcs1_verify( &rsa, NULL, NULL, RSA_PUBLIC, POLARSSL_MD_SHA1, 0,
                           sha1sum, rsa_ciphertext ) != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( 1 );
     }
 
     if( verbose != 0 )
-        printf( "passed\n\n" );
+        polarssl_printf( "passed\n\n" );
 #endif /* POLARSSL_SHA1_C */
 
+cleanup:
     rsa_free( &rsa );
 #else /* POLARSSL_PKCS1_V15 */
     ((void) verbose);
 #endif /* POLARSSL_PKCS1_V15 */
-    return( 0 );
+    return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_RSA_C */
index b301b097976ead81daf87dab748eaeec47b9734e..20408c742f14ed0a060c14cdb627f3c893dd67c9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  FIPS-180-1 compliant SHA-1 implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://www.itl.nist.gov/fipspubs/fip180-1.htm
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_SHA1_C)
 
 #include <stdio.h>
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if !defined(POLARSSL_SHA1_ALT)
 
 /*
 }
 #endif
 
+void sha1_init( sha1_context *ctx )
+{
+    memset( ctx, 0, sizeof( sha1_context ) );
+}
+
+void sha1_free( sha1_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( sha1_context ) );
+}
+
 /*
  * SHA-1 context setup
  */
@@ -103,8 +131,8 @@ void sha1_process( sha1_context *ctx, const unsigned char data[64] )
 
 #define R(t)                                            \
 (                                                       \
-    temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \
-           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \
+    temp = W[( t -  3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
+           W[( t - 14 ) & 0x0F] ^ W[  t       & 0x0F],  \
     ( W[t & 0x0F] = S(temp,1) )                         \
 )
 
@@ -242,7 +270,7 @@ void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
     size_t fill;
     uint32_t left;
 
-    if( ilen <= 0 )
+    if( ilen == 0 )
         return;
 
     left = ctx->total[0] & 0x3F;
@@ -320,11 +348,11 @@ void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
 {
     sha1_context ctx;
 
+    sha1_init( &ctx );
     sha1_starts( &ctx );
     sha1_update( &ctx, input, ilen );
     sha1_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha1_context ) );
+    sha1_free( &ctx );
 }
 
 #if defined(POLARSSL_FS_IO)
@@ -341,14 +369,14 @@ int sha1_file( const char *path, unsigned char output[20] )
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
 
+    sha1_init( &ctx );
     sha1_starts( &ctx );
 
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         sha1_update( &ctx, buf, n );
 
     sha1_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha1_context ) );
+    sha1_free( &ctx );
 
     if( ferror( f ) != 0 )
     {
@@ -364,7 +392,8 @@ int sha1_file( const char *path, unsigned char output[20] )
 /*
  * SHA-1 HMAC context setup
  */
-void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keylen )
+void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key,
+                       size_t keylen )
 {
     size_t i;
     unsigned char sum[20];
@@ -388,13 +417,14 @@ void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, size_t keyle
     sha1_starts( ctx );
     sha1_update( ctx, ctx->ipad, 64 );
 
-    memset( sum, 0, sizeof( sum ) );
+    polarssl_zeroize( sum, sizeof( sum ) );
 }
 
 /*
  * SHA-1 HMAC process buffer
  */
-void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
+void sha1_hmac_update( sha1_context *ctx, const unsigned char *input,
+                       size_t ilen )
 {
     sha1_update( ctx, input, ilen );
 }
@@ -412,7 +442,7 @@ void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
     sha1_update( ctx, tmpbuf, 20 );
     sha1_finish( ctx, output );
 
-    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
 }
 
 /*
@@ -433,18 +463,18 @@ void sha1_hmac( const unsigned char *key, size_t keylen,
 {
     sha1_context ctx;
 
+    sha1_init( &ctx );
     sha1_hmac_starts( &ctx, key, keylen );
     sha1_hmac_update( &ctx, input, ilen );
     sha1_hmac_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha1_context ) );
+    sha1_free( &ctx );
 }
 
 #if defined(POLARSSL_SELF_TEST)
 /*
  * FIPS-180-1 test vectors
  */
-static unsigned char sha1_test_buf[3][57] = 
+static unsigned char sha1_test_buf[3][57] =
 {
     { "abc" },
     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
@@ -537,18 +567,20 @@ static const unsigned char sha1_hmac_test_sum[7][20] =
  */
 int sha1_self_test( int verbose )
 {
-    int i, j, buflen;
+    int i, j, buflen, ret = 0;
     unsigned char buf[1024];
     unsigned char sha1sum[20];
     sha1_context ctx;
 
+    sha1_init( &ctx );
+
     /*
      * SHA-1
      */
     for( i = 0; i < 3; i++ )
     {
         if( verbose != 0 )
-            printf( "  SHA-1 test #%d: ", i + 1 );
+            polarssl_printf( "  SHA-1 test #%d: ", i + 1 );
 
         sha1_starts( &ctx );
 
@@ -568,22 +600,23 @@ int sha1_self_test( int verbose )
         if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     for( i = 0; i < 7; i++ )
     {
         if( verbose != 0 )
-            printf( "  HMAC-SHA-1 test #%d: ", i + 1 );
+            polarssl_printf( "  HMAC-SHA-1 test #%d: ", i + 1 );
 
         if( i == 5 || i == 6 )
         {
@@ -604,21 +637,25 @@ int sha1_self_test( int verbose )
         if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
-    return( 0 );
+exit:
+    sha1_free( &ctx );
+
+    return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_SHA1_C */
index e4d48427df365f85644fef18d36db368255d3dd9..4fc66982f297f984d5900ae7a58096ad3876243d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  FIPS-180-2 compliant SHA-256 implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_SHA256_C)
 
 #include <stdio.h>
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if !defined(POLARSSL_SHA256_ALT)
 
 /*
 }
 #endif
 
+void sha256_init( sha256_context *ctx )
+{
+    memset( ctx, 0, sizeof( sha256_context ) );
+}
+
+void sha256_free( sha256_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( sha256_context ) );
+}
+
 /*
  * SHA-256 context setup
  */
@@ -233,12 +261,13 @@ void sha256_process( sha256_context *ctx, const unsigned char data[64] )
 /*
  * SHA-256 process buffer
  */
-void sha256_update( sha256_context *ctx, const unsigned char *input, size_t ilen )
+void sha256_update( sha256_context *ctx, const unsigned char *input,
+                    size_t ilen )
 {
     size_t fill;
     uint32_t left;
 
-    if( ilen <= 0 )
+    if( ilen == 0 )
         return;
 
     left = ctx->total[0] & 0x3F;
@@ -322,11 +351,11 @@ void sha256( const unsigned char *input, size_t ilen,
 {
     sha256_context ctx;
 
+    sha256_init( &ctx );
     sha256_starts( &ctx, is224 );
     sha256_update( &ctx, input, ilen );
     sha256_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha256_context ) );
+    sha256_free( &ctx );
 }
 
 #if defined(POLARSSL_FS_IO)
@@ -343,14 +372,14 @@ int sha256_file( const char *path, unsigned char output[32], int is224 )
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( POLARSSL_ERR_SHA256_FILE_IO_ERROR );
 
+    sha256_init( &ctx );
     sha256_starts( &ctx, is224 );
 
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         sha256_update( &ctx, buf, n );
 
     sha256_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha256_context ) );
+    sha256_free( &ctx );
 
     if( ferror( f ) != 0 )
     {
@@ -391,13 +420,14 @@ void sha256_hmac_starts( sha256_context *ctx, const unsigned char *key,
     sha256_starts( ctx, is224 );
     sha256_update( ctx, ctx->ipad, 64 );
 
-    memset( sum, 0, sizeof( sum ) );
+    polarssl_zeroize( sum, sizeof( sum ) );
 }
 
 /*
  * SHA-256 HMAC process buffer
  */
-void sha256_hmac_update( sha256_context *ctx, const unsigned char *input, size_t ilen )
+void sha256_hmac_update( sha256_context *ctx, const unsigned char *input,
+                         size_t ilen )
 {
     sha256_update( ctx, input, ilen );
 }
@@ -419,7 +449,7 @@ void sha256_hmac_finish( sha256_context *ctx, unsigned char output[32] )
     sha256_update( ctx, tmpbuf, hlen );
     sha256_finish( ctx, output );
 
-    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
 }
 
 /*
@@ -440,18 +470,18 @@ void sha256_hmac( const unsigned char *key, size_t keylen,
 {
     sha256_context ctx;
 
+    sha256_init( &ctx );
     sha256_hmac_starts( &ctx, key, keylen, is224 );
     sha256_hmac_update( &ctx, input, ilen );
     sha256_hmac_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha256_context ) );
+    sha256_free( &ctx );
 }
 
 #if defined(POLARSSL_SELF_TEST)
 /*
  * FIPS-180-2 test vectors
  */
-static unsigned char sha256_test_buf[3][57] = 
+static unsigned char sha256_test_buf[3][57] =
 {
     { "abc" },
     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
@@ -615,18 +645,20 @@ static const unsigned char sha256_hmac_test_sum[14][32] =
  */
 int sha256_self_test( int verbose )
 {
-    int i, j, k, buflen;
+    int i, j, k, buflen, ret = 0;
     unsigned char buf[1024];
     unsigned char sha256sum[32];
     sha256_context ctx;
 
+    sha256_init( &ctx );
+
     for( i = 0; i < 6; i++ )
     {
         j = i % 3;
         k = i < 3;
 
         if( verbose != 0 )
-            printf( "  SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+            polarssl_printf( "  SHA-%d test #%d: ", 256 - k * 32, j + 1 );
 
         sha256_starts( &ctx, k );
 
@@ -646,17 +678,18 @@ int sha256_self_test( int verbose )
         if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     for( i = 0; i < 14; i++ )
     {
@@ -664,7 +697,7 @@ int sha256_self_test( int verbose )
         k = i < 7;
 
         if( verbose != 0 )
-            printf( "  HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+            polarssl_printf( "  HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
 
         if( j == 5 || j == 6 )
         {
@@ -685,21 +718,25 @@ int sha256_self_test( int verbose )
         if( memcmp( sha256sum, sha256_hmac_test_sum[i], buflen ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
-    return( 0 );
+exit:
+    sha256_free( &ctx );
+
+    return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_SHA256_C */
index 2366e7c2cd9b81773d5da5a6affe857819fcf1ee..f1d15256f86975db647f0227e16db8bdd441ebe4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  FIPS-180-2 compliant SHA-384/512 implementation
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_SHA512_C)
 
 #include <stdio.h>
 #endif
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if !defined(POLARSSL_SHA512_ALT)
 
 /*
@@ -55,7 +70,7 @@
         | ( (uint64_t) (b)[(i) + 6] <<  8 )       \
         | ( (uint64_t) (b)[(i) + 7]       );      \
 }
-#endif
+#endif /* GET_UINT64_BE */
 
 #ifndef PUT_UINT64_BE
 #define PUT_UINT64_BE(n,b,i)                            \
@@ -69,7 +84,7 @@
     (b)[(i) + 6] = (unsigned char) ( (n) >>  8 );       \
     (b)[(i) + 7] = (unsigned char) ( (n)       );       \
 }
-#endif
+#endif /* PUT_UINT64_BE */
 
 /*
  * Round constants
@@ -118,6 +133,19 @@ static const uint64_t K[80] =
     UL64(0x5FCB6FAB3AD6FAEC),  UL64(0x6C44198C4A475817)
 };
 
+void sha512_init( sha512_context *ctx )
+{
+    memset( ctx, 0, sizeof( sha512_context ) );
+}
+
+void sha512_free( sha512_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( sha512_context ) );
+}
+
 /*
  * SHA-512 context setup
  */
@@ -226,12 +254,13 @@ void sha512_process( sha512_context *ctx, const unsigned char data[128] )
 /*
  * SHA-512 process buffer
  */
-void sha512_update( sha512_context *ctx, const unsigned char *input, size_t ilen )
+void sha512_update( sha512_context *ctx, const unsigned char *input,
+                    size_t ilen )
 {
     size_t fill;
     unsigned int left;
 
-    if( ilen <= 0 )
+    if( ilen == 0 )
         return;
 
     left = (unsigned int) (ctx->total[0] & 0x7F);
@@ -320,11 +349,11 @@ void sha512( const unsigned char *input, size_t ilen,
 {
     sha512_context ctx;
 
+    sha512_init( &ctx );
     sha512_starts( &ctx, is384 );
     sha512_update( &ctx, input, ilen );
     sha512_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha512_context ) );
+    sha512_free( &ctx );
 }
 
 #if defined(POLARSSL_FS_IO)
@@ -341,14 +370,14 @@ int sha512_file( const char *path, unsigned char output[64], int is384 )
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( POLARSSL_ERR_SHA512_FILE_IO_ERROR );
 
+    sha512_init( &ctx );
     sha512_starts( &ctx, is384 );
 
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         sha512_update( &ctx, buf, n );
 
     sha512_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha512_context ) );
+    sha512_free( &ctx );
 
     if( ferror( f ) != 0 )
     {
@@ -389,7 +418,7 @@ void sha512_hmac_starts( sha512_context *ctx, const unsigned char *key,
     sha512_starts( ctx, is384 );
     sha512_update( ctx, ctx->ipad, 128 );
 
-    memset( sum, 0, sizeof( sum ) );
+    polarssl_zeroize( sum, sizeof( sum ) );
 }
 
 /*
@@ -418,7 +447,7 @@ void sha512_hmac_finish( sha512_context *ctx, unsigned char output[64] )
     sha512_update( ctx, tmpbuf, hlen );
     sha512_finish( ctx, output );
 
-    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+    polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
 }
 
 /*
@@ -439,11 +468,11 @@ void sha512_hmac( const unsigned char *key, size_t keylen,
 {
     sha512_context ctx;
 
+    sha512_init( &ctx );
     sha512_hmac_starts( &ctx, key, keylen, is384 );
     sha512_hmac_update( &ctx, input, ilen );
     sha512_hmac_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha512_context ) );
+    sha512_free( &ctx );
 }
 
 #if defined(POLARSSL_SELF_TEST)
@@ -451,7 +480,7 @@ void sha512_hmac( const unsigned char *key, size_t keylen,
 /*
  * FIPS-180-2 test vectors
  */
-static unsigned char sha512_test_buf[3][113] = 
+static unsigned char sha512_test_buf[3][113] =
 {
     { "abc" },
     { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
@@ -670,18 +699,20 @@ static const unsigned char sha512_hmac_test_sum[14][64] =
  */
 int sha512_self_test( int verbose )
 {
-    int i, j, k, buflen;
+    int i, j, k, buflen, ret = 0;
     unsigned char buf[1024];
     unsigned char sha512sum[64];
     sha512_context ctx;
 
+    sha512_init( &ctx );
+
     for( i = 0; i < 6; i++ )
     {
         j = i % 3;
         k = i < 3;
 
         if( verbose != 0 )
-            printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+            polarssl_printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
 
         sha512_starts( &ctx, k );
 
@@ -701,17 +732,18 @@ int sha512_self_test( int verbose )
         if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
     for( i = 0; i < 14; i++ )
     {
@@ -719,7 +751,7 @@ int sha512_self_test( int verbose )
         k = i < 7;
 
         if( verbose != 0 )
-            printf( "  HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+            polarssl_printf( "  HMAC-SHA-%d test #%d: ", 512 - k * 128, j + 1 );
 
         if( j == 5 || j == 6 )
         {
@@ -740,21 +772,25 @@ int sha512_self_test( int verbose )
         if( memcmp( sha512sum, sha512_hmac_test_sum[i], buflen ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
-    return( 0 );
+exit:
+    sha512_free( &ctx );
+
+    return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_SHA512_C */
index e0847b6dc6a170ad91dbbcf6d6c0376541a23755..836b68511b8a8a981e445eed72deef8d26093fcf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  SSL session cache implementation
  *
- *  Copyright (C) 2006-2012, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  * to store and retrieve the session information.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_SSL_CACHE_C)
 
 #include "polarssl/ssl_cache.h"
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
@@ -101,7 +105,9 @@ int ssl_cache_get( void *data, ssl_session *session )
          */
         if( entry->peer_cert.p != NULL )
         {
-            session->peer_cert = (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
+            session->peer_cert =
+                (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
+
             if( session->peer_cert == NULL )
             {
                 ret = 1;
@@ -186,17 +192,15 @@ int ssl_cache_set( void *data, const ssl_session *session )
         /*
          * Reuse oldest entry if max_entries reached
          */
-        if( old != NULL && count >= cache->max_entries )
+        if( count >= cache->max_entries )
         {
-            cur = old;
-            memset( &cur->session, 0, sizeof(ssl_session) );
-#if defined(POLARSSL_X509_CRT_PARSE_C)
-            if( cur->peer_cert.p != NULL )
+            if( old == NULL )
             {
-                polarssl_free( cur->peer_cert.p );
-                memset( &cur->peer_cert, 0, sizeof(x509_buf) );
+                ret = 1;
+                goto exit;
             }
-#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+            cur = old;
         }
 #else /* POLARSSL_HAVE_TIME */
         /*
@@ -213,22 +217,17 @@ int ssl_cache_set( void *data, const ssl_session *session )
 
             cur = cache->chain;
             cache->chain = cur->next;
-
-#if defined(POLARSSL_X509_CRT_PARSE_C)
-            if( cur->peer_cert.p != NULL )
-            {
-                polarssl_free( cur->peer_cert.p );
-                memset( &cur->peer_cert, 0, sizeof(x509_buf) );
-            }
-#endif /* POLARSSL_X509_CRT_PARSE_C */
-
-            memset( cur, 0, sizeof(ssl_cache_entry) );
+            cur->next = NULL;
             prv->next = cur;
         }
 #endif /* POLARSSL_HAVE_TIME */
         else
         {
-            cur = (ssl_cache_entry *) polarssl_malloc( sizeof(ssl_cache_entry) );
+            /*
+             * max_entries not reached, create new entry
+             */
+            cur = (ssl_cache_entry *)
+                        polarssl_malloc( sizeof(ssl_cache_entry) );
             if( cur == NULL )
             {
                 ret = 1;
@@ -251,12 +250,22 @@ int ssl_cache_set( void *data, const ssl_session *session )
     memcpy( &cur->session, session, sizeof( ssl_session ) );
 
 #if defined(POLARSSL_X509_CRT_PARSE_C)
+    /*
+     * If we're reusing an entry, free its certificate first
+     */
+    if( cur->peer_cert.p != NULL )
+    {
+        polarssl_free( cur->peer_cert.p );
+        memset( &cur->peer_cert, 0, sizeof(x509_buf) );
+    }
+
     /*
      * Store peer certificate
      */
     if( session->peer_cert != NULL )
     {
-        cur->peer_cert.p = (unsigned char *) polarssl_malloc( session->peer_cert->raw.len );
+        cur->peer_cert.p = (unsigned char *)
+                                polarssl_malloc( session->peer_cert->raw.len );
         if( cur->peer_cert.p == NULL )
         {
             ret = 1;
@@ -312,8 +321,7 @@ void ssl_cache_free( ssl_cache_context *cache )
         ssl_session_free( &prv->session );
 
 #if defined(POLARSSL_X509_CRT_PARSE_C)
-        if( prv->peer_cert.p != NULL )
-            polarssl_free( prv->peer_cert.p );
+        polarssl_free( prv->peer_cert.p );
 #endif /* POLARSSL_X509_CRT_PARSE_C */
 
         polarssl_free( prv );
index 615e9671518ca4d53a0c8a1149f1305c9f3d0999..df838e260571755b6a774db9232ed800470e039d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * \brief SSL ciphersuites for PolarSSL
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_SSL_TLS_C)
 
 /*
  * Ordered from most preferred to least preferred in terms of security.
  *
- * Current rule (except weak and null which come last):
+ * Current rule (except rc4, weak and null which come last):
  * 1. By key exchange:
  *    Forward-secure non-PSK > forward-secure PSK > other non-PSK > other PSK
  * 2. By key length and cipher:
- *    AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES > RC4
- * 3. By cipher mode when relevant GCM > CBC
- * 4. By hash function used
+ *    AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES
+ * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8
+ * 4. By hash function used when relevant
  * 5. By key exchange/auth again: EC > non-EC
  */
 static const int ciphersuite_preference[] =
 {
+#if defined(SSL_CIPHERSUITES)
+    SSL_CIPHERSUITES,
+#else
     /* All AES-256 ephemeral suites */
     TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
     TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
     TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
+    TLS_DHE_RSA_WITH_AES_256_CCM,
     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
     TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
     TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
+    TLS_DHE_RSA_WITH_AES_256_CCM_8,
 
     /* All CAMELLIA-256 ephemeral suites */
     TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
@@ -77,12 +88,16 @@ static const int ciphersuite_preference[] =
     TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
     TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
     TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
+    TLS_DHE_RSA_WITH_AES_128_CCM,
     TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
     TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
     TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
     TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+    TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+    TLS_DHE_RSA_WITH_AES_128_CCM_8,
 
     /* All CAMELLIA-128 ephemeral suites */
     TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
@@ -97,11 +112,10 @@ static const int ciphersuite_preference[] =
     TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
     TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
     TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
-    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
 
     /* The PSK ephemeral suites */
     TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
+    TLS_DHE_PSK_WITH_AES_256_CCM,
     TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
     TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
     TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
@@ -109,8 +123,10 @@ static const int ciphersuite_preference[] =
     TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,
     TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
     TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+    TLS_DHE_PSK_WITH_AES_256_CCM_8,
 
     TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
+    TLS_DHE_PSK_WITH_AES_128_CCM,
     TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
     TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
     TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
@@ -118,36 +134,59 @@ static const int ciphersuite_preference[] =
     TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,
     TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
     TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_DHE_PSK_WITH_AES_128_CCM_8,
 
     TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
     TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
-    TLS_ECDHE_PSK_WITH_RC4_128_SHA,
-    TLS_DHE_PSK_WITH_RC4_128_SHA,
 
     /* All AES-256 suites */
     TLS_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_RSA_WITH_AES_256_CCM,
     TLS_RSA_WITH_AES_256_CBC_SHA256,
     TLS_RSA_WITH_AES_256_CBC_SHA,
+    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+    TLS_RSA_WITH_AES_256_CCM_8,
 
     /* All CAMELLIA-256 suites */
     TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
     TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
     TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+    TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+    TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+    TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
 
     /* All AES-128 suites */
     TLS_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_RSA_WITH_AES_128_CCM,
     TLS_RSA_WITH_AES_128_CBC_SHA256,
     TLS_RSA_WITH_AES_128_CBC_SHA,
+    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+    TLS_RSA_WITH_AES_128_CCM_8,
 
     /* All CAMELLIA-128 suites */
     TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
     TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
     TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+    TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+    TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
 
     /* All remaining >= 128-bit suites */
     TLS_RSA_WITH_3DES_EDE_CBC_SHA,
-    TLS_RSA_WITH_RC4_128_SHA,
-    TLS_RSA_WITH_RC4_128_MD5,
+    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
 
     /* The RSA PSK suites */
     TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
@@ -163,22 +202,36 @@ static const int ciphersuite_preference[] =
     TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
 
     TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
-    TLS_RSA_PSK_WITH_RC4_128_SHA,
 
     /* The PSK suites */
     TLS_PSK_WITH_AES_256_GCM_SHA384,
+    TLS_PSK_WITH_AES_256_CCM,
     TLS_PSK_WITH_AES_256_CBC_SHA384,
     TLS_PSK_WITH_AES_256_CBC_SHA,
     TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
     TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+    TLS_PSK_WITH_AES_256_CCM_8,
 
     TLS_PSK_WITH_AES_128_GCM_SHA256,
+    TLS_PSK_WITH_AES_128_CCM,
     TLS_PSK_WITH_AES_128_CBC_SHA256,
     TLS_PSK_WITH_AES_128_CBC_SHA,
     TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
     TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+    TLS_PSK_WITH_AES_128_CCM_8,
 
     TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+
+    /* RC4 suites */
+    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+    TLS_ECDHE_PSK_WITH_RC4_128_SHA,
+    TLS_DHE_PSK_WITH_RC4_128_SHA,
+    TLS_RSA_WITH_RC4_128_SHA,
+    TLS_RSA_WITH_RC4_128_MD5,
+    TLS_ECDH_RSA_WITH_RC4_128_SHA,
+    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+    TLS_RSA_PSK_WITH_RC4_128_SHA,
     TLS_PSK_WITH_RC4_128_SHA,
 
     /* Weak suites */
@@ -198,6 +251,8 @@ static const int ciphersuite_preference[] =
     TLS_RSA_WITH_NULL_SHA256,
     TLS_RSA_WITH_NULL_SHA,
     TLS_RSA_WITH_NULL_MD5,
+    TLS_ECDH_RSA_WITH_NULL_SHA,
+    TLS_ECDH_ECDSA_WITH_NULL_SHA,
     TLS_RSA_PSK_WITH_NULL_SHA384,
     TLS_RSA_PSK_WITH_NULL_SHA256,
     TLS_RSA_PSK_WITH_NULL_SHA,
@@ -205,13 +260,10 @@ static const int ciphersuite_preference[] =
     TLS_PSK_WITH_NULL_SHA256,
     TLS_PSK_WITH_NULL_SHA,
 
+#endif
     0
 };
 
-#define MAX_CIPHERSUITES    128
-static int supported_ciphersuites[MAX_CIPHERSUITES];
-static int supported_init = 0;
-
 static const ssl_ciphersuite_t ciphersuite_definitions[] =
 {
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
@@ -262,6 +314,28 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
       0 },
 #endif /* POLARSSL_GCM_C */
 #endif /* POLARSSL_SHA512_C */
+#if defined(POLARSSL_CCM_C)
+    { TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_C */
 #endif /* POLARSSL_AES_C */
 
 #if defined(POLARSSL_CAMELLIA_C)
@@ -269,14 +343,14 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
       POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
 #if defined(POLARSSL_SHA512_C)
     { TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
       POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -388,14 +462,14 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
 #if defined(POLARSSL_SHA512_C)
     { TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384",
       POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_RSA,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -501,6 +575,28 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
       0 },
 #endif /* POLARSSL_SHA1_C */
 #endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_CCM_C)
+    { TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_C */
 #endif /* POLARSSL_AES_C */
 
 #if defined(POLARSSL_CAMELLIA_C)
@@ -614,6 +710,28 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
       0 },
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 #endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_CCM_C)
+    { TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_C */
 #endif /* POLARSSL_AES_C */
 
 #if defined(POLARSSL_CAMELLIA_C)
@@ -697,6 +815,244 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #endif /* POLARSSL_ARC4_C */
 #endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
 
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA1_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_SHA256_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_RSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+#if defined(POLARSSL_AES_C)
+#if defined(POLARSSL_SHA1_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_SHA256_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256",
+      POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256",
+      POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384",
+      POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_GCM_C)
+    { TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384",
+      POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_CAMELLIA_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+
+#if defined(POLARSSL_GCM_C)
+#if defined(POLARSSL_SHA256_C)
+    { TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
+      POLARSSL_CIPHER_CAMELLIA_128_GCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    { TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
+      POLARSSL_CIPHER_CAMELLIA_256_GCM, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA512_C */
+#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_CAMELLIA_C */
+
+#if defined(POLARSSL_DES_C)
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA",
+      POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#endif /* POLARSSL_DES_C */
+
+#if defined(POLARSSL_ARC4_C)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA",
+      POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_ARC4_C */
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+#if defined(POLARSSL_SHA1_C)
+    { TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA",
+      POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDH_ECDSA,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_WEAK },
+#endif /* POLARSSL_SHA1_C */
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
 #if defined(POLARSSL_AES_C)
 #if defined(POLARSSL_GCM_C)
@@ -721,7 +1077,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256",
       POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
@@ -729,7 +1085,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384",
       POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -748,6 +1104,28 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
       0 },
 #endif /* POLARSSL_SHA1_C */
 #endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_CCM_C)
+    { TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_C */
 #endif /* POLARSSL_AES_C */
 
 #if defined(POLARSSL_CAMELLIA_C)
@@ -755,7 +1133,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
@@ -763,7 +1141,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -835,7 +1213,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256",
       POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
@@ -843,7 +1221,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384",
       POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -862,6 +1240,28 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
       0 },
 #endif /* POLARSSL_SHA1_C */
 #endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_CCM_C)
+    { TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8",
+      POLARSSL_CIPHER_AES_256_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+    { TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      0 },
+    { TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8",
+      POLARSSL_CIPHER_AES_128_CCM, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      POLARSSL_CIPHERSUITE_SHORT_TAG },
+#endif /* POLARSSL_CCM_C */
 #endif /* POLARSSL_AES_C */
 
 #if defined(POLARSSL_CAMELLIA_C)
@@ -869,7 +1269,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
@@ -877,7 +1277,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -932,7 +1332,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256",
       POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
@@ -940,7 +1340,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384",
       POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -948,13 +1348,13 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA1_C)
     { TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA",
       POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 
     { TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA",
       POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA1_C */
@@ -966,7 +1366,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
@@ -974,7 +1374,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -986,7 +1386,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA1_C)
     { TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA",
       POLARSSL_CIPHER_DES_EDE3_CBC, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA1_C */
@@ -997,7 +1397,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA1_C)
     { TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA",
       POLARSSL_CIPHER_ARC4_128, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA1_C */
@@ -1028,7 +1428,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256",
       POLARSSL_CIPHER_AES_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
@@ -1036,7 +1436,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384",
       POLARSSL_CIPHER_AES_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -1062,7 +1462,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA256_C */
@@ -1070,7 +1470,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       POLARSSL_CIPHER_CAMELLIA_256_CBC, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       0 },
 #endif /* POLARSSL_SHA512_C */
@@ -1158,7 +1558,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif
@@ -1166,7 +1566,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif
@@ -1184,7 +1584,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_DHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif
@@ -1192,7 +1592,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_DHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif
@@ -1202,7 +1602,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA1_C)
     { TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA1, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif /* POLARSSL_SHA1_C */
@@ -1210,7 +1610,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif
@@ -1218,7 +1618,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_ECDHE_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif
@@ -1236,7 +1636,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA256_C)
     { TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA256, POLARSSL_KEY_EXCHANGE_RSA_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif
@@ -1244,7 +1644,7 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
 #if defined(POLARSSL_SHA512_C)
     { TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384",
       POLARSSL_CIPHER_NULL, POLARSSL_MD_SHA384, POLARSSL_KEY_EXCHANGE_RSA_PSK,
-      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
+      SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0,
       SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3,
       POLARSSL_CIPHERSUITE_WEAK },
 #endif
@@ -1279,6 +1679,17 @@ static const ssl_ciphersuite_t ciphersuite_definitions[] =
     { 0, "", 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
+#if defined(SSL_CIPHERSUITES)
+const int *ssl_list_ciphersuites( void )
+{
+    return( ciphersuite_preference );
+}
+#else
+#define MAX_CIPHERSUITES    sizeof( ciphersuite_definitions     ) /         \
+                            sizeof( ciphersuite_definitions[0]  )
+static int supported_ciphersuites[MAX_CIPHERSUITES];
+static int supported_init = 0;
+
 const int *ssl_list_ciphersuites( void )
 {
     /*
@@ -1287,25 +1698,33 @@ const int *ssl_list_ciphersuites( void )
      */
     if( supported_init == 0 )
     {
-        const int *p = ciphersuite_preference;
-        int *q = supported_ciphersuites;
-        size_t i;
-        size_t max = sizeof(supported_ciphersuites) / sizeof(int);
+        const int *p;
+        int *q;
 
-        for( i = 0; i < max - 1 && p[i] != 0; i++ )
+        for( p = ciphersuite_preference, q = supported_ciphersuites;
+             *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1;
+             p++ )
         {
-            if( ssl_ciphersuite_from_id( p[i] ) != NULL )
-                *(q++) = p[i];
+#if defined(POLARSSL_REMOVE_ARC4_CIPHERSUITES)
+            const ssl_ciphersuite_t *cs_info;
+            if( ( cs_info = ssl_ciphersuite_from_id( *p ) ) != NULL &&
+                cs_info->cipher != POLARSSL_CIPHER_ARC4_128 )
+#else
+            if( ssl_ciphersuite_from_id( *p ) != NULL )
+#endif
+                *(q++) = *p;
         }
         *q = 0;
 
         supported_init = 1;
     }
 
-    return supported_ciphersuites;
+    return( supported_ciphersuites );
 };
+#endif /* SSL_CIPHERSUITES */
 
-const ssl_ciphersuite_t *ssl_ciphersuite_from_string( const char *ciphersuite_name )
+const ssl_ciphersuite_t *ssl_ciphersuite_from_string(
+                                                const char *ciphersuite_name )
 {
     const ssl_ciphersuite_t *cur = ciphersuite_definitions;
 
@@ -1376,12 +1795,17 @@ pk_type_t ssl_get_ciphersuite_sig_pk_alg( const ssl_ciphersuite_t *info )
         case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA:
             return( POLARSSL_PK_ECDSA );
 
+        case POLARSSL_KEY_EXCHANGE_ECDH_RSA:
+        case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA:
+            return( POLARSSL_PK_ECKEY );
+
         default:
             return( POLARSSL_PK_NONE );
     }
 }
-#endif
+#endif /* POLARSSL_PK_C */
 
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
 int ssl_ciphersuite_uses_ec( const ssl_ciphersuite_t *info )
 {
     switch( info->key_exchange )
@@ -1389,13 +1813,17 @@ int ssl_ciphersuite_uses_ec( const ssl_ciphersuite_t *info )
         case POLARSSL_KEY_EXCHANGE_ECDHE_RSA:
         case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA:
         case POLARSSL_KEY_EXCHANGE_ECDHE_PSK:
+        case POLARSSL_KEY_EXCHANGE_ECDH_RSA:
+        case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA:
             return( 1 );
 
         default:
             return( 0 );
     }
 }
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
 
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
 int ssl_ciphersuite_uses_psk( const ssl_ciphersuite_t *info )
 {
     switch( info->key_exchange )
@@ -1410,5 +1838,6 @@ int ssl_ciphersuite_uses_psk( const ssl_ciphersuite_t *info )
             return( 0 );
     }
 }
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
 
-#endif
+#endif /* POLARSSL_SSL_TLS_C */
index 0eaa531fc9f1e5473a3302824840a061e372e792..d38d769551e01a45f6f6d9928e2e8bdb21ace091 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  SSLv3/TLSv1 client-side functions
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_SSL_CLI_C)
 
 #include "polarssl/debug.h"
 #include "polarssl/ssl.h"
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
@@ -51,6 +55,13 @@ typedef UINT32 uint32_t;
 #include <time.h>
 #endif
 
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+#endif
+
 #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
 static void ssl_write_hostname_ext( ssl_context *ssl,
                                     unsigned char *buf,
@@ -60,7 +71,7 @@ static void ssl_write_hostname_ext( ssl_context *ssl,
 
     *olen = 0;
 
-    if ( ssl->hostname == NULL )
+    if( ssl->hostname == NULL )
         return;
 
     SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s",
@@ -137,8 +148,10 @@ static void ssl_write_signature_algorithms_ext( ssl_context *ssl,
                                                 size_t *olen )
 {
     unsigned char *p = buf;
-    unsigned char *sig_alg_list = buf + 6;
     size_t sig_alg_len = 0;
+#if defined(POLARSSL_RSA_C) || defined(POLARSSL_ECDSA_C)
+    unsigned char *sig_alg_list = buf + 6;
+#endif
 
     *olen = 0;
 
@@ -231,21 +244,30 @@ static void ssl_write_supported_elliptic_curves_ext( ssl_context *ssl,
                                                      size_t *olen )
 {
     unsigned char *p = buf;
-    unsigned char elliptic_curve_list[20];
+    unsigned char *elliptic_curve_list = p + 6;
     size_t elliptic_curve_len = 0;
-    const ecp_curve_info *curve;
+    const ecp_curve_info *info;
+#if defined(POLARSSL_SSL_SET_CURVES)
+    const ecp_group_id *grp_id;
+#else
     ((void) ssl);
+#endif
 
     *olen = 0;
 
     SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) );
 
-    for( curve = ecp_curve_list();
-         curve->grp_id != POLARSSL_ECP_DP_NONE;
-         curve++ )
+#if defined(POLARSSL_SSL_SET_CURVES)
+    for( grp_id = ssl->curve_list; *grp_id != POLARSSL_ECP_DP_NONE; grp_id++ )
+    {
+        info = ecp_curve_info_from_grp_id( *grp_id );
+#else
+    for( info = ecp_curve_list(); info->grp_id != POLARSSL_ECP_DP_NONE; info++ )
     {
-        elliptic_curve_list[elliptic_curve_len++] = curve->tls_id >> 8;
-        elliptic_curve_list[elliptic_curve_len++] = curve->tls_id & 0xFF;
+#endif
+
+        elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8;
+        elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
     }
 
     if( elliptic_curve_len == 0 )
@@ -260,8 +282,6 @@ static void ssl_write_supported_elliptic_curves_ext( ssl_context *ssl,
     *p++ = (unsigned char)( ( ( elliptic_curve_len     ) >> 8 ) & 0xFF );
     *p++ = (unsigned char)( ( ( elliptic_curve_len     )      ) & 0xFF );
 
-    memcpy( p, elliptic_curve_list, elliptic_curve_len );
-
     *olen = 6 + elliptic_curve_len;
 }
 
@@ -376,6 +396,54 @@ static void ssl_write_session_ticket_ext( ssl_context *ssl,
 }
 #endif /* POLARSSL_SSL_SESSION_TICKETS */
 
+#if defined(POLARSSL_SSL_ALPN)
+static void ssl_write_alpn_ext( ssl_context *ssl,
+                                unsigned char *buf, size_t *olen )
+{
+    unsigned char *p = buf;
+    const char **cur;
+
+    if( ssl->alpn_list == NULL )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) );
+
+    *p++ = (unsigned char)( ( TLS_EXT_ALPN >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( TLS_EXT_ALPN      ) & 0xFF );
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     */
+
+    /* Skip writing extension and list length for now */
+    p += 4;
+
+    for( cur = ssl->alpn_list; *cur != NULL; cur++ )
+    {
+        *p = (unsigned char)( strlen( *cur ) & 0xFF );
+        memcpy( p + 1, *cur, *p );
+        p += 1 + *p;
+    }
+
+    *olen = p - buf;
+
+    /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */
+    buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
+    buf[5] = (unsigned char)( ( ( *olen - 6 )      ) & 0xFF );
+
+    /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */
+    buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
+    buf[3] = (unsigned char)( ( ( *olen - 4 )      ) & 0xFF );
+}
+#endif /* POLARSSL_SSL_ALPN */
+
 static int ssl_write_client_hello( ssl_context *ssl )
 {
     int ret;
@@ -390,6 +458,12 @@ static int ssl_write_client_hello( ssl_context *ssl )
 
     SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
 
+    if( ssl->f_rng == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "no RNG provided") );
+        return( POLARSSL_ERR_SSL_NO_RNG );
+    }
+
     if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
     {
         ssl->major_ver = ssl->min_major_ver;
@@ -431,7 +505,7 @@ static int ssl_write_client_hello( ssl_context *ssl )
         return( ret );
 
     p += 4;
-#endif
+#endif /* POLARSSL_HAVE_TIME */
 
     if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
         return( ret );
@@ -542,7 +616,7 @@ static int ssl_write_client_hello( ssl_context *ssl )
 
     *p++ = 1;
     *p++ = SSL_COMPRESS_NULL;
-#endif
+#endif /* POLARSSL_ZLIB_SUPPORT */
 
     // First write extensions, then the total length
     //
@@ -582,12 +656,20 @@ static int ssl_write_client_hello( ssl_context *ssl )
     ext_len += olen;
 #endif
 
+#if defined(POLARSSL_SSL_ALPN)
+    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
     SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
                    ext_len ) );
 
-    *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
-    p += ext_len;
+    if( ext_len > 0 )
+    {
+        *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
+        p += ext_len;
+    }
 
     ssl->out_msglen  = p - buf;
     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
@@ -721,7 +803,7 @@ static int ssl_parse_supported_point_formats_ext( ssl_context *ssl,
         return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
-    p = buf + 2;
+    p = buf + 1;
     while( list_size > 0 )
     {
         if( p[0] == POLARSSL_ECP_PF_UNCOMPRESSED ||
@@ -736,10 +818,59 @@ static int ssl_parse_supported_point_formats_ext( ssl_context *ssl,
         p++;
     }
 
-    return( 0 );
+    SSL_DEBUG_MSG( 1, ( "no point format in common" ) );
+    return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
 }
 #endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
 
+#if defined(POLARSSL_SSL_ALPN)
+static int ssl_parse_alpn_ext( ssl_context *ssl,
+                               const unsigned char *buf, size_t len )
+{
+    size_t list_len, name_len;
+    const char **p;
+
+    /* If we didn't send it, the server shouldn't send it */
+    if( ssl->alpn_list == NULL )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     *
+     * the "ProtocolNameList" MUST contain exactly one "ProtocolName"
+     */
+
+    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
+    if( len < 4 )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    list_len = ( buf[0] << 8 ) | buf[1];
+    if( list_len != len - 2 )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    name_len = buf[2];
+    if( name_len != list_len - 1 )
+        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    /* Check that the server chosen protocol was in our list and save it */
+    for( p = ssl->alpn_list; *p != NULL; p++ )
+    {
+        if( name_len == strlen( *p ) &&
+            memcmp( buf + 3, *p, name_len ) == 0 )
+        {
+            ssl->alpn_chosen = *p;
+            return( 0 );
+        }
+    }
+
+    return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
+}
+#endif /* POLARSSL_SSL_ALPN */
+
 static int ssl_parse_server_hello( ssl_context *ssl )
 {
     int ret, i, comp;
@@ -797,8 +928,8 @@ static int ssl_parse_server_hello( ssl_context *ssl )
     if( ssl->minor_ver < ssl->min_minor_ver )
     {
         SSL_DEBUG_MSG( 1, ( "server only supports ssl smaller than minimum"
-                            " [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver,
-                            buf[4], buf[5] ) );
+                            " [%d:%d] < [%d:%d]", ssl->major_ver,
+                            ssl->minor_ver, buf[4], buf[5] ) );
 
         ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
                                      SSL_ALERT_MSG_PROTOCOL_VERSION );
@@ -854,15 +985,15 @@ static int ssl_parse_server_hello( ssl_context *ssl )
      * Initialize update checksum functions
      */
     ssl->transform_negotiate->ciphersuite_info = ssl_ciphersuite_from_id( i );
-    ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
 
     if( ssl->transform_negotiate->ciphersuite_info == NULL )
     {
-        SSL_DEBUG_MSG( 1, ( "ciphersuite info for %02x not found",
-                          ssl->ciphersuite_list[ssl->minor_ver][i] ) );
+        SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) );
         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
     }
 
+    ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
+
     SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
     SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
 
@@ -953,7 +1084,8 @@ static int ssl_parse_server_hello( ssl_context *ssl )
             SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
             renegotiation_info_seen = 1;
 
-            if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ) ) != 0 )
+            if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4,
+                                                      ext_size ) ) != 0 )
                 return( ret );
 
             break;
@@ -1010,6 +1142,16 @@ static int ssl_parse_server_hello( ssl_context *ssl )
             break;
 #endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
 
+#if defined(POLARSSL_SSL_ALPN)
+        case TLS_EXT_ALPN:
+            SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
+
+            if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 )
+                return( ret );
+
+            break;
+#endif /* POLARSSL_SSL_ALPN */
+
         default:
             SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
                            ext_id ) );
@@ -1107,6 +1249,42 @@ static int ssl_parse_server_dh_params( ssl_context *ssl, unsigned char **p,
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
           POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+static int ssl_check_server_ecdh_params( const ssl_context *ssl )
+{
+    const ecp_curve_info *curve_info;
+
+    curve_info = ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id );
+    if( curve_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
+
+#if defined(POLARSSL_SSL_ECP_SET_CURVES)
+    if( ! ssl_curve_is_acceptable( ssl, ssl->handshake->ecdh_ctx.grp.id ) )
+#else
+    if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
+        ssl->handshake->ecdh_ctx.grp.nbits > 521 )
+#endif
+        return( -1 );
+
+    SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp );
+
+    return( 0 );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
     defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
     defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
@@ -1131,18 +1309,12 @@ static int ssl_parse_server_ecdh_params( ssl_context *ssl,
         return( ret );
     }
 
-    SSL_DEBUG_MSG( 2, ( "ECDH curve size: %d",
-                        (int) ssl->handshake->ecdh_ctx.grp.nbits ) );
-
-    if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
-        ssl->handshake->ecdh_ctx.grp.nbits > 521 )
+    if( ssl_check_server_ecdh_params( ssl ) != 0 )
     {
-        SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDH length)" ) );
+        SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
 
-    SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp );
-
     return( ret );
 }
 #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
@@ -1301,6 +1473,41 @@ static int ssl_parse_signature_algorithm( ssl_context *ssl,
           POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 #endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+static int ssl_get_ecdh_params_from_cert( ssl_context *ssl )
+{
+    int ret;
+    const ecp_keypair *peer_key;
+
+    if( ! pk_can_do( &ssl->session_negotiate->peer_cert->pk,
+                     POLARSSL_PK_ECKEY ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
+        return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
+    }
+
+    peer_key = pk_ec( ssl->session_negotiate->peer_cert->pk );
+
+    if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key,
+                                 POLARSSL_ECDH_THEIRS ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret );
+        return( ret );
+    }
+
+    if( ssl_check_server_ecdh_params( ssl ) != 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) );
+        return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+    }
+
+    return( ret );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
 static int ssl_parse_server_key_exchange( ssl_context *ssl )
 {
     int ret;
@@ -1329,6 +1536,26 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
     ((void) end);
 #endif
 
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
+    {
+        if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
+            return( ret );
+        }
+
+        SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+    ((void) p);
+    ((void) end);
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
     if( ( ret = ssl_read_record( ssl ) ) != 0 )
     {
         SSL_DEBUG_RET( 1, "ssl_read_record", ret );
@@ -1417,7 +1644,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
           POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
@@ -1449,7 +1676,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
             }
         }
         else
-#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 #if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
     defined(POLARSSL_SSL_PROTO_TLS1_1)
         if( ssl->minor_ver < SSL_MINOR_VERSION_3 )
@@ -1464,7 +1691,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
 #endif
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
         /*
@@ -1491,6 +1718,9 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
             md5_context md5;
             sha1_context sha1;
 
+            md5_init(  &md5  );
+            sha1_init( &sha1 );
+
             hashlen = 36;
 
             /*
@@ -1515,6 +1745,9 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
             sha1_update( &sha1, ssl->handshake->randbytes, 64 );
             sha1_update( &sha1, ssl->in_msg + 4, params_len );
             sha1_finish( &sha1, hash + 16 );
+
+            md5_free(  &md5  );
+            sha1_free( &sha1 );
         }
         else
 #endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \
@@ -1525,6 +1758,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
         {
             md_context_t ctx;
 
+            md_init( &ctx );
+
             /* Info from md_alg will be used instead */
             hashlen = 0;
 
@@ -1535,7 +1770,8 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
              *     ServerDHParams params;
              * };
              */
-            if( ( ret = md_init_ctx( &ctx, md_info_from_type( md_alg ) ) ) != 0 )
+            if( ( ret = md_init_ctx( &ctx,
+                                     md_info_from_type( md_alg ) ) ) != 0 )
             {
                 SSL_DEBUG_RET( 1, "md_init_ctx", ret );
                 return( ret );
@@ -1545,14 +1781,14 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
             md_update( &ctx, ssl->handshake->randbytes, 64 );
             md_update( &ctx, ssl->in_msg + 4, params_len );
             md_finish( &ctx, hash );
-            md_free_ctx( &ctx );
+            md_free( &ctx );
         }
         else
 #endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
           POLARSSL_SSL_PROTO_TLS1_2 */
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
         SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
@@ -1586,15 +1822,50 @@ exit:
     return( 0 );
 }
 
+#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)       && \
+    !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)   && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+static int ssl_parse_certificate_request( ssl_context *ssl )
+{
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+
+    SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
+
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
+    SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+}
+#else
 static int ssl_parse_certificate_request( ssl_context *ssl )
 {
     int ret;
     unsigned char *buf, *p;
     size_t n = 0, m = 0;
     size_t cert_type_len = 0, dn_len = 0;
+    const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
 
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
+    {
+        SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
+        ssl->state++;
+        return( 0 );
+    }
+
     /*
      *     0  .   0   handshake type
      *     1  .   3   handshake length
@@ -1720,6 +1991,10 @@ exit:
 
     return( 0 );
 }
+#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
 static int ssl_parse_server_hello_done( ssl_context *ssl )
 {
@@ -1790,7 +2065,7 @@ static int ssl_write_client_key_exchange( ssl_context *ssl )
         SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X  );
         SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
 
-        ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
+        ssl->handshake->pmslen = POLARSSL_PREMASTER_SIZE;
 
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
                                       ssl->handshake->premaster,
@@ -1806,9 +2081,13 @@ static int ssl_write_client_key_exchange( ssl_context *ssl )
     else
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
-        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
     {
         /*
          * ECDH key exchange -- send client public value
@@ -1841,7 +2120,9 @@ static int ssl_write_client_key_exchange( ssl_context *ssl )
     }
     else
 #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
@@ -1920,7 +2201,7 @@ static int ssl_write_client_key_exchange( ssl_context *ssl )
 #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
         if( ( ret = ssl_psk_derive_premaster( ssl,
@@ -1944,7 +2225,7 @@ static int ssl_write_client_key_exchange( ssl_context *ssl )
     {
         ((void) ciphersuite_info);
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
     if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
@@ -1976,12 +2257,12 @@ static int ssl_write_client_key_exchange( ssl_context *ssl )
     !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 static int ssl_write_certificate_verify( ssl_context *ssl )
 {
-    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
 
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
@@ -1990,8 +2271,8 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
         return( 0 );
     }
 
-    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
-    return( ret );
+    SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
 }
 #else
 static int ssl_write_certificate_verify( ssl_context *ssl )
@@ -2007,6 +2288,7 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
     SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
 
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
@@ -2104,7 +2386,7 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
 #endif /* POLARSSL_SSL_PROTO_TLS1_2 */
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
     if( ( ret = pk_sign( ssl_own_key( ssl ), md_alg, hash_start, hashlen,
@@ -2199,9 +2481,11 @@ static int ssl_parse_new_session_ticket( ssl_context *ssl )
      * Zero-length ticket means the server changed his mind and doesn't want
      * to send a ticket after all, so just forget it
      */
-    if( ticket_len == 0)
+    if( ticket_len == 0 )
         return( 0 );
 
+    polarssl_zeroize( ssl->session_negotiate->ticket,
+                      ssl->session_negotiate->ticket_len );
     polarssl_free( ssl->session_negotiate->ticket );
     ssl->session_negotiate->ticket = NULL;
     ssl->session_negotiate->ticket_len = 0;
@@ -2348,4 +2632,4 @@ int ssl_handshake_client_step( ssl_context *ssl )
 
     return( ret );
 }
-#endif
+#endif /* POLARSSL_SSL_CLI_C */
index e44bf7212f27ed2fe98ceafb9f9f89617246393a..25be98826739ff7e91498f08d21ec094f8353c2f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  SSLv3/TLSv1 server-side functions
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_SSL_SRV_C)
 
@@ -33,8 +37,8 @@
 #include "polarssl/ecp.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #endif
 
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * Serialize a session in the following format:
  *  0   .   n-1     session structure, n = sizeof(ssl_session)
@@ -140,7 +149,8 @@ static int ssl_load_session( ssl_session *session,
 
         x509_crt_init( session->peer_cert );
 
-        if( ( ret = x509_crt_parse( session->peer_cert, p, cert_len ) ) != 0 )
+        if( ( ret = x509_crt_parse_der( session->peer_cert,
+                                        p, cert_len ) ) != 0 )
         {
             x509_crt_free( session->peer_cert );
             polarssl_free( session->peer_cert );
@@ -202,7 +212,7 @@ static int ssl_write_ticket( ssl_context *ssl, size_t *tlen )
      */
     state = p + 2;
     if( ssl_save_session( ssl->session_negotiate, state,
-                          SSL_MAX_CONTENT_LEN - (state - ssl->out_ctr) - 48,
+                          SSL_MAX_CONTENT_LEN - ( state - ssl->out_ctr ) - 48,
                           &clear_len ) != 0 )
     {
         return( POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE );
@@ -310,7 +320,7 @@ static int ssl_parse_ticket( ssl_context *ssl,
     if( ( ret = ssl_load_session( &session, ticket, clear_len ) ) != 0 )
     {
         SSL_DEBUG_MSG( 1, ( "failed to parse ticket content" ) );
-        memset( &session, 0, sizeof( ssl_session ) );
+        ssl_session_free( &session );
         return( ret );
     }
 
@@ -319,7 +329,7 @@ static int ssl_parse_ticket( ssl_context *ssl,
     if( (int) ( time( NULL) - session.start ) > ssl->ticket_lifetime )
     {
         SSL_DEBUG_MSG( 1, ( "session ticket expired" ) );
-        memset( &session, 0, sizeof( ssl_session ) );
+        ssl_session_free( &session );
         return( POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED );
     }
 #endif
@@ -333,7 +343,9 @@ static int ssl_parse_ticket( ssl_context *ssl,
 
     ssl_session_free( ssl->session_negotiate );
     memcpy( ssl->session_negotiate, &session, sizeof( ssl_session ) );
-    memset( &session, 0, sizeof( ssl_session ) );
+
+    /* Zeroize instead of free as we copied the content */
+    polarssl_zeroize( &session, sizeof( ssl_session ) );
 
     return( 0 );
 }
@@ -367,6 +379,8 @@ static int ssl_parse_servername_ext( ssl_context *ssl,
     size_t servername_list_size, hostname_len;
     const unsigned char *p;
 
+    SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
+
     servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
     if( servername_list_size + 2 != len )
     {
@@ -389,6 +403,7 @@ static int ssl_parse_servername_ext( ssl_context *ssl,
             ret = ssl_sni_wrapper( ssl, p + 3, hostname_len );
             if( ret != 0 )
             {
+                SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret );
                 ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
                         SSL_ALERT_MSG_UNRECOGNIZED_NAME );
                 return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
@@ -457,59 +472,31 @@ static int ssl_parse_signature_algorithms_ext( ssl_context *ssl,
 {
     size_t sig_alg_list_size;
     const unsigned char *p;
+    const unsigned char *end = buf + len;
+    const int *md_cur;
+
 
     sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
     if( sig_alg_list_size + 2 != len ||
-        sig_alg_list_size %2 != 0 )
+        sig_alg_list_size % 2 != 0 )
     {
         SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
     }
 
-    p = buf + 2;
-    while( sig_alg_list_size > 0 )
-    {
-        /*
-         * For now, just ignore signature algorithm and rely on offered
-         * ciphersuites only. To be fixed later.
-         */
-#if defined(POLARSSL_SHA512_C)
-        if( p[0] == SSL_HASH_SHA512 )
-        {
-            ssl->handshake->sig_alg = SSL_HASH_SHA512;
-            break;
-        }
-        if( p[0] == SSL_HASH_SHA384 )
-        {
-            ssl->handshake->sig_alg = SSL_HASH_SHA384;
-            break;
-        }
-#endif
-#if defined(POLARSSL_SHA256_C)
-        if( p[0] == SSL_HASH_SHA256 )
-        {
-            ssl->handshake->sig_alg = SSL_HASH_SHA256;
-            break;
-        }
-        if( p[0] == SSL_HASH_SHA224 )
-        {
-            ssl->handshake->sig_alg = SSL_HASH_SHA224;
-            break;
-        }
-#endif
-        if( p[0] == SSL_HASH_SHA1 )
-        {
-            ssl->handshake->sig_alg = SSL_HASH_SHA1;
-            break;
-        }
-        if( p[0] == SSL_HASH_MD5 )
-        {
-            ssl->handshake->sig_alg = SSL_HASH_MD5;
-            break;
+    /*
+     * For now, ignore the SignatureAlgorithm part and rely on offered
+     * ciphersuites only for that part. To be fixed later.
+     *
+     * So, just look at the HashAlgorithm part.
+     */
+    for( md_cur = md_list(); *md_cur != POLARSSL_MD_NONE; md_cur++ ) {
+        for( p = buf + 2; p < end; p += 2 ) {
+            if( *md_cur == (int) ssl_md_alg_from_hash( p[0] ) ) {
+                ssl->handshake->sig_alg = p[0];
+                break;
+            }
         }
-
-        sig_alg_list_size -= 2;
-        p += 2;
     }
 
     SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d",
@@ -536,7 +523,7 @@ static int ssl_parse_supported_elliptic_curves( ssl_context *ssl,
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
     }
 
-    /* Don't allow our peer to make use allocated too much memory,
+    /* Don't allow our peer to make us allocate too much memory,
      * and leave room for a final 0 */
     our_size = list_size / 2 + 1;
     if( our_size > POLARSSL_ECP_DP_MAX )
@@ -545,7 +532,7 @@ static int ssl_parse_supported_elliptic_curves( ssl_context *ssl,
     if( ( curves = polarssl_malloc( our_size * sizeof( *curves ) ) ) == NULL )
         return( POLARSSL_ERR_SSL_MALLOC_FAILED );
 
-       /* explicit void pointer cast for buggy MS compiler */
+    /* explicit void pointer cast for buggy MS compiler */
     memset( (void *) curves, 0, our_size * sizeof( *curves ) );
     ssl->handshake->curves = curves;
 
@@ -680,6 +667,207 @@ static int ssl_parse_session_ticket_ext( ssl_context *ssl,
 }
 #endif /* POLARSSL_SSL_SESSION_TICKETS */
 
+#if defined(POLARSSL_SSL_ALPN)
+static int ssl_parse_alpn_ext( ssl_context *ssl,
+                               const unsigned char *buf, size_t len )
+{
+    size_t list_len, cur_len, ours_len;
+    const unsigned char *theirs, *start, *end;
+    const char **ours;
+
+    /* If ALPN not configured, just ignore the extension */
+    if( ssl->alpn_list == NULL )
+        return( 0 );
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     */
+
+    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
+    if( len < 4 )
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+    list_len = ( buf[0] << 8 ) | buf[1];
+    if( list_len != len - 2 )
+        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+    /*
+     * Use our order of preference
+     */
+    start = buf + 2;
+    end = buf + len;
+    for( ours = ssl->alpn_list; *ours != NULL; ours++ )
+    {
+        ours_len = strlen( *ours );
+        for( theirs = start; theirs != end; theirs += cur_len )
+        {
+            /* If the list is well formed, we should get equality first */
+            if( theirs > end )
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+            cur_len = *theirs++;
+
+            /* Empty strings MUST NOT be included */
+            if( cur_len == 0 )
+                return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+            if( cur_len == ours_len &&
+                memcmp( theirs, *ours, cur_len ) == 0 )
+            {
+                ssl->alpn_chosen = *ours;
+                return( 0 );
+            }
+        }
+    }
+
+    /* If we get there, no match was found */
+    ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
+                            SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL );
+    return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
+}
+#endif /* POLARSSL_SSL_ALPN */
+
+/*
+ * Auxiliary functions for ServerHello parsing and related actions
+ */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+/*
+ * Return 1 if the given EC key uses the given curve, 0 otherwise
+ */
+#if defined(POLARSSL_ECDSA_C)
+static int ssl_key_matches_curves( pk_context *pk,
+                                   const ecp_curve_info **curves )
+{
+    const ecp_curve_info **crv = curves;
+    ecp_group_id grp_id = pk_ec( *pk )->grp.id;
+
+    while( *crv != NULL )
+    {
+        if( (*crv)->grp_id == grp_id )
+            return( 1 );
+        crv++;
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_ECDSA_C */
+
+/*
+ * Try picking a certificate for this ciphersuite,
+ * return 0 on success and -1 on failure.
+ */
+static int ssl_pick_cert( ssl_context *ssl,
+                          const ssl_ciphersuite_t * ciphersuite_info )
+{
+    ssl_key_cert *cur, *list;
+    pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
+
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    if( ssl->handshake->sni_key_cert != NULL )
+        list = ssl->handshake->sni_key_cert;
+    else
+#endif
+        list = ssl->handshake->key_cert;
+
+    if( pk_alg == POLARSSL_PK_NONE )
+        return( 0 );
+
+    for( cur = list; cur != NULL; cur = cur->next )
+    {
+        if( ! pk_can_do( cur->key, pk_alg ) )
+            continue;
+
+        /*
+         * This avoids sending the client a cert it'll reject based on
+         * keyUsage or other extensions.
+         *
+         * It also allows the user to provision different certificates for
+         * different uses based on keyUsage, eg if they want to avoid signing
+         * and decrypting with the same RSA key.
+         */
+        if( ssl_check_cert_usage( cur->cert, ciphersuite_info,
+                                  SSL_IS_SERVER ) != 0 )
+        {
+            continue;
+        }
+
+#if defined(POLARSSL_ECDSA_C)
+        if( pk_alg == POLARSSL_PK_ECDSA )
+        {
+            if( ssl_key_matches_curves( cur->key, ssl->handshake->curves ) )
+                break;
+        }
+        else
+#endif
+            break;
+    }
+
+    if( cur == NULL )
+        return( -1 );
+
+    ssl->handshake->key_cert = cur;
+    return( 0 );
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+/*
+ * Check if a given ciphersuite is suitable for use with our config/keys/etc
+ * Sets ciphersuite_info only if the suite matches.
+ */
+static int ssl_ciphersuite_match( ssl_context *ssl, int suite_id,
+                                  const ssl_ciphersuite_t **ciphersuite_info )
+{
+    const ssl_ciphersuite_t *suite_info;
+
+    suite_info = ssl_ciphersuite_from_id( suite_id );
+    if( suite_info == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", suite_id ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    if( suite_info->min_minor_ver > ssl->minor_ver ||
+        suite_info->max_minor_ver < ssl->minor_ver )
+        return( 0 );
+
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+    if( ssl_ciphersuite_uses_ec( suite_info ) &&
+        ( ssl->handshake->curves == NULL ||
+          ssl->handshake->curves[0] == NULL ) )
+        return( 0 );
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    /* If the ciphersuite requires a pre-shared key and we don't
+     * have one, skip it now rather than failing later */
+    if( ssl_ciphersuite_uses_psk( suite_info ) &&
+        ssl->f_psk == NULL &&
+        ( ssl->psk == NULL || ssl->psk_identity == NULL ||
+          ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) )
+        return( 0 );
+#endif
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    /*
+     * Final check: if ciphersuite requires us to have a
+     * certificate/key of a particular type:
+     * - select the appropriate certificate if we have one, or
+     * - try the next ciphersuite if we don't
+     * This must be done last since we modify the key_cert list.
+     */
+    if( ssl_pick_cert( ssl, suite_info ) != 0 )
+        return( 0 );
+#endif
+
+    *ciphersuite_info = suite_info;
+    return( 0 );
+}
+
 #if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
 static int ssl_parse_client_hello_v2( ssl_context *ssl )
 {
@@ -746,7 +934,8 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl )
     if( ssl->minor_ver < ssl->min_minor_ver )
     {
         SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
-                            " [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver,
+                            " [%d:%d] < [%d:%d]",
+                            ssl->major_ver, ssl->minor_ver,
                             ssl->min_major_ver, ssl->min_minor_ver ) );
 
         ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
@@ -821,7 +1010,8 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl )
 
     p = buf + 6 + ciph_len;
     ssl->session_negotiate->length = sess_len;
-    memset( ssl->session_negotiate->id, 0, sizeof( ssl->session_negotiate->id ) );
+    memset( ssl->session_negotiate->id, 0,
+            sizeof( ssl->session_negotiate->id ) );
     memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->length );
 
     p += sess_len;
@@ -851,31 +1041,28 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl )
     }
 
     ciphersuites = ssl->ciphersuite_list[ssl->minor_ver];
+    ciphersuite_info = NULL;
+#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
+    for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
+    {
+        for( i = 0; ciphersuites[i] != 0; i++ )
+#else
     for( i = 0; ciphersuites[i] != 0; i++ )
     {
         for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
+#endif
         {
-            // Only allow non-ECC ciphersuites as we do not have extensions
-            //
-            if( p[0] == 0 && p[1] == 0 &&
-                ( ( ciphersuites[i] >> 8 ) & 0xFF ) == 0 &&
-                p[2] == ( ciphersuites[i] & 0xFF ) )
-            {
-                ciphersuite_info = ssl_ciphersuite_from_id( ciphersuites[i] );
+            if( p[0] != 0 ||
+                p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) ||
+                p[2] != ( ( ciphersuites[i]      ) & 0xFF ) )
+                continue;
 
-                if( ciphersuite_info == NULL )
-                {
-                    SSL_DEBUG_MSG( 1, ( "ciphersuite info for %02x not found",
-                                   ciphersuites[i] ) );
-                    return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
-                }
-
-                if( ciphersuite_info->min_minor_ver > ssl->minor_ver ||
-                    ciphersuite_info->max_minor_ver < ssl->minor_ver )
-                    continue;
+            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
+                                               &ciphersuite_info ) ) != 0 )
+                return( ret );
 
+            if( ciphersuite_info != NULL )
                 goto have_ciphersuite_v2;
-            }
         }
     }
 
@@ -911,69 +1098,6 @@ have_ciphersuite_v2:
 }
 #endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
 
-#if defined(POLARSSL_X509_CRT_PARSE_C)
-#if defined(POLARSSL_ECDSA_C)
-static int ssl_key_matches_curves( pk_context *pk,
-                                   const ecp_curve_info **curves )
-{
-    const ecp_curve_info **crv = curves;
-    ecp_group_id grp_id = pk_ec( *pk )->grp.id;
-
-    while( *crv != NULL )
-    {
-        if( (*crv)->grp_id == grp_id )
-            return( 1 );
-        crv++;
-    }
-
-    return( 0 );
-}
-#endif /* POLARSSL_ECDSA_C */
-
-/*
- * Try picking a certificate for this ciphersuite,
- * return 0 on success and -1 on failure.
- */
-static int ssl_pick_cert( ssl_context *ssl,
-                          const ssl_ciphersuite_t * ciphersuite_info )
-{
-    ssl_key_cert *cur, *list;
-    pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
-
-#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
-    if( ssl->handshake->sni_key_cert != NULL )
-        list = ssl->handshake->sni_key_cert;
-    else
-#endif
-        list = ssl->handshake->key_cert;
-
-    if( pk_alg == POLARSSL_PK_NONE )
-        return( 0 );
-
-    for( cur = list; cur != NULL; cur = cur->next )
-    {
-        if( ! pk_can_do( cur->key, pk_alg ) )
-            continue;
-
-#if defined(POLARSSL_ECDSA_C)
-        if( pk_alg == POLARSSL_PK_ECDSA )
-        {
-            if( ssl_key_matches_curves( cur->key, ssl->handshake->curves ) )
-                break;
-        }
-        else
-#endif
-            break;
-    }
-
-    if( cur == NULL )
-        return( -1 );
-
-    ssl->handshake->key_cert = cur;
-    return( 0 );
-}
-#endif /* POLARSSL_X509_CRT_PARSE_C */
-
 static int ssl_parse_client_hello( ssl_context *ssl )
 {
     int ret;
@@ -1014,15 +1138,20 @@ static int ssl_parse_client_hello( ssl_context *ssl )
                    buf[1], buf[2] ) );
 
     /*
-     * SSLv3 Client Hello
+     * SSLv3/TLS Client Hello
      *
      * Record layer:
      *     0  .   0   message type
      *     1  .   2   protocol version
      *     3  .   4   message length
      */
+
+    /* According to RFC 5246 Appendix E.1, the version here is typically
+     * "{03,00}, the lowest version number supported by the client, [or] the
+     * value of ClientHello.client_version", so the only meaningful check here
+     * is the major version shouldn't be less than 3 */
     if( buf[0] != SSL_MSG_HANDSHAKE ||
-        buf[1] != SSL_MAJOR_VERSION_3 )
+        buf[1] < SSL_MAJOR_VERSION_3 )
     {
         SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
@@ -1030,7 +1159,7 @@ static int ssl_parse_client_hello( ssl_context *ssl )
 
     n = ( buf[3] << 8 ) | buf[4];
 
-    if( n < 45 || n > 2048 )
+    if( n < 45 || n > SSL_MAX_CONTENT_LEN )
     {
         SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
@@ -1061,8 +1190,9 @@ static int ssl_parse_client_hello( ssl_context *ssl )
      *    38  .  38   session id length
      *    39  . 38+x  session id
      *   39+x . 40+x  ciphersuitelist length
-     *   41+x .  ..   ciphersuitelist
-     *    ..  .  ..   compression alg.
+     *   41+x . 40+y  ciphersuitelist
+     *   41+y . 41+y  compression alg length
+     *   42+y . 41+z  compression algs
      *    ..  .  ..   extensions
      */
     SSL_DEBUG_BUF( 4, "record contents", buf, n );
@@ -1077,21 +1207,24 @@ static int ssl_parse_client_hello( ssl_context *ssl )
     /*
      * Check the handshake type and protocol version
      */
-    if( buf[0] != SSL_HS_CLIENT_HELLO ||
-        buf[4] != SSL_MAJOR_VERSION_3 )
+    if( buf[0] != SSL_HS_CLIENT_HELLO )
     {
         SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
     }
 
-    ssl->major_ver = SSL_MAJOR_VERSION_3;
-    ssl->minor_ver = ( buf[5] <= ssl->max_minor_ver )
-                     ? buf[5]  : ssl->max_minor_ver;
+    ssl->major_ver = buf[4];
+    ssl->minor_ver = buf[5];
 
-    if( ssl->minor_ver < ssl->min_minor_ver )
+    ssl->handshake->max_major_ver = ssl->major_ver;
+    ssl->handshake->max_minor_ver = ssl->minor_ver;
+
+    if( ssl->major_ver < ssl->min_major_ver ||
+        ssl->minor_ver < ssl->min_minor_ver )
     {
         SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
-                            " [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver,
+                            " [%d:%d] < [%d:%d]",
+                            ssl->major_ver, ssl->minor_ver,
                             ssl->min_major_ver, ssl->min_minor_ver ) );
 
         ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
@@ -1100,8 +1233,13 @@ static int ssl_parse_client_hello( ssl_context *ssl )
         return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
     }
 
-    ssl->handshake->max_major_ver = buf[4];
-    ssl->handshake->max_minor_ver = buf[5];
+    if( ssl->major_ver > ssl->max_major_ver )
+    {
+        ssl->major_ver = ssl->max_major_ver;
+        ssl->minor_ver = ssl->max_minor_ver;
+    }
+    else if( ssl->minor_ver > ssl->max_minor_ver )
+        ssl->minor_ver = ssl->max_minor_ver;
 
     memcpy( ssl->handshake->randbytes, buf + 6, 32 );
 
@@ -1119,7 +1257,7 @@ static int ssl_parse_client_hello( ssl_context *ssl )
      */
     sess_len = buf[38];
 
-    if( sess_len > 32 )
+    if( sess_len > 32 || sess_len > n - 42 )
     {
         SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
@@ -1137,7 +1275,7 @@ static int ssl_parse_client_hello( ssl_context *ssl )
     ciph_len = ( buf[39 + sess_len] << 8 )
              | ( buf[40 + sess_len]      );
 
-    if( ciph_len < 2 || ciph_len > 256 || ( ciph_len % 2 ) != 0 )
+    if( ciph_len < 2 || ( ciph_len % 2 ) != 0 || ciph_len > n - 42 - sess_len )
     {
         SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
@@ -1148,7 +1286,8 @@ static int ssl_parse_client_hello( ssl_context *ssl )
      */
     comp_len = buf[41 + sess_len + ciph_len];
 
-    if( comp_len < 1 || comp_len > 16 )
+    if( comp_len < 1 || comp_len > 16 ||
+        comp_len > n - 42 - sess_len - ciph_len )
     {
         SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
@@ -1312,6 +1451,16 @@ static int ssl_parse_client_hello( ssl_context *ssl )
             break;
 #endif /* POLARSSL_SSL_SESSION_TICKETS */
 
+#if defined(POLARSSL_SSL_ALPN)
+        case TLS_EXT_ALPN:
+            SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
+
+            ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size );
+            if( ret != 0 )
+                return( ret );
+            break;
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+
         default:
             SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
                            ext_id ) );
@@ -1372,58 +1521,27 @@ static int ssl_parse_client_hello( ssl_context *ssl )
      * and certificate from the SNI callback triggered by the SNI extension.)
      */
     ciphersuites = ssl->ciphersuite_list[ssl->minor_ver];
+    ciphersuite_info = NULL;
+#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
+    for( j = 0, p = buf + 41 + sess_len; j < ciph_len; j += 2, p += 2 )
+    {
+        for( i = 0; ciphersuites[i] != 0; i++ )
+#else
     for( i = 0; ciphersuites[i] != 0; i++ )
     {
-        for( j = 0, p = buf + 41 + sess_len; j < ciph_len;
-            j += 2, p += 2 )
-        {
-            if( p[0] == ( ( ciphersuites[i] >> 8 ) & 0xFF ) &&
-                p[1] == ( ( ciphersuites[i]      ) & 0xFF ) )
-            {
-                ciphersuite_info = ssl_ciphersuite_from_id( ciphersuites[i] );
-
-                if( ciphersuite_info == NULL )
-                {
-                    SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found",
-                                   ciphersuites[i] ) );
-                    return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
-                }
-
-                if( ciphersuite_info->min_minor_ver > ssl->minor_ver ||
-                    ciphersuite_info->max_minor_ver < ssl->minor_ver )
-                    continue;
-
-#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
-                if( ssl_ciphersuite_uses_ec( ciphersuite_info ) &&
-                    ( ssl->handshake->curves == NULL ||
-                      ssl->handshake->curves[0] == NULL ) )
-                    continue;
-#endif
-
-#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
-                /* If the ciphersuite requires a pre-shared key and we don't
-                 * have one, skip it now rather than failing later */
-                if( ssl_ciphersuite_uses_psk( ciphersuite_info ) &&
-                    ssl->f_psk == NULL &&
-                    ( ssl->psk == NULL || ssl->psk_identity == NULL ||
-                      ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) )
-                    continue;
+        for( j = 0, p = buf + 41 + sess_len; j < ciph_len; j += 2, p += 2 )
 #endif
+        {
+            if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) ||
+                p[1] != ( ( ciphersuites[i]      ) & 0xFF ) )
+                continue;
 
-#if defined(POLARSSL_X509_CRT_PARSE_C)
-                /*
-                 * Final check: if ciphersuite requires us to have a
-                 * certificate/key of a particular type:
-                 * - select the appropriate certificate if we have one, or
-                 * - try the next ciphersuite if we don't
-                 * This must be done last since we modify the key_cert list.
-                 */
-                if( ssl_pick_cert( ssl, ciphersuite_info ) != 0 )
-                    continue;
-#endif
+            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
+                                               &ciphersuite_info ) ) != 0 )
+                return( ret );
 
+            if( ciphersuite_info != NULL )
                 goto have_ciphersuite;
-            }
         }
     }
 
@@ -1583,6 +1701,42 @@ static void ssl_write_supported_point_formats_ext( ssl_context *ssl,
 }
 #endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
 
+#if defined(POLARSSL_SSL_ALPN )
+static void ssl_write_alpn_ext( ssl_context *ssl,
+                                unsigned char *buf, size_t *olen )
+{
+    if( ssl->alpn_chosen == NULL )
+    {
+        *olen = 0;
+        return;
+    }
+
+    SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) );
+
+    /*
+     * 0 . 1    ext identifier
+     * 2 . 3    ext length
+     * 4 . 5    protocol list length
+     * 6 . 6    protocol name length
+     * 7 . 7+n  protocol name
+     */
+    buf[0] = (unsigned char)( ( TLS_EXT_ALPN >> 8 ) & 0xFF );
+    buf[1] = (unsigned char)( ( TLS_EXT_ALPN      ) & 0xFF );
+
+    *olen = 7 + strlen( ssl->alpn_chosen );
+
+    buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
+    buf[3] = (unsigned char)( ( ( *olen - 4 )      ) & 0xFF );
+
+    buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
+    buf[5] = (unsigned char)( ( ( *olen - 6 )      ) & 0xFF );
+
+    buf[6] = (unsigned char)( ( ( *olen - 7 )      ) & 0xFF );
+
+    memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 );
+}
+#endif /* POLARSSL_ECDH_C || POLARSSL_ECDSA_C */
+
 static int ssl_write_server_hello( ssl_context *ssl )
 {
 #if defined(POLARSSL_HAVE_TIME)
@@ -1594,6 +1748,12 @@ static int ssl_write_server_hello( ssl_context *ssl )
 
     SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
 
+    if( ssl->f_rng == NULL )
+    {
+        SSL_DEBUG_MSG( 1, ( "no RNG provided") );
+        return( POLARSSL_ERR_SSL_NO_RNG );
+    }
+
     /*
      *     0  .   0   handshake type
      *     1  .   3   handshake length
@@ -1623,7 +1783,7 @@ static int ssl_write_server_hello( ssl_context *ssl )
         return( ret );
 
     p += 4;
-#endif
+#endif /* POLARSSL_HAVE_TIME */
 
     if( ( ret = ssl->f_rng( ssl->p_rng, p, 28 ) ) != 0 )
         return( ret );
@@ -1645,6 +1805,7 @@ static int ssl_write_server_hello( ssl_context *ssl )
         ssl->f_get_cache != NULL &&
         ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) == 0 )
     {
+        SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) );
         ssl->handshake->resume = 1;
     }
 
@@ -1742,11 +1903,19 @@ static int ssl_write_server_hello( ssl_context *ssl )
     ext_len += olen;
 #endif
 
+#if defined(POLARSSL_SSL_ALPN)
+    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
     SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) );
 
-    *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
-    p += ext_len;
+    if( ext_len > 0 )
+    {
+        *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+        *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
+        p += ext_len;
+    }
 
     ssl->out_msglen  = p - buf;
     ssl->out_msgtype = SSL_MSG_HANDSHAKE;
@@ -1765,12 +1934,12 @@ static int ssl_write_server_hello( ssl_context *ssl )
     !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 static int ssl_write_certificate_request( ssl_context *ssl )
 {
-    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
 
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
     {
@@ -1779,8 +1948,8 @@ static int ssl_write_certificate_request( ssl_context *ssl )
         return( 0 );
     }
 
-    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
-    return( ret );
+    SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
 }
 #else
 static int ssl_write_certificate_request( ssl_context *ssl )
@@ -1797,6 +1966,7 @@ static int ssl_write_certificate_request( ssl_context *ssl )
     ssl->state++;
 
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
         ssl->authmode == SSL_VERIFY_NONE )
@@ -1811,7 +1981,7 @@ static int ssl_write_certificate_request( ssl_context *ssl )
      *     4  .   4   cert type count
      *     5  .. m-1  cert types
      *     m  .. m+1  sig alg length (TLS 1.2 only)
-     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only) 
+     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only)
      *     n  .. n+1  length of all DNs
      *    n+2 .. n+3  length of DN 1
      *    n+4 .. ...  Distinguished Name #1
@@ -1894,7 +2064,7 @@ static int ssl_write_certificate_request( ssl_context *ssl )
     crt = ssl->ca_chain;
 
     total_dn_size = 0;
-    while( crt != NULL )
+    while( crt != NULL && crt->version != 0 )
     {
         if( p - buf > 4096 )
             break;
@@ -1925,7 +2095,33 @@ static int ssl_write_certificate_request( ssl_context *ssl )
 }
 #endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED &&
           !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED &&
-          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
+          !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+static int ssl_get_ecdh_params_from_cert( ssl_context *ssl )
+{
+    int ret;
+
+    if( ! pk_can_do( ssl_own_key( ssl ), POLARSSL_PK_ECKEY ) )
+    {
+        SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
+        return( POLARSSL_ERR_SSL_PK_TYPE_MISMATCH );
+    }
+
+    if( ( ret = ecdh_get_params( &ssl->handshake->ecdh_ctx,
+                                 pk_ec( *ssl_own_key( ssl ) ),
+                                 POLARSSL_ECDH_OURS ) ) != 0 )
+    {
+        SSL_DEBUG_RET( 1, ( "ecdh_get_params" ), ret );
+        return( ret );
+    }
+
+    return( 0 );
+}
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 
 static int ssl_write_server_key_exchange( ssl_context *ssl )
 {
@@ -1948,6 +2144,9 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
 
     SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
 
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED) ||                           \
+    defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED) ||                           \
+    defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK )
@@ -1956,6 +2155,20 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
         ssl->state++;
         return( 0 );
     }
+#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
+    {
+        ssl_get_ecdh_params_from_cert( ssl );
+
+        SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
+        ssl->state++;
+        return( 0 );
+    }
+#endif
 
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED) ||                       \
     defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
@@ -1993,9 +2206,8 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
         }
 
         if( ( ret = dhm_make_params( &ssl->handshake->dhm_ctx,
-                                      (int) mpi_size( &ssl->handshake->dhm_ctx.P ),
-                                      p,
-                                      &len, ssl->f_rng, ssl->p_rng ) ) != 0 )
+                        (int) mpi_size( &ssl->handshake->dhm_ctx.P ),
+                        p, &len, ssl->f_rng, ssl->p_rng ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_make_params", ret );
             return( ret );
@@ -2015,10 +2227,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
           POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
@@ -2031,16 +2240,36 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
          *     ECPoint      public;
          * } ServerECDHParams;
          */
+        const ecp_curve_info **curve = NULL;
+#if defined(POLARSSL_SSL_SET_CURVES)
+        const ecp_group_id *gid;
+
+        /* Match our preference list against the offered curves */
+        for( gid = ssl->curve_list; *gid != POLARSSL_ECP_DP_NONE; gid++ )
+            for( curve = ssl->handshake->curves; *curve != NULL; curve++ )
+                if( (*curve)->grp_id == *gid )
+                    goto curve_matching_done;
+
+curve_matching_done:
+#else
+        curve = ssl->handshake->curves;
+#endif
+
+        if( *curve == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) );
+            return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
+        }
+
+        SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) );
+
         if( ( ret = ecp_use_known_dp( &ssl->handshake->ecdh_ctx.grp,
-                                   ssl->handshake->curves[0]->grp_id ) ) != 0 )
+                                       (*curve)->grp_id ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "ecp_use_known_dp", ret );
             return( ret );
         }
 
-        SSL_DEBUG_MSG( 2, ( "ECDH curve size: %d",
-                            (int) ssl->handshake->ecdh_ctx.grp.nbits ) );
-
         if( ( ret = ecdh_make_params( &ssl->handshake->ecdh_ctx, &len,
                                       p, SSL_MAX_CONTENT_LEN - n,
                                       ssl->f_rng, ssl->p_rng ) ) != 0 )
@@ -2057,9 +2286,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
 
         SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
     }
-#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
-          POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED */
 
 #if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
     defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
@@ -2084,14 +2311,14 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
             if( md_alg == POLARSSL_MD_NONE )
             {
                 SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+                return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
             }
         }
         else
-#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 #if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
     defined(POLARSSL_SSL_PROTO_TLS1_1)
-        if ( ciphersuite_info->key_exchange ==
+        if( ciphersuite_info->key_exchange ==
                   POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
         {
             md_alg = POLARSSL_MD_SHA1;
@@ -2112,6 +2339,9 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
             md5_context md5;
             sha1_context sha1;
 
+            md5_init(  &md5  );
+            sha1_init( &sha1 );
+
             /*
              * digitally-signed struct {
              *     opaque md5_hash[16];
@@ -2136,6 +2366,9 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
             sha1_finish( &sha1, hash + 16 );
 
             hashlen = 36;
+
+            md5_free(  &md5  );
+            sha1_free( &sha1 );
         }
         else
 #endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 || \
@@ -2145,6 +2378,9 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
         if( md_alg != POLARSSL_MD_NONE )
         {
             md_context_t ctx;
+            const md_info_t *md_info = md_info_from_type( md_alg );
+
+            md_init( &ctx );
 
             /* Info from md_alg will be used instead */
             hashlen = 0;
@@ -2156,7 +2392,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
              *     ServerDHParams params;
              * };
              */
-            if( ( ret = md_init_ctx( &ctx, md_info_from_type(md_alg) ) ) != 0 )
+            if( ( ret = md_init_ctx( &ctx, md_info ) ) != 0 )
             {
                 SSL_DEBUG_RET( 1, "md_init_ctx", ret );
                 return( ret );
@@ -2166,20 +2402,14 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
             md_update( &ctx, ssl->handshake->randbytes, 64 );
             md_update( &ctx, dig_signed, dig_signed_len );
             md_finish( &ctx, hash );
-
-            if( ( ret = md_free_ctx( &ctx ) ) != 0 )
-            {
-                SSL_DEBUG_RET( 1, "md_free_ctx", ret );
-                return( ret );
-            }
-
+            md_free( &ctx );
         }
         else
 #endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
           POLARSSL_SSL_PROTO_TLS1_2 */
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
         SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
@@ -2285,19 +2515,20 @@ static int ssl_parse_client_dh_public( ssl_context *ssl, unsigned char **p,
     n = ( (*p)[0] << 8 ) | (*p)[1];
     *p += 2;
 
-    if( n < 1 || n > ssl->handshake->dhm_ctx.len || *p + n > end )
+    if( *p + n > end )
     {
         SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
     }
 
-    if( ( ret = dhm_read_public( &ssl->handshake->dhm_ctx,
-                                  *p, n ) ) != 0 )
+    if( ( ret = dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 )
     {
         SSL_DEBUG_RET( 1, "dhm_read_public", ret );
         return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
     }
 
+    *p += n;
+
     SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
 
     return( ret );
@@ -2346,7 +2577,7 @@ static int ssl_parse_encrypted_pms( ssl_context *ssl,
 
     ret = pk_decrypt( ssl_own_key( ssl ), p, len,
                       pms, &ssl->handshake->pmslen,
-                      sizeof(ssl->handshake->premaster),
+                      sizeof( ssl->handshake->premaster ) - pms_offset,
                       ssl->f_rng, ssl->p_rng );
 
     if( ret != 0 || ssl->handshake->pmslen != 48 ||
@@ -2408,11 +2639,10 @@ static int ssl_parse_client_psk_identity( ssl_context *ssl, unsigned char **p,
 
     if( ssl->f_psk != NULL )
     {
-        if( ( ret != ssl->f_psk( ssl->p_psk, ssl, *p, n ) ) != 0 )
+        if( ssl->f_psk( ssl->p_psk, ssl, *p, n ) != 0 )
             ret = POLARSSL_ERR_SSL_UNKNOWN_IDENTITY;
     }
-
-    if( ret == 0 )
+    else
     {
         /* Identity is not a big secret since clients send it in the clear,
          * but treat it carefully anyway, just in case */
@@ -2437,9 +2667,8 @@ static int ssl_parse_client_psk_identity( ssl_context *ssl, unsigned char **p,
     }
 
     *p += n;
-    ret = 0;
 
-    return( ret );
+    return( 0 );
 }
 #endif /* POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED */
 
@@ -2474,7 +2703,7 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_RSA )
     {
         unsigned char *p = ssl->in_msg + 4;
-        unsigned char *end = ssl->in_msg + ssl->in_msglen;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
 
         if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 )
         {
@@ -2482,7 +2711,13 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
             return( ret );
         }
 
-        ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
+        if( p != end )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+
+        ssl->handshake->pmslen = POLARSSL_PREMASTER_SIZE;
 
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
                                       ssl->handshake->premaster,
@@ -2498,21 +2733,16 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
     else
 #endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
-        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDH_ECDSA )
     {
-        size_t n = ssl->in_msg[3];
-
-        if( n < 1 || n > mpi_size( &ssl->handshake->ecdh_ctx.grp.P ) * 2 + 2 ||
-            n + 4 != ssl->in_hslen )
-        {
-            SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-        }
-
         if( ( ret = ecdh_read_public( &ssl->handshake->ecdh_ctx,
-                                       ssl->in_msg + 4, n ) ) != 0 )
+                        ssl->in_msg + 4, ssl->in_hslen - 4 ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "ecdh_read_public", ret );
             return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
@@ -2534,12 +2764,14 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
     }
     else
 #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+          POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 #if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK )
     {
         unsigned char *p = ssl->in_msg + 4;
-        unsigned char *end = ssl->in_msg + ssl->in_msglen;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
 
         if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
         {
@@ -2547,6 +2779,12 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
             return( ret );
         }
 
+        if( p != end )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+
         if( ( ret = ssl_psk_derive_premaster( ssl,
                         ciphersuite_info->key_exchange ) ) != 0 )
         {
@@ -2560,7 +2798,7 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK )
     {
         unsigned char *p = ssl->in_msg + 4;
-        unsigned char *end = ssl->in_msg + ssl->in_msglen;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
 
         if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
         {
@@ -2587,7 +2825,7 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
         unsigned char *p = ssl->in_msg + 4;
-        unsigned char *end = ssl->in_msg + ssl->in_msglen;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
 
         if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
         {
@@ -2600,6 +2838,12 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
             return( ret );
         }
 
+        if( p != end )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
+
         if( ( ret = ssl_psk_derive_premaster( ssl,
                         ciphersuite_info->key_exchange ) ) != 0 )
         {
@@ -2613,7 +2857,7 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
     {
         unsigned char *p = ssl->in_msg + 4;
-        unsigned char *end = ssl->in_msg + ssl->in_msglen;
+        unsigned char *end = ssl->in_msg + ssl->in_hslen;
 
         if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
         {
@@ -2644,10 +2888,10 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
     {
         if( ( ret = ssl_parse_encrypted_pms( ssl,
                                              ssl->in_msg + 4,
-                                             ssl->in_msg + ssl->in_msglen,
+                                             ssl->in_msg + ssl->in_hslen,
                                              0 ) ) != 0 )
         {
-            SSL_DEBUG_RET( 1, ( "ssl_parse_parse_ecrypted_pms_secret" ), ret );
+            SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret );
             return( ret );
         }
     }
@@ -2655,7 +2899,7 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
 #endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
     if( ( ret = ssl_derive_keys( ssl ) ) != 0 )
@@ -2677,12 +2921,12 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl )
     !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 static int ssl_parse_certificate_verify( ssl_context *ssl )
 {
-    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
 
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
@@ -2691,8 +2935,8 @@ static int ssl_parse_certificate_verify( ssl_context *ssl )
         return( 0 );
     }
 
-    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
-    return( ret );
+    SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
 }
 #else
 static int ssl_parse_certificate_verify( ssl_context *ssl )
@@ -2711,6 +2955,7 @@ static int ssl_parse_certificate_verify( ssl_context *ssl )
     SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
 
     if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK ||
         ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
@@ -2775,7 +3020,8 @@ static int ssl_parse_certificate_verify( ssl_context *ssl )
         }
     }
     else
-#endif
+#endif /* POLARSSL_SSL_PROTO_SSL3 || POLARSSL_SSL_PROTO_TLS1 ||
+          POLARSSL_SSL_PROTO_TLS1_1 */
 #if defined(POLARSSL_SSL_PROTO_TLS1_2)
     if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
     {
@@ -2820,7 +3066,7 @@ static int ssl_parse_certificate_verify( ssl_context *ssl )
 #endif /* POLARSSL_SSL_PROTO_TLS1_2 */
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
     sig_len = ( ssl->in_msg[4 + sa_len] << 8 ) | ssl->in_msg[5 + sa_len];
@@ -2886,15 +3132,18 @@ static int ssl_write_new_session_ticket( ssl_context *ssl )
 
     ssl->out_msglen = 10 + tlen;
 
+    /*
+     * Morally equivalent to updating ssl->state, but NewSessionTicket and
+     * ChangeCipherSpec share the same state.
+     */
+    ssl->handshake->new_session_ticket = 0;
+
     if( ( ret = ssl_write_record( ssl ) ) != 0 )
     {
         SSL_DEBUG_RET( 1, "ssl_write_record", ret );
         return( ret );
     }
 
-    /* No need to remember writing a NewSessionTicket any more */
-    ssl->handshake->new_session_ticket = 0;
-
     SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) );
 
     return( 0 );
@@ -3017,4 +3266,4 @@ int ssl_handshake_server_step( ssl_context *ssl )
 
     return( ret );
 }
-#endif
+#endif /* POLARSSL_SSL_SRV_C */
index bca55da973c3250698ecc453db27d6b3e1f80cf8..8613b8d0e3d9b2c5b372fc3f51692076cc44661b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  SSLv3/TLSv1 shared functions
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  http://www.ietf.org/rfc/rfc4346.txt
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_SSL_TLS_C)
 
 #include "polarssl/debug.h"
 #include "polarssl/ssl.h"
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_X509_CRT_PARSE_C) && \
+    defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+#include "polarssl/oid.h"
+#endif
+
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #define strcasecmp _stricmp
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 #if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
 /*
  * Convert max_fragment_length codes to length.
@@ -87,8 +101,8 @@ static int ssl_session_copy( ssl_session *dst, const ssl_session *src )
 
         x509_crt_init( dst->peer_cert );
 
-        if( ( ret = x509_crt_parse( dst->peer_cert, src->peer_cert->raw.p,
-                                    src->peer_cert->raw.len ) != 0 ) )
+        if( ( ret = x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p,
+                                        src->peer_cert->raw.len ) ) != 0 )
         {
             polarssl_free( dst->peer_cert );
             dst->peer_cert = NULL;
@@ -112,19 +126,19 @@ static int ssl_session_copy( ssl_session *dst, const ssl_session *src )
 }
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
-int (*ssl_hw_record_init)(ssl_context *ssl,
-                       const unsigned char *key_enc, const unsigned char *key_dec,
-                       size_t keylen,
-                       const unsigned char *iv_enc,  const unsigned char *iv_dec,
-                       size_t ivlen,
-                       const unsigned char *mac_enc, const unsigned char *mac_dec,
-                       size_t maclen) = NULL;
-int (*ssl_hw_record_activate)(ssl_context *ssl, int direction) = NULL;
-int (*ssl_hw_record_reset)(ssl_context *ssl) = NULL;
-int (*ssl_hw_record_write)(ssl_context *ssl) = NULL;
-int (*ssl_hw_record_read)(ssl_context *ssl) = NULL;
-int (*ssl_hw_record_finish)(ssl_context *ssl) = NULL;
-#endif
+int (*ssl_hw_record_init)( ssl_context *ssl,
+                     const unsigned char *key_enc, const unsigned char *key_dec,
+                     size_t keylen,
+                     const unsigned char *iv_enc,  const unsigned char *iv_dec,
+                     size_t ivlen,
+                     const unsigned char *mac_enc, const unsigned char *mac_dec,
+                     size_t maclen ) = NULL;
+int (*ssl_hw_record_activate)( ssl_context *ssl, int direction) = NULL;
+int (*ssl_hw_record_reset)( ssl_context *ssl ) = NULL;
+int (*ssl_hw_record_write)( ssl_context *ssl ) = NULL;
+int (*ssl_hw_record_read)( ssl_context *ssl ) = NULL;
+int (*ssl_hw_record_finish)( ssl_context *ssl ) = NULL;
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
 
 /*
  * Key material generation
@@ -142,6 +156,9 @@ static int ssl3_prf( const unsigned char *secret, size_t slen,
     unsigned char sha1sum[20];
     ((void)label);
 
+    md5_init(  &md5  );
+    sha1_init( &sha1 );
+
     /*
      *  SSLv3:
      *    block =
@@ -166,11 +183,11 @@ static int ssl3_prf( const unsigned char *secret, size_t slen,
         md5_finish( &md5, dstbuf + i * 16 );
     }
 
-    memset( &md5,  0, sizeof( md5  ) );
-    memset( &sha1, 0, sizeof( sha1 ) );
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
 
-    memset( padding, 0, sizeof( padding ) );
-    memset( sha1sum, 0, sizeof( sha1sum ) );
+    polarssl_zeroize( padding, sizeof( padding ) );
+    polarssl_zeroize( sha1sum, sizeof( sha1sum ) );
 
     return( 0 );
 }
@@ -232,8 +249,8 @@ static int tls1_prf( const unsigned char *secret, size_t slen,
             dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
     }
 
-    memset( tmp, 0, sizeof( tmp ) );
-    memset( h_i, 0, sizeof( h_i ) );
+    polarssl_zeroize( tmp, sizeof( tmp ) );
+    polarssl_zeroize( h_i, sizeof( h_i ) );
 
     return( 0 );
 }
@@ -275,8 +292,8 @@ static int tls_prf_sha256( const unsigned char *secret, size_t slen,
             dstbuf[i + j]  = h_i[j];
     }
 
-    memset( tmp, 0, sizeof( tmp ) );
-    memset( h_i, 0, sizeof( h_i ) );
+    polarssl_zeroize( tmp, sizeof( tmp ) );
+    polarssl_zeroize( h_i, sizeof( h_i ) );
 
     return( 0 );
 }
@@ -317,44 +334,44 @@ static int tls_prf_sha384( const unsigned char *secret, size_t slen,
             dstbuf[i + j]  = h_i[j];
     }
 
-    memset( tmp, 0, sizeof( tmp ) );
-    memset( h_i, 0, sizeof( h_i ) );
+    polarssl_zeroize( tmp, sizeof( tmp ) );
+    polarssl_zeroize( h_i, sizeof( h_i ) );
 
     return( 0 );
 }
 #endif /* POLARSSL_SHA512_C */
 #endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
-static void ssl_update_checksum_start(ssl_context *, const unsigned char *, size_t);
+static void ssl_update_checksum_start( ssl_context *, const unsigned char *, size_t );
 
 #if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
     defined(POLARSSL_SSL_PROTO_TLS1_1)
-static void ssl_update_checksum_md5sha1(ssl_context *, const unsigned char *, size_t);
+static void ssl_update_checksum_md5sha1( ssl_context *, const unsigned char *, size_t );
 #endif
 
 #if defined(POLARSSL_SSL_PROTO_SSL3)
-static void ssl_calc_verify_ssl(ssl_context *,unsigned char *);
-static void ssl_calc_finished_ssl(ssl_context *,unsigned char *,int);
+static void ssl_calc_verify_ssl( ssl_context *, unsigned char * );
+static void ssl_calc_finished_ssl( ssl_context *, unsigned char *, int );
 #endif
 
 #if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
-static void ssl_calc_verify_tls(ssl_context *,unsigned char *);
-static void ssl_calc_finished_tls(ssl_context *,unsigned char *,int);
+static void ssl_calc_verify_tls( ssl_context *, unsigned char * );
+static void ssl_calc_finished_tls( ssl_context *, unsigned char *, int );
 #endif
 
 #if defined(POLARSSL_SSL_PROTO_TLS1_2)
 #if defined(POLARSSL_SHA256_C)
-static void ssl_update_checksum_sha256(ssl_context *, const unsigned char *, size_t);
-static void ssl_calc_verify_tls_sha256(ssl_context *,unsigned char *);
-static void ssl_calc_finished_tls_sha256(ssl_context *,unsigned char *,int);
+static void ssl_update_checksum_sha256( ssl_context *, const unsigned char *, size_t );
+static void ssl_calc_verify_tls_sha256( ssl_context *,unsigned char * );
+static void ssl_calc_finished_tls_sha256( ssl_context *,unsigned char *, int );
 #endif
 
 #if defined(POLARSSL_SHA512_C)
-static void ssl_update_checksum_sha384(ssl_context *, const unsigned char *, size_t);
-static void ssl_calc_verify_tls_sha384(ssl_context *,unsigned char *);
-static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int);
-#endif
+static void ssl_update_checksum_sha384( ssl_context *, const unsigned char *, size_t );
+static void ssl_calc_verify_tls_sha384( ssl_context *, unsigned char * );
+static void ssl_calc_finished_tls_sha384( ssl_context *, unsigned char *, int );
 #endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
 
 int ssl_derive_keys( ssl_context *ssl )
 {
@@ -432,10 +449,10 @@ int ssl_derive_keys( ssl_context *ssl )
     }
     else
 #endif
-#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
     /*
@@ -457,7 +474,7 @@ int ssl_derive_keys( ssl_context *ssl )
                             "master secret",
                             handshake->randbytes, 64, session->master, 48 );
 
-        memset( handshake->premaster, 0, sizeof( handshake->premaster ) );
+        polarssl_zeroize( handshake->premaster, sizeof(handshake->premaster) );
     }
     else
         SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
@@ -468,7 +485,7 @@ int ssl_derive_keys( ssl_context *ssl )
     memcpy( tmp, handshake->randbytes, 64 );
     memcpy( handshake->randbytes, tmp + 32, 32 );
     memcpy( handshake->randbytes + 32, tmp, 32 );
-    memset( tmp, 0, sizeof( tmp ) );
+    polarssl_zeroize( tmp, sizeof( tmp ) );
 
     /*
      *  SSLv3:
@@ -491,63 +508,87 @@ int ssl_derive_keys( ssl_context *ssl )
     SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 );
     SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
 
-    memset( handshake->randbytes, 0, sizeof( handshake->randbytes ) );
+    polarssl_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) );
 
     /*
      * Determine the appropriate key, IV and MAC length.
      */
 
-    if( cipher_info->mode == POLARSSL_MODE_GCM )
+    transform->keylen = cipher_info->key_length / 8;
+
+    if( cipher_info->mode == POLARSSL_MODE_GCM ||
+        cipher_info->mode == POLARSSL_MODE_CCM )
     {
-        transform->keylen = cipher_info->key_length;
-        transform->keylen /= 8;
-        transform->minlen = 1;
+        transform->maclen = 0;
+
         transform->ivlen = 12;
         transform->fixed_ivlen = 4;
-        transform->maclen = 0;
+
+        /* Minimum length is expicit IV + tag */
+        transform->minlen = transform->ivlen - transform->fixed_ivlen
+                            + ( transform->ciphersuite_info->flags &
+                                POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16 );
     }
     else
     {
-        if( md_info->type != POLARSSL_MD_NONE )
-        {
-            int ret;
-
-            if( ( ret = md_init_ctx( &transform->md_ctx_enc, md_info ) ) != 0 )
-            {
-                SSL_DEBUG_RET( 1, "md_init_ctx", ret );
-                return( ret );
-            }
+        int ret;
 
-            if( ( ret = md_init_ctx( &transform->md_ctx_dec, md_info ) ) != 0 )
-            {
-                SSL_DEBUG_RET( 1, "md_init_ctx", ret );
-                return( ret );
-            }
+        /* Initialize HMAC contexts */
+        if( ( ret = md_init_ctx( &transform->md_ctx_enc, md_info ) ) != 0 ||
+            ( ret = md_init_ctx( &transform->md_ctx_dec, md_info ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "md_init_ctx", ret );
+            return( ret );
+        }
 
-            transform->maclen = md_get_size( md_info );
+        /* Get MAC length */
+        transform->maclen = md_get_size( md_info );
 
 #if defined(POLARSSL_SSL_TRUNCATED_HMAC)
-            /*
-             * If HMAC is to be truncated, we shall keep the leftmost bytes,
-             * (rfc 6066 page 13 or rfc 2104 section 4),
-             * so we only need to adjust the length here.
-             */
-            if( session->trunc_hmac == SSL_TRUNC_HMAC_ENABLED )
-                transform->maclen = SSL_TRUNCATED_HMAC_LEN;
+        /*
+         * If HMAC is to be truncated, we shall keep the leftmost bytes,
+         * (rfc 6066 page 13 or rfc 2104 section 4),
+         * so we only need to adjust the length here.
+         */
+        if( session->trunc_hmac == SSL_TRUNC_HMAC_ENABLED )
+            transform->maclen = SSL_TRUNCATED_HMAC_LEN;
 #endif /* POLARSSL_SSL_TRUNCATED_HMAC */
-        }
 
-        transform->keylen = cipher_info->key_length;
-        transform->keylen /= 8;
+        /* IV length */
         transform->ivlen = cipher_info->iv_size;
 
-        transform->minlen = transform->keylen;
-        if( transform->minlen < transform->maclen )
+        /* Minimum length */
+        if( cipher_info->mode == POLARSSL_MODE_STREAM )
+            transform->minlen = transform->maclen;
+        else
         {
-            if( cipher_info->mode == POLARSSL_MODE_STREAM )
-                transform->minlen = transform->maclen;
+            /*
+             * GenericBlockCipher:
+             * first multiple of blocklen greater than maclen
+             * + IV except for SSL3 and TLS 1.0
+             */
+            transform->minlen = transform->maclen
+                                + cipher_info->block_size
+                                - transform->maclen % cipher_info->block_size;
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1)
+            if( ssl->minor_ver == SSL_MINOR_VERSION_0 ||
+                ssl->minor_ver == SSL_MINOR_VERSION_1 )
+                ; /* No need to adjust minlen */
             else
-                transform->minlen += transform->keylen;
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
+            if( ssl->minor_ver == SSL_MINOR_VERSION_2 ||
+                ssl->minor_ver == SSL_MINOR_VERSION_3 )
+            {
+                transform->minlen += transform->ivlen;
+            }
+            else
+#endif
+            {
+                SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+            }
         }
     }
 
@@ -596,11 +637,17 @@ int ssl_derive_keys( ssl_context *ssl )
 #if defined(POLARSSL_SSL_PROTO_SSL3)
     if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
     {
+        if( transform->maclen > sizeof transform->mac_enc )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
+        }
+
         memcpy( transform->mac_enc, mac_enc, transform->maclen );
         memcpy( transform->mac_dec, mac_dec, transform->maclen );
     }
     else
-#endif
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 #if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
     defined(POLARSSL_SSL_PROTO_TLS1_2)
     if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
@@ -612,11 +659,11 @@ int ssl_derive_keys( ssl_context *ssl )
 #endif
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
-    if( ssl_hw_record_init != NULL)
+    if( ssl_hw_record_init != NULL )
     {
         int ret = 0;
 
@@ -629,10 +676,10 @@ int ssl_derive_keys( ssl_context *ssl )
                                         transform->maclen ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "ssl_hw_record_init", ret );
-            return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+            return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED );
         }
     }
-#endif
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
 
     if( ( ret = cipher_init_ctx( &transform->cipher_ctx_enc,
                                  cipher_info ) ) != 0 )
@@ -683,7 +730,7 @@ int ssl_derive_keys( ssl_context *ssl )
     }
 #endif /* POLARSSL_CIPHER_MODE_CBC */
 
-    memset( keyblk, 0, sizeof( keyblk ) );
+    polarssl_zeroize( keyblk, sizeof( keyblk ) );
 
 #if defined(POLARSSL_ZLIB_SUPPORT)
     // Initialize compression
@@ -707,7 +754,8 @@ int ssl_derive_keys( ssl_context *ssl )
         memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) );
         memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) );
 
-        if( deflateInit( &transform->ctx_deflate, Z_DEFAULT_COMPRESSION ) != Z_OK ||
+        if( deflateInit( &transform->ctx_deflate,
+                         Z_DEFAULT_COMPRESSION )   != Z_OK ||
             inflateInit( &transform->ctx_inflate ) != Z_OK )
         {
             SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) );
@@ -760,9 +808,12 @@ void ssl_calc_verify_ssl( ssl_context *ssl, unsigned char hash[36] )
     SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
     SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
 
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
+
     return;
 }
-#endif
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 
 #if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1)
 void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] )
@@ -781,6 +832,9 @@ void ssl_calc_verify_tls( ssl_context *ssl, unsigned char hash[36] )
     SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
     SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
 
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
+
     return;
 }
 #endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 */
@@ -799,6 +853,8 @@ void ssl_calc_verify_tls_sha256( ssl_context *ssl, unsigned char hash[32] )
     SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 );
     SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
 
+    sha256_free( &sha256 );
+
     return;
 }
 #endif /* POLARSSL_SHA256_C */
@@ -816,6 +872,8 @@ void ssl_calc_verify_tls_sha384( ssl_context *ssl, unsigned char hash[48] )
     SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 );
     SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
 
+    sha512_free( &sha512 );
+
     return;
 }
 #endif /* POLARSSL_SHA512_C */
@@ -863,19 +921,18 @@ int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex )
     if( key_ex == POLARSSL_KEY_EXCHANGE_DHE_PSK )
     {
         int ret;
-        size_t len = ssl->handshake->dhm_ctx.len;
-
-        if( end - p < 2 + (int) len )
-            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+        size_t len = end - ( p + 2 );
 
-        *(p++) = (unsigned char)( len >> 8 );
-        *(p++) = (unsigned char)( len );
+        /* Write length only when we know the actual value */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                      p, &len, ssl->f_rng, ssl->p_rng ) ) != 0 )
+                                      p + 2, &len,
+                                      ssl->f_rng, ssl->p_rng ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( ret );
         }
+        *(p++) = (unsigned char)( len >> 8 );
+        *(p++) = (unsigned char)( len );
         p += len;
 
         SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K  );
@@ -889,7 +946,7 @@ int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex )
         size_t zlen;
 
         if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen,
-                                       p + 2, end - (p + 2),
+                                       p + 2, end - ( p + 2 ),
                                        ssl->f_rng, ssl->p_rng ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret );
@@ -906,10 +963,13 @@ int ssl_psk_derive_premaster( ssl_context *ssl, key_exchange_type_t key_ex )
 #endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
     /* opaque psk<0..2^16-1>; */
+    if( end - p < 2 + (int) ssl->psk_len )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
     *(p++) = (unsigned char)( ssl->psk_len >> 8 );
     *(p++) = (unsigned char)( ssl->psk_len      );
     memcpy( p, ssl->psk, ssl->psk_len );
@@ -941,6 +1001,8 @@ static void ssl_mac( md_context_t *md_ctx, unsigned char *secret,
         padlen = 40;
     else if( md_type == POLARSSL_MD_SHA256 )
         padlen = 32;
+    else if( md_type == POLARSSL_MD_SHA384 )
+        padlen = 16;
 
     memcpy( header, ctr, 8 );
     header[ 8] = (unsigned char)  type;
@@ -970,17 +1032,19 @@ static void ssl_mac( md_context_t *md_ctx, unsigned char *secret,
 static int ssl_encrypt_buf( ssl_context *ssl )
 {
     size_t i;
+    const cipher_mode_t mode = cipher_get_cipher_mode(
+                                        &ssl->transform_out->cipher_ctx_enc );
 
     SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
 
     /*
-     * Add MAC before encrypt, except for GCM
+     * Add MAC before encrypt, except for AEAD modes
      */
 #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) ||     \
     ( defined(POLARSSL_CIPHER_MODE_CBC) &&                                  \
       ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
-    if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode !=
-                                                        POLARSSL_MODE_GCM )
+    if( mode != POLARSSL_MODE_GCM &&
+        mode != POLARSSL_MODE_CCM )
     {
 #if defined(POLARSSL_SSL_PROTO_SSL3)
         if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
@@ -1007,7 +1071,7 @@ static int ssl_encrypt_buf( ssl_context *ssl )
 #endif
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
         SSL_DEBUG_BUF( 4, "computed mac",
@@ -1016,14 +1080,13 @@ static int ssl_encrypt_buf( ssl_context *ssl )
 
         ssl->out_msglen += ssl->transform_out->maclen;
     }
-#endif /* GCM not the only option */
+#endif /* AEAD not the only option */
 
     /*
      * Encrypt
      */
 #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
-    if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode ==
-                                                        POLARSSL_MODE_STREAM )
+    if( mode == POLARSSL_MODE_STREAM )
     {
         int ret;
         size_t olen = 0;
@@ -1035,61 +1098,34 @@ static int ssl_encrypt_buf( ssl_context *ssl )
         SSL_DEBUG_BUF( 4, "before encrypt: output payload",
                        ssl->out_msg, ssl->out_msglen );
 
-        if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_reset", ret );
-            return( ret );
-        }
-
-        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
+        if( ( ret = cipher_crypt( &ssl->transform_out->cipher_ctx_enc,
                                    ssl->transform_out->iv_enc,
-                                   ssl->transform_out->ivlen ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
-            return( ret );
-        }
-
-        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
-                                   ssl->out_msg, ssl->out_msglen, ssl->out_msg,
-                                   &olen ) ) != 0 )
+                                   ssl->transform_out->ivlen,
+                                   ssl->out_msg, ssl->out_msglen,
+                                   ssl->out_msg, &olen ) ) != 0 )
         {
-            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            SSL_DEBUG_RET( 1, "cipher_crypt", ret );
             return( ret );
         }
 
         if( ssl->out_msglen != olen )
         {
-            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
-                                ssl->out_msglen, olen ) );
-            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
-        }
-
-        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
-                                   ssl->out_msg + olen, &olen ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_finish", ret );
-            return( ret );
-        }
-
-        if( 0 != olen )
-        {
-            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
-                                0, olen ) );
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
             return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
     }
     else
 #endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */
-#if defined(POLARSSL_GCM_C)
-    if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode ==
-                                                        POLARSSL_MODE_GCM )
+#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C)
+    if( mode == POLARSSL_MODE_GCM ||
+        mode == POLARSSL_MODE_CCM )
     {
-        size_t enc_msglen, olen, totlen;
+        int ret;
+        size_t enc_msglen, olen;
         unsigned char *enc_msg;
         unsigned char add_data[13];
-        int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
-
-        enc_msglen = ssl->out_msglen;
+        unsigned char taglen = ssl->transform_out->ciphersuite_info->flags &
+                               POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16;
 
         memcpy( add_data, ssl->out_ctr, 8 );
         add_data[8]  = ssl->out_msgtype;
@@ -1105,8 +1141,8 @@ static int ssl_encrypt_buf( ssl_context *ssl )
          * Generate IV
          */
         ret = ssl->f_rng( ssl->p_rng,
-                    ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
-                    ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+                ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
+                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
         if( ret != 0 )
             return( ret );
 
@@ -1115,7 +1151,7 @@ static int ssl_encrypt_buf( ssl_context *ssl )
                 ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
 
         SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv,
-                       ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
 
         /*
          * Fix pointer positions and message length with added IV
@@ -1133,62 +1169,35 @@ static int ssl_encrypt_buf( ssl_context *ssl )
                        ssl->out_msg, ssl->out_msglen );
 
         /*
-         * Encrypt
+         * Encrypt and authenticate
          */
-        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
-                                    ssl->transform_out->iv_enc,
-                                    ssl->transform_out->ivlen ) ) != 0 ||
-            ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
-        {
-            return( ret );
-        }
-
-        if( ( ret = cipher_update_ad( &ssl->transform_out->cipher_ctx_enc,
-                                      add_data, 13 ) ) != 0 )
-        {
-            return( ret );
-        }
-
-        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
-                                   enc_msg, enc_msglen,
-                                   enc_msg, &olen ) ) != 0 )
-        {
-            return( ret );
-        }
-        totlen = olen;
-
-        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
-                                   enc_msg + olen, &olen ) ) != 0 )
+        if( ( ret = cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc,
+                                         ssl->transform_out->iv_enc,
+                                         ssl->transform_out->ivlen,
+                                         add_data, 13,
+                                         enc_msg, enc_msglen,
+                                         enc_msg, &olen,
+                                         enc_msg + enc_msglen, taglen ) ) != 0 )
         {
+            SSL_DEBUG_RET( 1, "cipher_auth_encrypt", ret );
             return( ret );
         }
-        totlen += olen;
 
-        if( totlen != enc_msglen )
+        if( olen != enc_msglen )
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( -1 );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
-        /*
-         * Authenticate
-         */
-        ssl->out_msglen += 16;
-
-        if( ( ret = cipher_write_tag( &ssl->transform_out->cipher_ctx_enc,
-                                      enc_msg + enc_msglen, 16 ) ) != 0 )
-        {
-            return( ret );
-        }
+        ssl->out_msglen += taglen;
 
-        SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, 16 );
+        SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen );
     }
     else
-#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_GCM_C || POLARSSL_CCM_C */
 #if defined(POLARSSL_CIPHER_MODE_CBC) &&                                    \
     ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) )
-    if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode ==
-                                                        POLARSSL_MODE_CBC )
+    if( mode == POLARSSL_MODE_CBC )
     {
         int ret;
         unsigned char *enc_msg;
@@ -1236,46 +1245,25 @@ static int ssl_encrypt_buf( ssl_context *ssl )
 
         SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
                             "including %d bytes of IV and %d bytes of padding",
-                       ssl->out_msglen, ssl->transform_out->ivlen, padlen + 1 ) );
+                            ssl->out_msglen, ssl->transform_out->ivlen,
+                            padlen + 1 ) );
 
         SSL_DEBUG_BUF( 4, "before encrypt: output payload",
                        ssl->out_iv, ssl->out_msglen );
 
-        if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_reset", ret );
-            return( ret );
-        }
-
-        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
+        if( ( ret = cipher_crypt( &ssl->transform_out->cipher_ctx_enc,
                                    ssl->transform_out->iv_enc,
-                                   ssl->transform_out->ivlen ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
-            return( ret );
-        }
-
-        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
-                                   enc_msg, enc_msglen, enc_msg,
-                                   &olen ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_update", ret );
-            return( ret );
-        }
-
-        enc_msglen -= olen;
-
-        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
-                                   enc_msg + olen, &olen ) ) != 0 )
+                                   ssl->transform_out->ivlen,
+                                   enc_msg, enc_msglen,
+                                   enc_msg, &olen ) ) != 0 )
         {
-            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            SSL_DEBUG_RET( 1, "cipher_crypt", ret );
             return( ret );
         }
 
         if( enc_msglen != olen )
         {
-            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
-                                enc_msglen, olen ) );
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
             return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
@@ -1296,13 +1284,20 @@ static int ssl_encrypt_buf( ssl_context *ssl )
           ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
     for( i = 8; i > 0; i-- )
         if( ++ssl->out_ctr[i - 1] != 0 )
             break;
 
+    /* The loops goes to its end iff the counter is wrapping */
+    if( i == 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
+        return( POLARSSL_ERR_SSL_COUNTER_WRAPPING );
+    }
+
     SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
 
     return( 0 );
@@ -1312,8 +1307,14 @@ static int ssl_encrypt_buf( ssl_context *ssl )
 
 static int ssl_decrypt_buf( ssl_context *ssl )
 {
-    size_t i, padlen = 0, correct = 1;
-    unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
+    size_t i;
+    const cipher_mode_t mode = cipher_get_cipher_mode(
+                                        &ssl->transform_in->cipher_ctx_dec );
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) ||     \
+    ( defined(POLARSSL_CIPHER_MODE_CBC) &&                                  \
+      ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
+    size_t padlen = 0, correct = 1;
+#endif
 
     SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
 
@@ -1325,72 +1326,54 @@ static int ssl_decrypt_buf( ssl_context *ssl )
     }
 
 #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
-    if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode ==
-                                                       POLARSSL_MODE_STREAM )
+    if( mode == POLARSSL_MODE_STREAM )
     {
         int ret;
         size_t olen = 0;
 
         padlen = 0;
 
-        if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_reset", ret );
-            return( ret );
-        }
-
-        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
+        if( ( ret = cipher_crypt( &ssl->transform_in->cipher_ctx_dec,
                                    ssl->transform_in->iv_dec,
-                                   ssl->transform_in->ivlen ) ) != 0 )
+                                   ssl->transform_in->ivlen,
+                                   ssl->in_msg, ssl->in_msglen,
+                                   ssl->in_msg, &olen ) ) != 0 )
         {
-            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
-            return( ret );
-        }
-
-        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
-                                   ssl->in_msg, ssl->in_msglen, ssl->in_msg,
-                                   &olen ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            SSL_DEBUG_RET( 1, "cipher_crypt", ret );
             return( ret );
         }
 
         if( ssl->in_msglen != olen )
         {
-            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
-            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
-        }
-
-        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
-                                   ssl->in_msg + olen, &olen ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_finish", ret );
-            return( ret );
-        }
-
-        if( 0 != olen )
-        {
-            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
             return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
     }
     else
 #endif /* POLARSSL_ARC4_C || POLARSSL_CIPHER_NULL_CIPHER */
-#if defined(POLARSSL_GCM_C)
-    if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode ==
-                                                       POLARSSL_MODE_GCM )
+#if defined(POLARSSL_GCM_C) || defined(POLARSSL_CCM_C)
+    if( mode == POLARSSL_MODE_GCM ||
+        mode == POLARSSL_MODE_CCM )
     {
+        int ret;
+        size_t dec_msglen, olen;
         unsigned char *dec_msg;
         unsigned char *dec_msg_result;
-        size_t dec_msglen, olen, totlen;
         unsigned char add_data[13];
-        int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+        unsigned char taglen = ssl->transform_in->ciphersuite_info->flags &
+                               POLARSSL_CIPHERSUITE_SHORT_TAG ? 8 : 16;
+        unsigned char explicit_iv_len =  ssl->transform_in->ivlen -
+                                         ssl->transform_in->fixed_ivlen;
 
-        padlen = 0;
+        if( ssl->in_msglen < explicit_iv_len + taglen )
+        {
+            SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
+                                "+ taglen (%d)", ssl->in_msglen,
+                                explicit_iv_len, taglen ) );
+            return( POLARSSL_ERR_SSL_INVALID_MAC );
+        }
+        dec_msglen = ssl->in_msglen - explicit_iv_len - taglen;
 
-        dec_msglen = ssl->in_msglen - ( ssl->transform_in->ivlen -
-                                        ssl->transform_in->fixed_ivlen );
-        dec_msglen -= 16;
         dec_msg = ssl->in_msg;
         dec_msg_result = ssl->in_msg;
         ssl->in_msglen = dec_msglen;
@@ -1411,63 +1394,38 @@ static int ssl_decrypt_buf( ssl_context *ssl )
 
         SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec,
                                      ssl->transform_in->ivlen );
-        SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 );
+        SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen );
 
         /*
-         * Decrypt
+         * Decrypt and authenticate
          */
-        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
-                                    ssl->transform_in->iv_dec,
-                                    ssl->transform_in->ivlen ) ) != 0 ||
-            ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
+        if( ( ret = cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec,
+                                         ssl->transform_in->iv_dec,
+                                         ssl->transform_in->ivlen,
+                                         add_data, 13,
+                                         dec_msg, dec_msglen,
+                                         dec_msg_result, &olen,
+                                         dec_msg + dec_msglen, taglen ) ) != 0 )
         {
-            return( ret );
-        }
+            SSL_DEBUG_RET( 1, "cipher_auth_decrypt", ret );
 
-        if( ( ret = cipher_update_ad( &ssl->transform_in->cipher_ctx_dec,
-                                      add_data, 13 ) ) != 0 )
-        {
-            return( ret );
-        }
-
-        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
-                                   dec_msg, dec_msglen,
-                                   dec_msg_result, &olen ) ) != 0 )
-        {
-            return( ret );
-        }
-        totlen = olen;
+            if( ret == POLARSSL_ERR_CIPHER_AUTH_FAILED )
+                return( POLARSSL_ERR_SSL_INVALID_MAC );
 
-        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
-                                   dec_msg_result + olen, &olen ) ) != 0 )
-        {
             return( ret );
         }
-        totlen += olen;
 
-        if( totlen != dec_msglen )
+        if( olen != dec_msglen )
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( -1 );
-        }
-
-        /*
-         * Authenticate
-         */
-        if( ( ret = cipher_check_tag( &ssl->transform_in->cipher_ctx_dec,
-                                      dec_msg + dec_msglen, 16 ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_check_tag", ret );
-            return( POLARSSL_ERR_SSL_INVALID_MAC );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
-
     }
     else
-#endif /* POLARSSL_GCM_C */
+#endif /* POLARSSL_GCM_C || POLARSSL_CCM_C */
 #if defined(POLARSSL_CIPHER_MODE_CBC) &&                                    \
     ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) )
-    if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode ==
-                                                       POLARSSL_MODE_CBC )
+    if( mode == POLARSSL_MODE_CBC )
     {
         /*
          * Decrypt and check the padding
@@ -1497,8 +1455,10 @@ static int ssl_decrypt_buf( ssl_context *ssl )
         if( ssl->in_msglen < minlen + ssl->transform_in->ivlen ||
             ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 )
         {
-            SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) + 1 ) ( + expl IV )",
-                           ssl->in_msglen, ssl->transform_in->ivlen, ssl->transform_in->maclen ) );
+            SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) "
+                                "+ 1 ) ( + expl IV )", ssl->in_msglen,
+                                ssl->transform_in->ivlen,
+                                ssl->transform_in->maclen ) );
             return( POLARSSL_ERR_SSL_INVALID_MAC );
         }
 
@@ -1520,39 +1480,19 @@ static int ssl_decrypt_buf( ssl_context *ssl )
         }
 #endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */
 
-        if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_reset", ret );
-            return( ret );
-        }
-
-        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
+        if( ( ret = cipher_crypt( &ssl->transform_in->cipher_ctx_dec,
                                    ssl->transform_in->iv_dec,
-                                   ssl->transform_in->ivlen ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
-            return( ret );
-        }
-
-        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
-                                   dec_msg, dec_msglen, dec_msg_result,
-                                   &olen ) ) != 0 )
-        {
-            SSL_DEBUG_RET( 1, "cipher_update", ret );
-            return( ret );
-        }
-
-        dec_msglen -= olen;
-        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
-                                   dec_msg_result + olen, &olen ) ) != 0 )
+                                   ssl->transform_in->ivlen,
+                                   dec_msg, dec_msglen,
+                                   dec_msg_result, &olen ) ) != 0 )
         {
-            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            SSL_DEBUG_RET( 1, "cipher_crypt", ret );
             return( ret );
         }
 
         if( dec_msglen != olen )
         {
-            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
             return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
@@ -1594,7 +1534,7 @@ static int ssl_decrypt_buf( ssl_context *ssl )
             }
         }
         else
-#endif
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 #if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
     defined(POLARSSL_SSL_PROTO_TLS1_2)
         if( ssl->minor_ver > SSL_MINOR_VERSION_0 )
@@ -1606,6 +1546,22 @@ static int ssl_decrypt_buf( ssl_context *ssl )
             size_t pad_count = 0, real_count = 1;
             size_t padding_idx = ssl->in_msglen - padlen - 1;
 
+            /*
+             * Padding is guaranteed to be incorrect if:
+             *   1. padlen >= ssl->in_msglen
+             *
+             *   2. padding_idx >= SSL_MAX_CONTENT_LEN +
+             *                     ssl->transform_in->maclen
+             *
+             * In both cases we reset padding_idx to a safe value (0) to
+             * prevent out-of-buffer reads.
+             */
+            correct &= ( ssl->in_msglen >= padlen + 1 );
+            correct &= ( padding_idx < SSL_MAX_CONTENT_LEN +
+                                       ssl->transform_in->maclen );
+
+            padding_idx *= correct;
+
             for( i = 1; i <= 256; i++ )
             {
                 real_count &= ( i <= padlen );
@@ -1616,7 +1572,7 @@ static int ssl_decrypt_buf( ssl_context *ssl )
             correct &= ( pad_count == padlen ); /* Only 1 on correct padding */
 
 #if defined(POLARSSL_SSL_DEBUG_ALL)
-            if( padlen > 0 && correct == 0)
+            if( padlen > 0 && correct == 0 )
                 SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
 #endif
             padlen &= correct * 0x1FF;
@@ -1626,7 +1582,7 @@ static int ssl_decrypt_buf( ssl_context *ssl )
           POLARSSL_SSL_PROTO_TLS1_2 */
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
     }
     else
@@ -1634,21 +1590,23 @@ static int ssl_decrypt_buf( ssl_context *ssl )
           ( POLARSSL_AES_C || POLARSSL_CAMELLIA_C ) */
     {
         SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+        return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
     }
 
     SSL_DEBUG_BUF( 4, "raw buffer after decryption",
                    ssl->in_msg, ssl->in_msglen );
 
     /*
-     * Always compute the MAC (RFC4346, CBCTIME), except for GCM of course
+     * Always compute the MAC (RFC4346, CBCTIME), except for AEAD of course
      */
 #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) ||     \
     ( defined(POLARSSL_CIPHER_MODE_CBC) &&                                  \
       ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
-    if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode !=
-                                                        POLARSSL_MODE_GCM )
+    if( mode != POLARSSL_MODE_GCM &&
+        mode != POLARSSL_MODE_CCM )
     {
+        unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
+
         ssl->in_msglen -= ( ssl->transform_in->maclen + padlen );
 
         ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
@@ -1674,7 +1632,7 @@ static int ssl_decrypt_buf( ssl_context *ssl )
              * Process MAC and always update for padlen afterwards to make
              * total time independent of padlen
              *
-             * extra_run compensates MAC check for padlen 
+             * extra_run compensates MAC check for padlen
              *
              * Known timing attacks:
              *  - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
@@ -1704,7 +1662,7 @@ static int ssl_decrypt_buf( ssl_context *ssl )
               POLARSSL_SSL_PROTO_TLS1_2 */
         {
             SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
         }
 
         SSL_DEBUG_BUF( 4, "message  mac", tmp, ssl->transform_in->maclen );
@@ -1726,7 +1684,7 @@ static int ssl_decrypt_buf( ssl_context *ssl )
         if( correct == 0 )
             return( POLARSSL_ERR_SSL_INVALID_MAC );
     }
-#endif /* GCM not the only option */
+#endif /* AEAD not the only option */
 
     if( ssl->in_msglen == 0 )
     {
@@ -1750,6 +1708,13 @@ static int ssl_decrypt_buf( ssl_context *ssl )
         if( ++ssl->in_ctr[i - 1] != 0 )
             break;
 
+    /* The loops goes to its end iff the counter is wrapping */
+    if( i == 0 )
+    {
+        SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) );
+        return( POLARSSL_ERR_SSL_COUNTER_WRAPPING );
+    }
+
     SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
 
     return( 0 );
@@ -1791,7 +1756,8 @@ static int ssl_compress_buf( ssl_context *ssl )
         return( POLARSSL_ERR_SSL_COMPRESSION_FAILED );
     }
 
-    ssl->out_msglen = SSL_BUFFER_LEN - ssl->transform_out->ctx_deflate.avail_out;
+    ssl->out_msglen = SSL_BUFFER_LEN -
+                      ssl->transform_out->ctx_deflate.avail_out;
 
     SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
                    ssl->out_msglen ) );
@@ -1836,7 +1802,8 @@ static int ssl_decompress_buf( ssl_context *ssl )
         return( POLARSSL_ERR_SSL_COMPRESSION_FAILED );
     }
 
-    ssl->in_msglen = SSL_MAX_CONTENT_LEN - ssl->transform_in->ctx_inflate.avail_out;
+    ssl->in_msglen = SSL_MAX_CONTENT_LEN -
+                     ssl->transform_in->ctx_inflate.avail_out;
 
     SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
                    ssl->in_msglen ) );
@@ -1860,6 +1827,12 @@ int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
 
     SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
 
+    if( nb_want > SSL_BUFFER_LEN - 8 )
+    {
+        SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
     while( ssl->in_left < nb_want )
     {
         len = nb_want - ssl->in_left;
@@ -1949,7 +1922,7 @@ int ssl_write_record( ssl_context *ssl )
 #endif /*POLARSSL_ZLIB_SUPPORT */
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
-    if( ssl_hw_record_write != NULL)
+    if( ssl_hw_record_write != NULL )
     {
         SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_write()" ) );
 
@@ -1957,13 +1930,13 @@ int ssl_write_record( ssl_context *ssl )
         if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH )
         {
             SSL_DEBUG_RET( 1, "ssl_hw_record_write", ret );
-            return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+            return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED );
         }
 
         if( ret == 0 )
             done = 1;
     }
-#endif
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
     if( !done )
     {
         ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
@@ -2013,9 +1986,6 @@ int ssl_read_record( ssl_context *ssl )
 
     SSL_DEBUG_MSG( 2, ( "=> read record" ) );
 
-    SSL_DEBUG_BUF( 4, "input record from network",
-                   ssl->in_hdr, 5 + ssl->in_msglen );
-
     if( ssl->in_hslen != 0 &&
         ssl->in_hslen < ssl->in_msglen )
     {
@@ -2046,7 +2016,8 @@ int ssl_read_record( ssl_context *ssl )
             return( POLARSSL_ERR_SSL_INVALID_RECORD );
         }
 
-        ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+        if( ssl->state != SSL_HANDSHAKE_OVER )
+            ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
 
         return( 0 );
     }
@@ -2082,13 +2053,20 @@ int ssl_read_record( ssl_context *ssl )
         return( POLARSSL_ERR_SSL_INVALID_RECORD );
     }
 
+    /* Sanity check (outer boundaries) */
+    if( ssl->in_msglen < 1 || ssl->in_msglen > SSL_BUFFER_LEN - 13 )
+    {
+        SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+        return( POLARSSL_ERR_SSL_INVALID_RECORD );
+    }
+
     /*
-     * Make sure the message length is acceptable
+     * Make sure the message length is acceptable for the current transform
+     * and protocol version.
      */
     if( ssl->transform_in == NULL )
     {
-        if( ssl->in_msglen < 1 ||
-            ssl->in_msglen > SSL_MAX_CONTENT_LEN )
+        if( ssl->in_msglen > SSL_MAX_CONTENT_LEN )
         {
             SSL_DEBUG_MSG( 1, ( "bad message length" ) );
             return( POLARSSL_ERR_SSL_INVALID_RECORD );
@@ -2117,7 +2095,8 @@ int ssl_read_record( ssl_context *ssl )
          * TLS encrypted messages can have up to 256 bytes of padding
          */
         if( ssl->minor_ver >= SSL_MINOR_VERSION_1 &&
-            ssl->in_msglen > ssl->transform_in->minlen + SSL_MAX_CONTENT_LEN + 256 )
+            ssl->in_msglen > ssl->transform_in->minlen +
+                             SSL_MAX_CONTENT_LEN + 256 )
         {
             SSL_DEBUG_MSG( 1, ( "bad message length" ) );
             return( POLARSSL_ERR_SSL_INVALID_RECORD );
@@ -2138,7 +2117,7 @@ int ssl_read_record( ssl_context *ssl )
                    ssl->in_hdr, 5 + ssl->in_msglen );
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
-    if( ssl_hw_record_read != NULL)
+    if( ssl_hw_record_read != NULL )
     {
         SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_read()" ) );
 
@@ -2146,13 +2125,13 @@ int ssl_read_record( ssl_context *ssl )
         if( ret != 0 && ret != POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH )
         {
             SSL_DEBUG_RET( 1, "ssl_hw_record_read", ret );
-            return POLARSSL_ERR_SSL_HW_ACCEL_FAILED;
+            return( POLARSSL_ERR_SSL_HW_ACCEL_FAILED );
         }
 
         if( ret == 0 )
             done = 1;
     }
-#endif
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
     if( !done && ssl->transform_in != NULL )
     {
         if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
@@ -2314,13 +2293,15 @@ int ssl_send_alert_message( ssl_context *ssl,
 /*
  * Handshake functions
  */
-#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)       && \
-    !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)   && \
-    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
-    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#if !defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)         && \
+    !defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)     && \
+    !defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)     && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)   && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED)    && \
+    !defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
 int ssl_write_certificate( ssl_context *ssl )
 {
-    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
@@ -2334,13 +2315,12 @@ int ssl_write_certificate( ssl_context *ssl )
         return( 0 );
     }
 
-    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
-    return( ret );
+    SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
 }
 
 int ssl_parse_certificate( ssl_context *ssl )
 {
-    int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
     const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
 
     SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
@@ -2354,8 +2334,8 @@ int ssl_parse_certificate( ssl_context *ssl )
         return( 0 );
     }
 
-    SSL_DEBUG_MSG( 1, ( "should not happen" ) );
-    return( ret );
+    SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
 }
 #else
 int ssl_write_certificate( ssl_context *ssl )
@@ -2429,7 +2409,7 @@ int ssl_write_certificate( ssl_context *ssl )
     while( crt != NULL )
     {
         n = crt->raw.len;
-        if( i + 3 + n > SSL_MAX_CONTENT_LEN )
+        if( n > SSL_MAX_CONTENT_LEN - 3 - i )
         {
             SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
                            i + 3 + n, SSL_MAX_CONTENT_LEN ) );
@@ -2487,7 +2467,8 @@ int ssl_parse_certificate( ssl_context *ssl )
     }
 
     if( ssl->endpoint == SSL_IS_SERVER &&
-        ssl->authmode == SSL_VERIFY_NONE )
+        ( ssl->authmode == SSL_VERIFY_NONE ||
+          ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK ) )
     {
         ssl->session_negotiate->verify_result = BADCERT_SKIP_VERIFY;
         SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
@@ -2621,6 +2602,30 @@ int ssl_parse_certificate( ssl_context *ssl )
 
     SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert );
 
+    /*
+     * On client, make sure the server cert doesn't change during renego to
+     * avoid "triple handshake" attack: https://secure-resumption.com/
+     */
+    if( ssl->endpoint == SSL_IS_CLIENT &&
+        ssl->renegotiation == SSL_RENEGOTIATION )
+    {
+        if( ssl->session->peer_cert == NULL )
+        {
+            SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+
+        if( ssl->session->peer_cert->raw.len !=
+            ssl->session_negotiate->peer_cert->raw.len ||
+            memcmp( ssl->session->peer_cert->raw.p,
+                    ssl->session_negotiate->peer_cert->raw.p,
+                    ssl->session->peer_cert->raw.len ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) );
+            return( POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE );
+        }
+    }
+
     if( ssl->authmode != SSL_VERIFY_NONE )
     {
         if( ssl->ca_chain == NULL )
@@ -2629,13 +2634,46 @@ int ssl_parse_certificate( ssl_context *ssl )
             return( POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED );
         }
 
+        /*
+         * Main check: verify certificate
+         */
         ret = x509_crt_verify( ssl->session_negotiate->peer_cert,
                                ssl->ca_chain, ssl->ca_crl, ssl->peer_cn,
                               &ssl->session_negotiate->verify_result,
                                ssl->f_vrfy, ssl->p_vrfy );
 
         if( ret != 0 )
+        {
             SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
+        }
+
+        /*
+         * Secondary checks: always done, but change 'ret' only if it was 0
+         */
+
+#if defined(POLARSSL_SSL_SET_CURVES)
+        {
+            pk_context *pk = &ssl->session_negotiate->peer_cert->pk;
+
+            /* If certificate uses an EC key, make sure the curve is OK */
+            if( pk_can_do( pk, POLARSSL_PK_ECKEY ) &&
+                ! ssl_curve_is_acceptable( ssl, pk_ec( *pk )->grp.id ) )
+            {
+                SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
+                if( ret == 0 )
+                    ret = POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE;
+            }
+        }
+#endif /* POLARSSL_SSL_SET_CURVES */
+
+        if( ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
+                                  ciphersuite_info,
+                                  ! ssl->endpoint ) != 0 )
+        {
+            SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
+            if( ret == 0 )
+                ret = POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE;
+        }
 
         if( ssl->authmode != SSL_VERIFY_REQUIRED )
             ret = 0;
@@ -2645,9 +2683,13 @@ int ssl_parse_certificate( ssl_context *ssl )
 
     return( ret );
 }
-#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED &&
-          !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED &&
-          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#endif /* !POLARSSL_KEY_EXCHANGE_RSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED
+          !POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED
+          !POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 
 int ssl_write_change_cipher_spec( ssl_context *ssl )
 {
@@ -2726,8 +2768,10 @@ void ssl_optimize_checksum( ssl_context *ssl,
     else
 #endif
 #endif /* POLARSSL_SSL_PROTO_TLS1_2 */
-        /* Should never happen */
+    {
+        SSL_DEBUG_MSG( 1, ( "should never happen" ) );
         return;
+    }
 }
 
 static void ssl_update_checksum_start( ssl_context *ssl,
@@ -2847,12 +2891,12 @@ static void ssl_calc_finished_ssl(
 
     SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 );
 
-    memset(  &md5, 0, sizeof(  md5_context ) );
-    memset( &sha1, 0, sizeof( sha1_context ) );
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
 
-    memset(  padbuf, 0, sizeof(  padbuf ) );
-    memset(  md5sum, 0, sizeof(  md5sum ) );
-    memset( sha1sum, 0, sizeof( sha1sum ) );
+    polarssl_zeroize(  padbuf, sizeof(  padbuf ) );
+    polarssl_zeroize(  md5sum, sizeof(  md5sum ) );
+    polarssl_zeroize( sha1sum, sizeof( sha1sum ) );
 
     SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
@@ -2905,10 +2949,10 @@ static void ssl_calc_finished_tls(
 
     SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
 
-    memset(  &md5, 0, sizeof(  md5_context ) );
-    memset( &sha1, 0, sizeof( sha1_context ) );
+    md5_free(  &md5  );
+    sha1_free( &sha1 );
 
-    memset(  padbuf, 0, sizeof(  padbuf ) );
+    polarssl_zeroize(  padbuf, sizeof(  padbuf ) );
 
     SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
@@ -2954,9 +2998,9 @@ static void ssl_calc_finished_tls_sha256(
 
     SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
 
-    memset( &sha256, 0, sizeof( sha256_context ) );
+    sha256_free( &sha256 );
 
-    memset(  padbuf, 0, sizeof(  padbuf ) );
+    polarssl_zeroize(  padbuf, sizeof(  padbuf ) );
 
     SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
@@ -3001,9 +3045,9 @@ static void ssl_calc_finished_tls_sha384(
 
     SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
 
-    memset( &sha512, 0, sizeof( sha512_context ) );
+    sha512_free( &sha512 );
 
-    memset(  padbuf, 0, sizeof(  padbuf ) );
+    polarssl_zeroize(  padbuf, sizeof( padbuf ) );
 
     SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
@@ -3024,7 +3068,10 @@ void ssl_handshake_wrapup( ssl_context *ssl )
     ssl->handshake = NULL;
 
     if( ssl->renegotiation == SSL_RENEGOTIATION )
+    {
         ssl->renegotiation =  SSL_RENEGOTIATION_DONE;
+        ssl->renego_records_seen = 0;
+    }
 
     /*
      * Switch in our now active transform context
@@ -3105,7 +3152,8 @@ int ssl_write_finished( ssl_context *ssl )
         ssl->state++;
 
     /*
-     * Switch to our negotiated transform and session parameters for outbound data.
+     * Switch to our negotiated transform and session parameters for outbound
+     * data.
      */
     SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) );
     ssl->transform_out = ssl->transform_negotiate;
@@ -3113,7 +3161,7 @@ int ssl_write_finished( ssl_context *ssl )
     memset( ssl->out_ctr, 0, 8 );
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
-    if( ssl_hw_record_activate != NULL)
+    if( ssl_hw_record_activate != NULL )
     {
         if( ( ret = ssl_hw_record_activate( ssl, SSL_CHANNEL_OUTBOUND ) ) != 0 )
         {
@@ -3145,7 +3193,8 @@ int ssl_parse_finished( ssl_context *ssl )
     ssl->handshake->calc_finished( ssl, buf, ssl->endpoint ^ 1 );
 
     /*
-     * Switch to our negotiated transform and session parameters for inbound data.
+     * Switch to our negotiated transform and session parameters for inbound
+     * data.
      */
     SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
     ssl->transform_in = ssl->transform_negotiate;
@@ -3164,7 +3213,7 @@ int ssl_parse_finished( ssl_context *ssl )
         ssl->in_msg = ssl->in_iv;
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
-    if( ssl_hw_record_activate != NULL)
+    if( ssl_hw_record_activate != NULL )
     {
         if( ( ret = ssl_hw_record_activate( ssl, SSL_CHANNEL_INBOUND ) ) != 0 )
         {
@@ -3221,64 +3270,109 @@ int ssl_parse_finished( ssl_context *ssl )
     return( 0 );
 }
 
+static void ssl_handshake_params_init( ssl_handshake_params *handshake )
+{
+    memset( handshake, 0, sizeof( ssl_handshake_params ) );
+
+#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
+    defined(POLARSSL_SSL_PROTO_TLS1_1)
+     md5_init(   &handshake->fin_md5  );
+    sha1_init(   &handshake->fin_sha1 );
+     md5_starts( &handshake->fin_md5  );
+    sha1_starts( &handshake->fin_sha1 );
+#endif
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+#if defined(POLARSSL_SHA256_C)
+    sha256_init(   &handshake->fin_sha256    );
+    sha256_starts( &handshake->fin_sha256, 0 );
+#endif
+#if defined(POLARSSL_SHA512_C)
+    sha512_init(   &handshake->fin_sha512    );
+    sha512_starts( &handshake->fin_sha512, 1 );
+#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+
+    handshake->update_checksum = ssl_update_checksum_start;
+    handshake->sig_alg = SSL_HASH_SHA1;
+
+#if defined(POLARSSL_DHM_C)
+    dhm_init( &handshake->dhm_ctx );
+#endif
+#if defined(POLARSSL_ECDH_C)
+    ecdh_init( &handshake->ecdh_ctx );
+#endif
+}
+
+static void ssl_transform_init( ssl_transform *transform )
+{
+    memset( transform, 0, sizeof(ssl_transform) );
+
+    cipher_init( &transform->cipher_ctx_enc );
+    cipher_init( &transform->cipher_ctx_dec );
+
+    md_init( &transform->md_ctx_enc );
+    md_init( &transform->md_ctx_dec );
+}
+
+void ssl_session_init( ssl_session *session )
+{
+    memset( session, 0, sizeof(ssl_session) );
+}
+
 static int ssl_handshake_init( ssl_context *ssl )
 {
+    /* Clear old handshake information if present */
     if( ssl->transform_negotiate )
         ssl_transform_free( ssl->transform_negotiate );
-    else
+    if( ssl->session_negotiate )
+        ssl_session_free( ssl->session_negotiate );
+    if( ssl->handshake )
+        ssl_handshake_free( ssl->handshake );
+
+    /*
+     * Either the pointers are now NULL or cleared properly and can be freed.
+     * Now allocate missing structures.
+     */
+    if( ssl->transform_negotiate == NULL )
     {
         ssl->transform_negotiate =
             (ssl_transform *) polarssl_malloc( sizeof(ssl_transform) );
     }
 
-    if( ssl->session_negotiate )
-        ssl_session_free( ssl->session_negotiate );
-    else
+    if( ssl->session_negotiate == NULL )
     {
         ssl->session_negotiate =
             (ssl_session *) polarssl_malloc( sizeof(ssl_session) );
     }
 
-    if( ssl->handshake )
-        ssl_handshake_free( ssl->handshake );
-    else
+    if( ssl->handshake == NULL)
     {
         ssl->handshake = (ssl_handshake_params *)
             polarssl_malloc( sizeof(ssl_handshake_params) );
     }
 
+    /* All pointers should exist and can be directly freed without issue */
     if( ssl->handshake == NULL ||
         ssl->transform_negotiate == NULL ||
         ssl->session_negotiate == NULL )
     {
         SSL_DEBUG_MSG( 1, ( "malloc() of ssl sub-contexts failed" ) );
-        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
-    }
 
-    memset( ssl->handshake, 0, sizeof(ssl_handshake_params) );
-    memset( ssl->transform_negotiate, 0, sizeof(ssl_transform) );
-    memset( ssl->session_negotiate, 0, sizeof(ssl_session) );
+        polarssl_free( ssl->handshake );
+        polarssl_free( ssl->transform_negotiate );
+        polarssl_free( ssl->session_negotiate );
 
-#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) || \
-    defined(POLARSSL_SSL_PROTO_TLS1_1)
-     md5_starts( &ssl->handshake->fin_md5 );
-    sha1_starts( &ssl->handshake->fin_sha1 );
-#endif
-#if defined(POLARSSL_SSL_PROTO_TLS1_2)
-#if defined(POLARSSL_SHA256_C)
-    sha256_starts( &ssl->handshake->fin_sha256, 0 );
-#endif
-#if defined(POLARSSL_SHA512_C)
-    sha512_starts( &ssl->handshake->fin_sha512, 1 );
-#endif
-#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+        ssl->handshake = NULL;
+        ssl->transform_negotiate = NULL;
+        ssl->session_negotiate = NULL;
 
-    ssl->handshake->update_checksum = ssl_update_checksum_start;
-    ssl->handshake->sig_alg = SSL_HASH_SHA1;
+        return( POLARSSL_ERR_SSL_MALLOC_FAILED );
+    }
 
-#if defined(POLARSSL_ECDH_C)
-    ecdh_init( &ssl->handshake->ecdh_ctx );
-#endif
+    /* Initialize structures */
+    ssl_session_init( ssl->session_negotiate );
+    ssl_transform_init( ssl->transform_negotiate );
+    ssl_handshake_params_init( ssl->handshake );
 
 #if defined(POLARSSL_X509_CRT_PARSE_C)
     ssl->handshake->key_cert = ssl->key_cert;
@@ -3307,6 +3401,8 @@ int ssl_init( ssl_context *ssl )
 
     ssl_set_ciphersuites( ssl, ssl_list_ciphersuites() );
 
+    ssl->renego_max_records = SSL_RENEGO_MAX_RECORDS_DEFAULT;
+
 #if defined(POLARSSL_DHM_C)
     if( ( ret = mpi_read_string( &ssl->dhm_P, 16,
                                  POLARSSL_DHM_RFC5114_MODP_1024_P) ) != 0 ||
@@ -3340,7 +3436,8 @@ int ssl_init( ssl_context *ssl )
     if( ssl->out_ctr == NULL )
     {
         SSL_DEBUG_MSG( 1, ( "malloc(%d bytes) failed", len ) );
-        polarssl_free( ssl-> in_ctr );
+        polarssl_free( ssl->in_ctr );
+        ssl->in_ctr = NULL;
         return( POLARSSL_ERR_SSL_MALLOC_FAILED );
     }
 
@@ -3351,6 +3448,10 @@ int ssl_init( ssl_context *ssl )
     ssl->ticket_lifetime = SSL_DEFAULT_TICKET_LIFETIME;
 #endif
 
+#if defined(POLARSSL_SSL_SET_CURVES)
+    ssl->curve_list = ecp_grp_id_list( );
+#endif
+
     if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
         return( ret );
 
@@ -3392,11 +3493,13 @@ int ssl_session_reset( ssl_context *ssl )
     ssl->transform_in = NULL;
     ssl->transform_out = NULL;
 
+    ssl->renego_records_seen = 0;
+
     memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
     memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
 
 #if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
-    if( ssl_hw_record_reset != NULL)
+    if( ssl_hw_record_reset != NULL )
     {
         SSL_DEBUG_MSG( 2, ( "going for ssl_hw_record_reset()" ) );
         if( ( ret = ssl_hw_record_reset( ssl ) ) != 0 )
@@ -3421,6 +3524,10 @@ int ssl_session_reset( ssl_context *ssl )
         ssl->session = NULL;
     }
 
+#if defined(POLARSSL_SSL_ALPN)
+    ssl->alpn_chosen = NULL;
+#endif
+
     if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
         return( ret );
 
@@ -3428,6 +3535,14 @@ int ssl_session_reset( ssl_context *ssl )
 }
 
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
+static void ssl_ticket_keys_free( ssl_ticket_keys *tkeys )
+{
+    aes_free( &tkeys->enc );
+    aes_free( &tkeys->dec );
+
+    polarssl_zeroize( tkeys, sizeof(ssl_ticket_keys) );
+}
+
 /*
  * Allocate and initialize ticket keys
  */
@@ -3444,18 +3559,31 @@ static int ssl_ticket_keys_init( ssl_context *ssl )
     if( tkeys == NULL )
         return( POLARSSL_ERR_SSL_MALLOC_FAILED );
 
+    aes_init( &tkeys->enc );
+    aes_init( &tkeys->dec );
+
     if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->key_name, 16 ) ) != 0 )
+    {
+        ssl_ticket_keys_free( tkeys );
+        polarssl_free( tkeys );
         return( ret );
+    }
 
     if( ( ret = ssl->f_rng( ssl->p_rng, buf, 16 ) ) != 0 ||
         ( ret = aes_setkey_enc( &tkeys->enc, buf, 128 ) ) != 0 ||
         ( ret = aes_setkey_dec( &tkeys->dec, buf, 128 ) ) != 0 )
     {
-            return( ret );
+        ssl_ticket_keys_free( tkeys );
+        polarssl_free( tkeys );
+        return( ret );
     }
 
     if( ( ret = ssl->f_rng( ssl->p_rng, tkeys->mac_key, 16 ) ) != 0 )
+    {
+        ssl_ticket_keys_free( tkeys );
+        polarssl_free( tkeys );
         return( ret );
+    }
 
     ssl->ticket_keys = tkeys;
 
@@ -3555,7 +3683,8 @@ void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites )
     ssl->ciphersuite_list[SSL_MINOR_VERSION_3] = ciphersuites;
 }
 
-void ssl_set_ciphersuites_for_version( ssl_context *ssl, const int *ciphersuites,
+void ssl_set_ciphersuites_for_version( ssl_context *ssl,
+                                       const int *ciphersuites,
                                        int major, int minor )
 {
     if( major != SSL_MAJOR_VERSION_3 )
@@ -3583,7 +3712,8 @@ static ssl_key_cert *ssl_add_key_cert( ssl_context *ssl )
     if( ssl->key_cert == NULL )
     {
         ssl->key_cert = key_cert;
-        ssl->handshake->key_cert = key_cert;
+        if( ssl->handshake != NULL )
+            ssl->handshake->key_cert = key_cert;
     }
     else
     {
@@ -3593,7 +3723,7 @@ static ssl_key_cert *ssl_add_key_cert( ssl_context *ssl )
         last->next = key_cert;
     }
 
-    return key_cert;
+    return( key_cert );
 }
 
 void ssl_set_ca_chain( ssl_context *ssl, x509_crt *ca_chain,
@@ -3684,6 +3814,9 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
     if( psk == NULL || psk_identity == NULL )
         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
 
+    if( psk_len > POLARSSL_PSK_MAX_LEN )
+        return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+
     if( ssl->psk != NULL )
     {
         polarssl_free( ssl->psk );
@@ -3694,7 +3827,8 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
     ssl->psk_identity_len = psk_identity_len;
 
     ssl->psk = (unsigned char *) polarssl_malloc( ssl->psk_len );
-    ssl->psk_identity = (unsigned char *) polarssl_malloc( ssl->psk_identity_len );
+    ssl->psk_identity = (unsigned char *)
+                                polarssl_malloc( ssl->psk_identity_len );
 
     if( ssl->psk == NULL || ssl->psk_identity == NULL )
         return( POLARSSL_ERR_SSL_MALLOC_FAILED );
@@ -3739,13 +3873,13 @@ int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx )
 {
     int ret;
 
-    if( ( ret = mpi_copy(&ssl->dhm_P, &dhm_ctx->P) ) != 0 )
+    if( ( ret = mpi_copy( &ssl->dhm_P, &dhm_ctx->P ) ) != 0 )
     {
         SSL_DEBUG_RET( 1, "mpi_copy", ret );
         return( ret );
     }
 
-    if( ( ret = mpi_copy(&ssl->dhm_G, &dhm_ctx->G) ) != 0 )
+    if( ( ret = mpi_copy( &ssl->dhm_G, &dhm_ctx->G ) ) != 0 )
     {
         SSL_DEBUG_RET( 1, "mpi_copy", ret );
         return( ret );
@@ -3755,6 +3889,16 @@ int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx )
 }
 #endif /* POLARSSL_DHM_C */
 
+#if defined(POLARSSL_SSL_SET_CURVES)
+/*
+ * Set the allowed elliptic curves
+ */
+void ssl_set_curves( ssl_context *ssl, const ecp_group_id *curve_list )
+{
+  ssl->curve_list = curve_list;
+}
+#endif
+
 #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
 int ssl_set_hostname( ssl_context *ssl, const char *hostname )
 {
@@ -3789,6 +3933,37 @@ void ssl_set_sni( ssl_context *ssl,
 }
 #endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
 
+#if defined(POLARSSL_SSL_ALPN)
+int ssl_set_alpn_protocols( ssl_context *ssl, const char **protos )
+{
+    size_t cur_len, tot_len;
+    const char **p;
+
+    /*
+     * "Empty strings MUST NOT be included and byte strings MUST NOT be
+     * truncated". Check lengths now rather than later.
+     */
+    tot_len = 0;
+    for( p = protos; *p != NULL; p++ )
+    {
+        cur_len = strlen( *p );
+        tot_len += cur_len;
+
+        if( cur_len == 0 || cur_len > 255 || tot_len > 65535 )
+            return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    ssl->alpn_list = protos;
+
+    return( 0 );
+}
+
+const char *ssl_get_alpn_protocol( const ssl_context *ssl )
+{
+    return( ssl->alpn_chosen );
+}
+#endif /* POLARSSL_SSL_ALPN */
+
 void ssl_set_max_version( ssl_context *ssl, int major, int minor )
 {
     if( major >= SSL_MIN_MAJOR_VERSION && major <= SSL_MAX_MAJOR_VERSION &&
@@ -3812,7 +3987,7 @@ void ssl_set_min_version( ssl_context *ssl, int major, int minor )
 #if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
 int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code )
 {
-    if( mfl_code >= sizeof( mfl_code_to_length ) ||
+    if( mfl_code >= SSL_MAX_FRAG_LEN_INVALID ||
         mfl_code_to_length[mfl_code] > SSL_MAX_CONTENT_LEN )
     {
         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
@@ -3846,6 +4021,11 @@ void ssl_legacy_renegotiation( ssl_context *ssl, int allow_legacy )
     ssl->allow_legacy_renegotiation = allow_legacy;
 }
 
+void ssl_set_renegotiation_enforced( ssl_context *ssl, int max_records )
+{
+    ssl->renego_max_records = max_records;
+}
+
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
 int ssl_set_session_tickets( ssl_context *ssl, int use_tickets )
 {
@@ -3882,7 +4062,7 @@ int ssl_get_verify_result( const ssl_context *ssl )
 const char *ssl_get_ciphersuite( const ssl_context *ssl )
 {
     if( ssl == NULL || ssl->session == NULL )
-        return NULL;
+        return( NULL );
 
     return ssl_get_ciphersuite_name( ssl->session->ciphersuite );
 }
@@ -3913,9 +4093,9 @@ const char *ssl_get_version( const ssl_context *ssl )
 const x509_crt *ssl_get_peer_cert( const ssl_context *ssl )
 {
     if( ssl == NULL || ssl->session == NULL )
-        return NULL;
+        return( NULL );
 
-    return ssl->session->peer_cert;
+    return( ssl->session->peer_cert );
 }
 #endif /* POLARSSL_X509_CRT_PARSE_C */
 
@@ -4142,7 +4322,8 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
 
             if( ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED ||
                 ( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
-                  ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION ) )
+                  ssl->allow_legacy_renegotiation ==
+                                                SSL_LEGACY_NO_RENEGOTIATION ) )
             {
                 SSL_DEBUG_MSG( 3, ( "ignoring renegotiation, sending alert" ) );
 
@@ -4156,7 +4337,7 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
                         return( ret );
                 }
                 else
-#endif
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
 #if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
     defined(POLARSSL_SSL_PROTO_TLS1_2)
                 if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
@@ -4169,10 +4350,11 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
                     }
                 }
                 else
-#endif
+#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 ||
+          POLARSSL_SSL_PROTO_TLS1_2 */
                 {
                     SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                    return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+                    return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
                 }
             }
             else
@@ -4188,9 +4370,15 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
         }
         else if( ssl->renegotiation == SSL_RENEGOTIATION_PENDING )
         {
-            SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
-                                "but not honored by client" ) );
-            return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+            ssl->renego_records_seen++;
+
+            if( ssl->renego_max_records >= 0 &&
+                ssl->renego_records_seen > ssl->renego_max_records )
+            {
+                SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
+                                    "but not honored by client" ) );
+                return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
+            }
         }
         else if( ssl->in_msgtype != SSL_MSG_APPLICATION_DATA )
         {
@@ -4315,18 +4503,21 @@ int ssl_close_notify( ssl_context *ssl )
 
 void ssl_transform_free( ssl_transform *transform )
 {
+    if( transform == NULL )
+        return;
+
 #if defined(POLARSSL_ZLIB_SUPPORT)
     deflateEnd( &transform->ctx_deflate );
     inflateEnd( &transform->ctx_inflate );
 #endif
 
-    cipher_free_ctx( &transform->cipher_ctx_enc );
-    cipher_free_ctx( &transform->cipher_ctx_dec );
+    cipher_free( &transform->cipher_ctx_enc );
+    cipher_free( &transform->cipher_ctx_dec );
 
-    md_free_ctx( &transform->md_ctx_enc );
-    md_free_ctx( &transform->md_ctx_dec );
+    md_free( &transform->md_ctx_enc );
+    md_free( &transform->md_ctx_dec );
 
-    memset( transform, 0, sizeof( ssl_transform ) );
+    polarssl_zeroize( transform, sizeof( ssl_transform ) );
 }
 
 #if defined(POLARSSL_X509_CRT_PARSE_C)
@@ -4352,6 +4543,9 @@ static void ssl_key_cert_free( ssl_key_cert *key_cert )
 
 void ssl_handshake_free( ssl_handshake_params *handshake )
 {
+    if( handshake == NULL )
+        return;
+
 #if defined(POLARSSL_DHM_C)
     dhm_free( &handshake->dhm_ctx );
 #endif
@@ -4360,8 +4554,8 @@ void ssl_handshake_free( ssl_handshake_params *handshake )
 #endif
 
 #if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
-       /* explicit void pointer cast for buggy MS compiler */
-       polarssl_free( (void *) handshake->curves );
+    /* explicit void pointer cast for buggy MS compiler */
+    polarssl_free( (void *) handshake->curves );
 #endif
 
 #if defined(POLARSSL_X509_CRT_PARSE_C) && \
@@ -4381,13 +4575,16 @@ void ssl_handshake_free( ssl_handshake_params *handshake )
             cur = next;
         }
     }
-#endif
+#endif /* POLARSSL_X509_CRT_PARSE_C && POLARSSL_SSL_SERVER_NAME_INDICATION */
 
-    memset( handshake, 0, sizeof( ssl_handshake_params ) );
+    polarssl_zeroize( handshake, sizeof( ssl_handshake_params ) );
 }
 
 void ssl_session_free( ssl_session *session )
 {
+    if( session == NULL )
+        return;
+
 #if defined(POLARSSL_X509_CRT_PARSE_C)
     if( session->peer_cert != NULL )
     {
@@ -4400,7 +4597,7 @@ void ssl_session_free( ssl_session *session )
     polarssl_free( session->ticket );
 #endif
 
-    memset( session, 0, sizeof( ssl_session ) );
+    polarssl_zeroize( session, sizeof( ssl_session ) );
 }
 
 /*
@@ -4408,24 +4605,27 @@ void ssl_session_free( ssl_session *session )
  */
 void ssl_free( ssl_context *ssl )
 {
+    if( ssl == NULL )
+        return;
+
     SSL_DEBUG_MSG( 2, ( "=> free" ) );
 
     if( ssl->out_ctr != NULL )
     {
-        memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );
+        polarssl_zeroize( ssl->out_ctr, SSL_BUFFER_LEN );
         polarssl_free( ssl->out_ctr );
     }
 
     if( ssl->in_ctr != NULL )
     {
-        memset( ssl->in_ctr, 0, SSL_BUFFER_LEN );
+        polarssl_zeroize( ssl->in_ctr, SSL_BUFFER_LEN );
         polarssl_free( ssl->in_ctr );
     }
 
 #if defined(POLARSSL_ZLIB_SUPPORT)
     if( ssl->compress_buf != NULL )
     {
-        memset( ssl->compress_buf, 0, SSL_BUFFER_LEN );
+        polarssl_zeroize( ssl->compress_buf, SSL_BUFFER_LEN );
         polarssl_free( ssl->compress_buf );
     }
 #endif
@@ -4459,13 +4659,17 @@ void ssl_free( ssl_context *ssl )
     }
 
 #if defined(POLARSSL_SSL_SESSION_TICKETS)
-    polarssl_free( ssl->ticket_keys );
+    if( ssl->ticket_keys )
+    {
+        ssl_ticket_keys_free( ssl->ticket_keys );
+        polarssl_free( ssl->ticket_keys );
+    }
 #endif
 
 #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
-    if ( ssl->hostname != NULL )
+    if( ssl->hostname != NULL )
     {
-        memset( ssl->hostname, 0, ssl->hostname_len );
+        polarssl_zeroize( ssl->hostname, ssl->hostname_len );
         polarssl_free( ssl->hostname );
         ssl->hostname_len = 0;
     }
@@ -4474,8 +4678,8 @@ void ssl_free( ssl_context *ssl )
 #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
     if( ssl->psk != NULL )
     {
-        memset( ssl->psk, 0, ssl->psk_len );
-        memset( ssl->psk_identity, 0, ssl->psk_identity_len );
+        polarssl_zeroize( ssl->psk, ssl->psk_len );
+        polarssl_zeroize( ssl->psk_identity, ssl->psk_identity_len );
         polarssl_free( ssl->psk );
         polarssl_free( ssl->psk_identity );
         ssl->psk_len = 0;
@@ -4498,7 +4702,7 @@ void ssl_free( ssl_context *ssl )
     SSL_DEBUG_MSG( 2, ( "<= free" ) );
 
     /* Actually clear after last debug message */
-    memset( ssl, 0, sizeof( ssl_context ) );
+    polarssl_zeroize( ssl, sizeof( ssl_context ) );
 }
 
 #if defined(POLARSSL_PK_C)
@@ -4534,7 +4738,7 @@ pk_type_t ssl_pk_alg_from_sig( unsigned char sig )
             return( POLARSSL_PK_NONE );
     }
 }
-#endif
+#endif /* POLARSSL_PK_C */
 
 /*
  * Convert between SSL_HASH_XXX and POLARSSL_MD_XXX
@@ -4568,4 +4772,102 @@ md_type_t ssl_md_alg_from_hash( unsigned char hash )
     }
 }
 
+#if defined(POLARSSL_SSL_SET_CURVES)
+/*
+ * Check is a curve proposed by the peer is in our list.
+ * Return 1 if we're willing to use it, 0 otherwise.
+ */
+int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id )
+{
+    const ecp_group_id *gid;
+
+    for( gid = ssl->curve_list; *gid != POLARSSL_ECP_DP_NONE; gid++ )
+        if( *gid == grp_id )
+            return( 1 );
+
+    return( 0 );
+}
+#endif /* POLARSSL_SSL_SET_CURVES */
+
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+int ssl_check_cert_usage( const x509_crt *cert,
+                          const ssl_ciphersuite_t *ciphersuite,
+                          int cert_endpoint )
+{
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    int usage = 0;
+#endif
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+    const char *ext_oid;
+    size_t ext_len;
+#endif
+
+#if !defined(POLARSSL_X509_CHECK_KEY_USAGE) &&          \
+    !defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+    ((void) cert);
+    ((void) cert_endpoint);
 #endif
+
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    if( cert_endpoint == SSL_IS_SERVER )
+    {
+        /* Server part of the key exchange */
+        switch( ciphersuite->key_exchange )
+        {
+            case POLARSSL_KEY_EXCHANGE_RSA:
+            case POLARSSL_KEY_EXCHANGE_RSA_PSK:
+                usage = KU_KEY_ENCIPHERMENT;
+                break;
+
+            case POLARSSL_KEY_EXCHANGE_DHE_RSA:
+            case POLARSSL_KEY_EXCHANGE_ECDHE_RSA:
+            case POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA:
+                usage = KU_DIGITAL_SIGNATURE;
+                break;
+
+            case POLARSSL_KEY_EXCHANGE_ECDH_RSA:
+            case POLARSSL_KEY_EXCHANGE_ECDH_ECDSA:
+                usage = KU_KEY_AGREEMENT;
+                break;
+
+            /* Don't use default: we want warnings when adding new values */
+            case POLARSSL_KEY_EXCHANGE_NONE:
+            case POLARSSL_KEY_EXCHANGE_PSK:
+            case POLARSSL_KEY_EXCHANGE_DHE_PSK:
+            case POLARSSL_KEY_EXCHANGE_ECDHE_PSK:
+                usage = 0;
+        }
+    }
+    else
+    {
+        /* Client auth: we only implement rsa_sign and ecdsa_sign for now */
+        usage = KU_DIGITAL_SIGNATURE;
+    }
+
+    if( x509_crt_check_key_usage( cert, usage ) != 0 )
+        return( -1 );
+#else
+    ((void) ciphersuite);
+#endif /* POLARSSL_X509_CHECK_KEY_USAGE */
+
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+    if( cert_endpoint == SSL_IS_SERVER )
+    {
+        ext_oid = OID_SERVER_AUTH;
+        ext_len = OID_SIZE( OID_SERVER_AUTH );
+    }
+    else
+    {
+        ext_oid = OID_CLIENT_AUTH;
+        ext_len = OID_SIZE( OID_CLIENT_AUTH );
+    }
+
+    if( x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 )
+        return( -1 );
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */
+
+    return( 0 );
+}
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+
+#endif /* POLARSSL_SSL_TLS_C */
index 659aa7e4bb428a1ea89c76fe20a0f00351d39bea..522c70fef75b0dc14f2199dd14c1d5605629db90 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Threading abstraction layer
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_THREADING_C)
 
 #include "polarssl/threading.h"
 
-#if defined(POLARSSL_THREADING_DUMMY)
-static int threading_mutex_init_dummy( threading_mutex_t *mutex )
-{
-    ((void) mutex );
-    return( 0 );
-}
-
-static int threading_mutex_free_dummy( threading_mutex_t *mutex )
-{
-    ((void) mutex );
-    return( 0 );
-}
-
-static int threading_mutex_lock_dummy( threading_mutex_t *mutex )
-{
-    ((void) mutex );
-    return( 0 );
-}
-
-static int threading_mutex_unlock_dummy( threading_mutex_t *mutex )
-{
-    ((void) mutex );
-    return( 0 );
-}
-
-int (*polarssl_mutex_init)( threading_mutex_t * ) = threading_mutex_init_dummy;
-int (*polarssl_mutex_free)( threading_mutex_t * ) = threading_mutex_free_dummy;
-int (*polarssl_mutex_lock)( threading_mutex_t * ) = threading_mutex_lock_dummy;
-int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_unlock_dummy;
-#endif /* POLARSSL_THREADING_DUMMY */
-
 #if defined(POLARSSL_THREADING_PTHREAD)
 static int threading_mutex_init_pthread( threading_mutex_t *mutex )
 {
@@ -112,10 +85,16 @@ int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_unlock_pth
 #endif /* POLARSSL_THREADING_PTHREAD */
 
 #if defined(POLARSSL_THREADING_ALT)
-int (*polarssl_mutex_init)( threading_mutex_t * ) = NULL;
-int (*polarssl_mutex_free)( threading_mutex_t * ) = NULL;
-int (*polarssl_mutex_lock)( threading_mutex_t * ) = NULL;
-int (*polarssl_mutex_unlock)( threading_mutex_t * ) = NULL;
+static int threading_mutex_fail( threading_mutex_t *mutex )
+{
+    ((void) mutex );
+    return( POLARSSL_ERR_THREADING_BAD_INPUT_DATA );
+}
+
+int (*polarssl_mutex_init)( threading_mutex_t * ) = threading_mutex_fail;
+int (*polarssl_mutex_free)( threading_mutex_t * ) = threading_mutex_fail;
+int (*polarssl_mutex_lock)( threading_mutex_t * ) = threading_mutex_fail;
+int (*polarssl_mutex_unlock)( threading_mutex_t * ) = threading_mutex_fail;
 
 int threading_set_alt( int (*mutex_init)( threading_mutex_t * ),
                        int (*mutex_free)( threading_mutex_t * ),
index 1b4311cbc63497dfcacfa7fce7c4281a3939b33a..6c1dfa46b1802433032ac9c71f50793c1e5a4e9f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Portable interface to the CPU cycle counter
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#include <stdio.h>
+#define polarssl_printf     printf
+#endif
 
-#if defined(POLARSSL_TIMING_C)
+#if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT)
 
 #include "polarssl/timing.h"
 
@@ -52,10 +63,10 @@ struct _hr_time
     struct timeval start;
 };
 
-#endif
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
-       (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+    ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__)
 
 #define POLARSSL_HAVE_HARDCLOCK
 
@@ -66,7 +77,8 @@ unsigned long hardclock( void )
     __asm   mov  [tsc], eax
     return( tsc );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
     defined(__GNUC__) && defined(__i386__)
@@ -76,26 +88,28 @@ unsigned long hardclock( void )
 unsigned long hardclock( void )
 {
     unsigned long lo, hi;
-    asm( "rdtsc" : "=a" (lo), "=d" (hi) );
+    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
     return( lo );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __i386__ */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
-    defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
+    defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) )
 
 #define POLARSSL_HAVE_HARDCLOCK
 
 unsigned long hardclock( void )
 {
     unsigned long lo, hi;
-    asm( "rdtsc" : "=a" (lo), "=d" (hi) ); 
-    return( lo | (hi << 32) );
+    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
+    return( lo | ( hi << 32 ) );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && ( __amd64__ || __x86_64__ ) */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
-    defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+    defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) )
 
 #define POLARSSL_HAVE_HARDCLOCK
 
@@ -105,15 +119,16 @@ unsigned long hardclock( void )
 
     do
     {
-        asm( "mftbu %0" : "=r" (tbu0) );
-        asm( "mftb  %0" : "=r" (tbl ) );
-        asm( "mftbu %0" : "=r" (tbu1) );
+        asm volatile( "mftbu %0" : "=r" (tbu0) );
+        asm volatile( "mftb  %0" : "=r" (tbl ) );
+        asm volatile( "mftbu %0" : "=r" (tbu1) );
     }
     while( tbu0 != tbu1 );
 
     return( tbl );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && ( __powerpc__ || __ppc__ ) */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
     defined(__GNUC__) && defined(__sparc64__)
@@ -126,11 +141,12 @@ unsigned long hardclock( void )
 unsigned long hardclock( void )
 {
     unsigned long tick;
-    asm( "rdpr %%tick, %0;" : "=&r" (tick) );
+    asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) );
     return( tick );
 }
-#endif
-#endif
+#endif /* __OpenBSD__ */
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __sparc64__ */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&  \
     defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__)
@@ -140,11 +156,12 @@ unsigned long hardclock( void )
 unsigned long hardclock( void )
 {
     unsigned long tick;
-    asm( ".byte 0x83, 0x41, 0x00, 0x00" );
-    asm( "mov   %%g1, %0" : "=r" (tick) );
+    asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" );
+    asm volatile( "mov   %%g1, %0" : "=r" (tick) );
     return( tick );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __sparc__ && !__sparc64__ */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&      \
     defined(__GNUC__) && defined(__alpha__)
@@ -154,10 +171,11 @@ unsigned long hardclock( void )
 unsigned long hardclock( void )
 {
     unsigned long cc;
-    asm( "rpcc %0" : "=r" (cc) );
+    asm volatile( "rpcc %0" : "=r" (cc) );
     return( cc & 0xFFFFFFFF );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __alpha__ */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) &&      \
     defined(__GNUC__) && defined(__ia64__)
@@ -167,10 +185,11 @@ unsigned long hardclock( void )
 unsigned long hardclock( void )
 {
     unsigned long itc;
-    asm( "mov %0 = ar.itc" : "=r" (itc) );
+    asm volatile( "mov %0 = ar.itc" : "=r" (itc) );
     return( itc );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
+          __GNUC__ && __ia64__ */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(_MSC_VER) && \
     !defined(EFIX64) && !defined(EFI32)
@@ -181,11 +200,11 @@ unsigned long hardclock( void )
 {
     LARGE_INTEGER offset;
 
-       QueryPerformanceCounter( &offset );
+    QueryPerformanceCounter( &offset );
 
-       return (unsigned long)( offset.QuadPart );
+    return( (unsigned long)( offset.QuadPart ) );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */
 
 #if !defined(POLARSSL_HAVE_HARDCLOCK)
 
@@ -208,7 +227,7 @@ unsigned long hardclock( void )
     return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000
           + ( tv_cur.tv_usec - tv_init.tv_usec ) );
 }
-#endif
+#endif /* !POLARSSL_HAVE_HARDCLOCK */
 
 volatile int alarmed = 0;
 
@@ -234,17 +253,17 @@ unsigned long get_timer( struct hr_time *val, int reset )
 }
 
 DWORD WINAPI TimerProc( LPVOID uElapse )
-{   
+{
     Sleep( (DWORD) uElapse );
-    alarmed = 1; 
+    alarmed = 1;
     return( TRUE );
 }
 
 void set_alarm( int seconds )
-{   
+{
     DWORD ThreadId;
 
-    alarmed = 0; 
+    alarmed = 0;
     CloseHandle( CreateThread( NULL, 0, TimerProc,
         (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
 }
@@ -254,7 +273,7 @@ void m_sleep( int milliseconds )
     Sleep( milliseconds );
 }
 
-#else
+#else /* _WIN32 && !EFIX64 && !EFI32 */
 
 unsigned long get_timer( struct hr_time *val, int reset )
 {
@@ -282,10 +301,10 @@ void m_sleep( int milliseconds )
     usleep( milliseconds * 1000 );
 }
 
-#else
+#else /* INTEGRITY */
 
 static void sighandler( int signum )
-{   
+{
     alarmed = 1;
     signal( signum, sighandler );
 }
@@ -302,12 +321,180 @@ void m_sleep( int milliseconds )
     struct timeval tv;
 
     tv.tv_sec  = milliseconds / 1000;
-    tv.tv_usec = milliseconds * 1000;
+    tv.tv_usec = ( milliseconds % 1000 ) * 1000;
 
     select( 0, NULL, NULL, NULL, &tv );
 }
 #endif /* INTEGRITY */
 
-#endif
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+
+#if defined(POLARSSL_SELF_TEST)
 
+/* To test net_usleep against our functions */
+#if defined(POLARSSL_NET_C)
+#include "polarssl/net.h"
 #endif
+
+/*
+ * Busy-waits for the given number of milliseconds.
+ * Used for testing hardclock.
+ */
+static void busy_msleep( unsigned long msec )
+{
+    struct hr_time hires;
+    unsigned long i = 0; /* for busy-waiting */
+    volatile unsigned long j; /* to prevent optimisation */
+
+    (void) get_timer( &hires, 1 );
+
+    while( get_timer( &hires, 0 ) < msec )
+        i++;
+
+    j = i;
+    (void) j;
+}
+
+/*
+ * Checkup routine
+ *
+ * Warning: this is work in progress, some tests may not be reliable enough
+ * yet! False positives may happen.
+ */
+int timing_self_test( int verbose )
+{
+    unsigned long cycles, ratio;
+    unsigned long millisecs, secs;
+    int hardfail;
+    struct hr_time hires;
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING tests note: will take some time!\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #1 (m_sleep   / get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        m_sleep( 500 * secs );
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 450 * secs || millisecs > 550 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #2 (set_alarm / get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        set_alarm( secs );
+        while( !alarmed )
+            ;
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 900 * secs || millisecs > 1100 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #3 (hardclock / get_timer): " );
+
+    /*
+     * Allow one failure for possible counter wrapping.
+     * On a 4Ghz 32-bit machine the cycle counter wraps about once per second;
+     * since the whole test is about 10ms, it shouldn't happen twice in a row.
+     */
+    hardfail = 0;
+
+hard_test:
+    if( hardfail > 1 )
+    {
+        if( verbose != 0 )
+            polarssl_printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    /* Get a reference ratio cycles/ms */
+    millisecs = 1;
+    cycles = hardclock();
+    busy_msleep( millisecs );
+    cycles = hardclock() - cycles;
+    ratio = cycles / millisecs;
+
+    /* Check that the ratio is mostly constant */
+    for( millisecs = 2; millisecs <= 4; millisecs++ )
+    {
+        cycles = hardclock();
+        busy_msleep( millisecs );
+        cycles = hardclock() - cycles;
+
+        /* Allow variation up to 20% */
+        if( cycles / millisecs < ratio - ratio / 5 ||
+            cycles / millisecs > ratio + ratio / 5 )
+        {
+            hardfail++;
+            goto hard_test;
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+
+#if defined(POLARSSL_NET_C)
+    if( verbose != 0 )
+        polarssl_printf( "  TIMING test #4 (net_usleep/ get_timer): " );
+
+    for( secs = 1; secs <= 3; secs++ )
+    {
+        (void) get_timer( &hires, 1 );
+
+        net_usleep( 500000 * secs );
+
+        millisecs = get_timer( &hires, 0 );
+
+        if( millisecs < 450 * secs || millisecs > 550 * secs )
+        {
+            if( verbose != 0 )
+                polarssl_printf( "failed\n" );
+
+            return( 1 );
+        }
+    }
+
+    if( verbose != 0 )
+        polarssl_printf( "passed\n" );
+#endif /* POLARSSL_NET_C */
+
+    if( verbose != 0 )
+        polarssl_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* POLARSSL_SELF_TEST */
+
+#endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */
index c1080b781612e11709e47e3987317a9e3f7b9daf..c3c708a2de5b5e2a9826f98dde198e6fb5621384 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Version information
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_VERSION_C)
 
@@ -34,17 +38,19 @@ const char version[] = POLARSSL_VERSION_STRING;
 
 unsigned int version_get_number()
 {
-    return POLARSSL_VERSION_NUMBER;
+    return( POLARSSL_VERSION_NUMBER );
 }
 
 void version_get_string( char *string )
 {
-    memcpy( string, POLARSSL_VERSION_STRING, sizeof( POLARSSL_VERSION_STRING ) );
+    memcpy( string, POLARSSL_VERSION_STRING,
+            sizeof( POLARSSL_VERSION_STRING ) );
 }
 
 void version_get_string_full( char *string )
 {
-    memcpy( string, POLARSSL_VERSION_STRING_FULL, sizeof( POLARSSL_VERSION_STRING_FULL ) );
+    memcpy( string, POLARSSL_VERSION_STRING_FULL,
+            sizeof( POLARSSL_VERSION_STRING_FULL ) );
 }
 
 #endif /* POLARSSL_VERSION_C */
diff --git a/pdns/ext/polarssl/library/version_features.c b/pdns/ext/polarssl/library/version_features.c
new file mode 100644 (file)
index 0000000..1023198
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ *  Version feature information
+ *
+ *  Copyright (C) 2006-2014, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined(POLARSSL_CONFIG_FILE)
+#include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
+
+#if defined(POLARSSL_VERSION_C)
+
+#include "polarssl/version.h"
+
+#include <string.h>
+
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+    !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
+const char *features[] = {
+#if defined(POLARSSL_VERSION_FEATURES)
+#if defined(POLARSSL_HAVE_INT8)
+    "POLARSSL_HAVE_INT8",
+#endif /* POLARSSL_HAVE_INT8 */
+#if defined(POLARSSL_HAVE_INT16)
+    "POLARSSL_HAVE_INT16",
+#endif /* POLARSSL_HAVE_INT16 */
+#if defined(POLARSSL_HAVE_LONGLONG)
+    "POLARSSL_HAVE_LONGLONG",
+#endif /* POLARSSL_HAVE_LONGLONG */
+#if defined(POLARSSL_HAVE_ASM)
+    "POLARSSL_HAVE_ASM",
+#endif /* POLARSSL_HAVE_ASM */
+#if defined(POLARSSL_HAVE_SSE2)
+    "POLARSSL_HAVE_SSE2",
+#endif /* POLARSSL_HAVE_SSE2 */
+#if defined(POLARSSL_HAVE_TIME)
+    "POLARSSL_HAVE_TIME",
+#endif /* POLARSSL_HAVE_TIME */
+#if defined(POLARSSL_HAVE_IPV6)
+    "POLARSSL_HAVE_IPV6",
+#endif /* POLARSSL_HAVE_IPV6 */
+#if defined(POLARSSL_PLATFORM_MEMORY)
+    "POLARSSL_PLATFORM_MEMORY",
+#endif /* POLARSSL_PLATFORM_MEMORY */
+#if defined(POLARSSL_PLATFORM_NO_STD_FUNCTIONS)
+    "POLARSSL_PLATFORM_NO_STD_FUNCTIONS",
+#endif /* POLARSSL_PLATFORM_NO_STD_FUNCTIONS */
+#if defined(POLARSSL_PLATFORM_PRINTF_ALT)
+    "POLARSSL_PLATFORM_PRINTF_ALT",
+#endif /* POLARSSL_PLATFORM_PRINTF_ALT */
+#if defined(POLARSSL_PLATFORM_FPRINTF_ALT)
+    "POLARSSL_PLATFORM_FPRINTF_ALT",
+#endif /* POLARSSL_PLATFORM_FPRINTF_ALT */
+#if defined(POLARSSL_TIMING_ALT)
+    "POLARSSL_TIMING_ALT",
+#endif /* POLARSSL_TIMING_ALT */
+#if defined(POLARSSL_AES_ALT)
+    "POLARSSL_AES_ALT",
+#endif /* POLARSSL_AES_ALT */
+#if defined(POLARSSL_ARC4_ALT)
+    "POLARSSL_ARC4_ALT",
+#endif /* POLARSSL_ARC4_ALT */
+#if defined(POLARSSL_BLOWFISH_ALT)
+    "POLARSSL_BLOWFISH_ALT",
+#endif /* POLARSSL_BLOWFISH_ALT */
+#if defined(POLARSSL_CAMELLIA_ALT)
+    "POLARSSL_CAMELLIA_ALT",
+#endif /* POLARSSL_CAMELLIA_ALT */
+#if defined(POLARSSL_DES_ALT)
+    "POLARSSL_DES_ALT",
+#endif /* POLARSSL_DES_ALT */
+#if defined(POLARSSL_XTEA_ALT)
+    "POLARSSL_XTEA_ALT",
+#endif /* POLARSSL_XTEA_ALT */
+#if defined(POLARSSL_MD2_ALT)
+    "POLARSSL_MD2_ALT",
+#endif /* POLARSSL_MD2_ALT */
+#if defined(POLARSSL_MD4_ALT)
+    "POLARSSL_MD4_ALT",
+#endif /* POLARSSL_MD4_ALT */
+#if defined(POLARSSL_MD5_ALT)
+    "POLARSSL_MD5_ALT",
+#endif /* POLARSSL_MD5_ALT */
+#if defined(POLARSSL_RIPEMD160_ALT)
+    "POLARSSL_RIPEMD160_ALT",
+#endif /* POLARSSL_RIPEMD160_ALT */
+#if defined(POLARSSL_SHA1_ALT)
+    "POLARSSL_SHA1_ALT",
+#endif /* POLARSSL_SHA1_ALT */
+#if defined(POLARSSL_SHA256_ALT)
+    "POLARSSL_SHA256_ALT",
+#endif /* POLARSSL_SHA256_ALT */
+#if defined(POLARSSL_SHA512_ALT)
+    "POLARSSL_SHA512_ALT",
+#endif /* POLARSSL_SHA512_ALT */
+#if defined(POLARSSL_AES_ROM_TABLES)
+    "POLARSSL_AES_ROM_TABLES",
+#endif /* POLARSSL_AES_ROM_TABLES */
+#if defined(POLARSSL_CIPHER_MODE_CBC)
+    "POLARSSL_CIPHER_MODE_CBC",
+#endif /* POLARSSL_CIPHER_MODE_CBC */
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+    "POLARSSL_CIPHER_MODE_CFB",
+#endif /* POLARSSL_CIPHER_MODE_CFB */
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+    "POLARSSL_CIPHER_MODE_CTR",
+#endif /* POLARSSL_CIPHER_MODE_CTR */
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+    "POLARSSL_CIPHER_NULL_CIPHER",
+#endif /* POLARSSL_CIPHER_NULL_CIPHER */
+#if defined(POLARSSL_CIPHER_PADDING_PKCS7)
+    "POLARSSL_CIPHER_PADDING_PKCS7",
+#endif /* POLARSSL_CIPHER_PADDING_PKCS7 */
+#if defined(POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS)
+    "POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS",
+#endif /* POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS */
+#if defined(POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN)
+    "POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN",
+#endif /* POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN */
+#if defined(POLARSSL_CIPHER_PADDING_ZEROS)
+    "POLARSSL_CIPHER_PADDING_ZEROS",
+#endif /* POLARSSL_CIPHER_PADDING_ZEROS */
+#if defined(POLARSSL_ENABLE_WEAK_CIPHERSUITES)
+    "POLARSSL_ENABLE_WEAK_CIPHERSUITES",
+#endif /* POLARSSL_ENABLE_WEAK_CIPHERSUITES */
+#if defined(POLARSSL_REMOVE_ARC4_CIPHERSUITES)
+    "POLARSSL_REMOVE_ARC4_CIPHERSUITES",
+#endif /* POLARSSL_REMOVE_ARC4_CIPHERSUITES */
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP192R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP224R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP256R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP384R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+    "POLARSSL_ECP_DP_SECP521R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP192K1_ENABLED)
+    "POLARSSL_ECP_DP_SECP192K1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP192K1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP224K1_ENABLED)
+    "POLARSSL_ECP_DP_SECP224K1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP224K1_ENABLED */
+#if defined(POLARSSL_ECP_DP_SECP256K1_ENABLED)
+    "POLARSSL_ECP_DP_SECP256K1_ENABLED",
+#endif /* POLARSSL_ECP_DP_SECP256K1_ENABLED */
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+    "POLARSSL_ECP_DP_BP256R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+    "POLARSSL_ECP_DP_BP384R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+    "POLARSSL_ECP_DP_BP512R1_ENABLED",
+#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
+#if defined(POLARSSL_ECP_DP_M221_ENABLED)
+    "POLARSSL_ECP_DP_M221_ENABLED",
+#endif /* POLARSSL_ECP_DP_M221_ENABLED */
+#if defined(POLARSSL_ECP_DP_M255_ENABLED)
+    "POLARSSL_ECP_DP_M255_ENABLED",
+#endif /* POLARSSL_ECP_DP_M255_ENABLED */
+#if defined(POLARSSL_ECP_DP_M383_ENABLED)
+    "POLARSSL_ECP_DP_M383_ENABLED",
+#endif /* POLARSSL_ECP_DP_M383_ENABLED */
+#if defined(POLARSSL_ECP_DP_M511_ENABLED)
+    "POLARSSL_ECP_DP_M511_ENABLED",
+#endif /* POLARSSL_ECP_DP_M511_ENABLED */
+#if defined(POLARSSL_ECP_NIST_OPTIM)
+    "POLARSSL_ECP_NIST_OPTIM",
+#endif /* POLARSSL_ECP_NIST_OPTIM */
+#if defined(POLARSSL_ECDSA_DETERMINISTIC)
+    "POLARSSL_ECDSA_DETERMINISTIC",
+#endif /* POLARSSL_ECDSA_DETERMINISTIC */
+#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_PSK_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_RSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_RSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_RSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+#if defined(POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED)
+    "POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED",
+#endif /* POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED */
+#if defined(POLARSSL_PK_PARSE_EC_EXTENDED)
+    "POLARSSL_PK_PARSE_EC_EXTENDED",
+#endif /* POLARSSL_PK_PARSE_EC_EXTENDED */
+#if defined(POLARSSL_ERROR_STRERROR_BC)
+    "POLARSSL_ERROR_STRERROR_BC",
+#endif /* POLARSSL_ERROR_STRERROR_BC */
+#if defined(POLARSSL_ERROR_STRERROR_DUMMY)
+    "POLARSSL_ERROR_STRERROR_DUMMY",
+#endif /* POLARSSL_ERROR_STRERROR_DUMMY */
+#if defined(POLARSSL_GENPRIME)
+    "POLARSSL_GENPRIME",
+#endif /* POLARSSL_GENPRIME */
+#if defined(POLARSSL_FS_IO)
+    "POLARSSL_FS_IO",
+#endif /* POLARSSL_FS_IO */
+#if defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
+    "POLARSSL_NO_DEFAULT_ENTROPY_SOURCES",
+#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
+#if defined(POLARSSL_NO_PLATFORM_ENTROPY)
+    "POLARSSL_NO_PLATFORM_ENTROPY",
+#endif /* POLARSSL_NO_PLATFORM_ENTROPY */
+#if defined(POLARSSL_ENTROPY_FORCE_SHA256)
+    "POLARSSL_ENTROPY_FORCE_SHA256",
+#endif /* POLARSSL_ENTROPY_FORCE_SHA256 */
+#if defined(POLARSSL_MEMORY_DEBUG)
+    "POLARSSL_MEMORY_DEBUG",
+#endif /* POLARSSL_MEMORY_DEBUG */
+#if defined(POLARSSL_MEMORY_BACKTRACE)
+    "POLARSSL_MEMORY_BACKTRACE",
+#endif /* POLARSSL_MEMORY_BACKTRACE */
+#if defined(POLARSSL_PKCS1_V15)
+    "POLARSSL_PKCS1_V15",
+#endif /* POLARSSL_PKCS1_V15 */
+#if defined(POLARSSL_PKCS1_V21)
+    "POLARSSL_PKCS1_V21",
+#endif /* POLARSSL_PKCS1_V21 */
+#if defined(POLARSSL_RSA_NO_CRT)
+    "POLARSSL_RSA_NO_CRT",
+#endif /* POLARSSL_RSA_NO_CRT */
+#if defined(POLARSSL_SELF_TEST)
+    "POLARSSL_SELF_TEST",
+#endif /* POLARSSL_SELF_TEST */
+#if defined(POLARSSL_SSL_ALERT_MESSAGES)
+    "POLARSSL_SSL_ALERT_MESSAGES",
+#endif /* POLARSSL_SSL_ALERT_MESSAGES */
+#if defined(POLARSSL_SSL_DEBUG_ALL)
+    "POLARSSL_SSL_DEBUG_ALL",
+#endif /* POLARSSL_SSL_DEBUG_ALL */
+#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
+    "POLARSSL_SSL_HW_RECORD_ACCEL",
+#endif /* POLARSSL_SSL_HW_RECORD_ACCEL */
+#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+    "POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO",
+#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
+#if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
+    "POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE",
+#endif /* POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE */
+#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
+    "POLARSSL_SSL_MAX_FRAGMENT_LENGTH",
+#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
+#if defined(POLARSSL_SSL_PROTO_SSL3)
+    "POLARSSL_SSL_PROTO_SSL3",
+#endif /* POLARSSL_SSL_PROTO_SSL3 */
+#if defined(POLARSSL_SSL_PROTO_TLS1)
+    "POLARSSL_SSL_PROTO_TLS1",
+#endif /* POLARSSL_SSL_PROTO_TLS1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1_1)
+    "POLARSSL_SSL_PROTO_TLS1_1",
+#endif /* POLARSSL_SSL_PROTO_TLS1_1 */
+#if defined(POLARSSL_SSL_PROTO_TLS1_2)
+    "POLARSSL_SSL_PROTO_TLS1_2",
+#endif /* POLARSSL_SSL_PROTO_TLS1_2 */
+#if defined(POLARSSL_SSL_ALPN)
+    "POLARSSL_SSL_ALPN",
+#endif /* POLARSSL_SSL_ALPN */
+#if defined(POLARSSL_SSL_SESSION_TICKETS)
+    "POLARSSL_SSL_SESSION_TICKETS",
+#endif /* POLARSSL_SSL_SESSION_TICKETS */
+#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
+    "POLARSSL_SSL_SERVER_NAME_INDICATION",
+#endif /* POLARSSL_SSL_SERVER_NAME_INDICATION */
+#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
+    "POLARSSL_SSL_TRUNCATED_HMAC",
+#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
+#if defined(POLARSSL_SSL_SET_CURVES)
+    "POLARSSL_SSL_SET_CURVES",
+#endif /* POLARSSL_SSL_SET_CURVES */
+#if defined(POLARSSL_THREADING_ALT)
+    "POLARSSL_THREADING_ALT",
+#endif /* POLARSSL_THREADING_ALT */
+#if defined(POLARSSL_THREADING_PTHREAD)
+    "POLARSSL_THREADING_PTHREAD",
+#endif /* POLARSSL_THREADING_PTHREAD */
+#if defined(POLARSSL_VERSION_FEATURES)
+    "POLARSSL_VERSION_FEATURES",
+#endif /* POLARSSL_VERSION_FEATURES */
+#if defined(POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3)
+    "POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3",
+#endif /* POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 */
+#if defined(POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+    "POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION",
+#endif /* POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    "POLARSSL_X509_CHECK_KEY_USAGE",
+#endif /* POLARSSL_X509_CHECK_KEY_USAGE */
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+    "POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE",
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+    "POLARSSL_X509_RSASSA_PSS_SUPPORT",
+#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */
+#if defined(POLARSSL_ZLIB_SUPPORT)
+    "POLARSSL_ZLIB_SUPPORT",
+#endif /* POLARSSL_ZLIB_SUPPORT */
+#if defined(POLARSSL_AESNI_C)
+    "POLARSSL_AESNI_C",
+#endif /* POLARSSL_AESNI_C */
+#if defined(POLARSSL_AES_C)
+    "POLARSSL_AES_C",
+#endif /* POLARSSL_AES_C */
+#if defined(POLARSSL_ARC4_C)
+    "POLARSSL_ARC4_C",
+#endif /* POLARSSL_ARC4_C */
+#if defined(POLARSSL_ASN1_PARSE_C)
+    "POLARSSL_ASN1_PARSE_C",
+#endif /* POLARSSL_ASN1_PARSE_C */
+#if defined(POLARSSL_ASN1_WRITE_C)
+    "POLARSSL_ASN1_WRITE_C",
+#endif /* POLARSSL_ASN1_WRITE_C */
+#if defined(POLARSSL_BASE64_C)
+    "POLARSSL_BASE64_C",
+#endif /* POLARSSL_BASE64_C */
+#if defined(POLARSSL_BIGNUM_C)
+    "POLARSSL_BIGNUM_C",
+#endif /* POLARSSL_BIGNUM_C */
+#if defined(POLARSSL_BLOWFISH_C)
+    "POLARSSL_BLOWFISH_C",
+#endif /* POLARSSL_BLOWFISH_C */
+#if defined(POLARSSL_CAMELLIA_C)
+    "POLARSSL_CAMELLIA_C",
+#endif /* POLARSSL_CAMELLIA_C */
+#if defined(POLARSSL_CCM_C)
+    "POLARSSL_CCM_C",
+#endif /* POLARSSL_CCM_C */
+#if defined(POLARSSL_CERTS_C)
+    "POLARSSL_CERTS_C",
+#endif /* POLARSSL_CERTS_C */
+#if defined(POLARSSL_CIPHER_C)
+    "POLARSSL_CIPHER_C",
+#endif /* POLARSSL_CIPHER_C */
+#if defined(POLARSSL_CTR_DRBG_C)
+    "POLARSSL_CTR_DRBG_C",
+#endif /* POLARSSL_CTR_DRBG_C */
+#if defined(POLARSSL_DEBUG_C)
+    "POLARSSL_DEBUG_C",
+#endif /* POLARSSL_DEBUG_C */
+#if defined(POLARSSL_DES_C)
+    "POLARSSL_DES_C",
+#endif /* POLARSSL_DES_C */
+#if defined(POLARSSL_DHM_C)
+    "POLARSSL_DHM_C",
+#endif /* POLARSSL_DHM_C */
+#if defined(POLARSSL_ECDH_C)
+    "POLARSSL_ECDH_C",
+#endif /* POLARSSL_ECDH_C */
+#if defined(POLARSSL_ECDSA_C)
+    "POLARSSL_ECDSA_C",
+#endif /* POLARSSL_ECDSA_C */
+#if defined(POLARSSL_ECP_C)
+    "POLARSSL_ECP_C",
+#endif /* POLARSSL_ECP_C */
+#if defined(POLARSSL_ENTROPY_C)
+    "POLARSSL_ENTROPY_C",
+#endif /* POLARSSL_ENTROPY_C */
+#if defined(POLARSSL_ERROR_C)
+    "POLARSSL_ERROR_C",
+#endif /* POLARSSL_ERROR_C */
+#if defined(POLARSSL_GCM_C)
+    "POLARSSL_GCM_C",
+#endif /* POLARSSL_GCM_C */
+#if defined(POLARSSL_HAVEGE_C)
+    "POLARSSL_HAVEGE_C",
+#endif /* POLARSSL_HAVEGE_C */
+#if defined(POLARSSL_HMAC_DRBG_C)
+    "POLARSSL_HMAC_DRBG_C",
+#endif /* POLARSSL_HMAC_DRBG_C */
+#if defined(POLARSSL_MD_C)
+    "POLARSSL_MD_C",
+#endif /* POLARSSL_MD_C */
+#if defined(POLARSSL_MD2_C)
+    "POLARSSL_MD2_C",
+#endif /* POLARSSL_MD2_C */
+#if defined(POLARSSL_MD4_C)
+    "POLARSSL_MD4_C",
+#endif /* POLARSSL_MD4_C */
+#if defined(POLARSSL_MD5_C)
+    "POLARSSL_MD5_C",
+#endif /* POLARSSL_MD5_C */
+#if defined(POLARSSL_MEMORY_C)
+    "POLARSSL_MEMORY_C",
+#endif /* POLARSSL_MEMORY_C */
+#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
+    "POLARSSL_MEMORY_BUFFER_ALLOC_C",
+#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */
+#if defined(POLARSSL_NET_C)
+    "POLARSSL_NET_C",
+#endif /* POLARSSL_NET_C */
+#if defined(POLARSSL_OID_C)
+    "POLARSSL_OID_C",
+#endif /* POLARSSL_OID_C */
+#if defined(POLARSSL_PADLOCK_C)
+    "POLARSSL_PADLOCK_C",
+#endif /* POLARSSL_PADLOCK_C */
+#if defined(POLARSSL_PBKDF2_C)
+    "POLARSSL_PBKDF2_C",
+#endif /* POLARSSL_PBKDF2_C */
+#if defined(POLARSSL_PEM_PARSE_C)
+    "POLARSSL_PEM_PARSE_C",
+#endif /* POLARSSL_PEM_PARSE_C */
+#if defined(POLARSSL_PEM_WRITE_C)
+    "POLARSSL_PEM_WRITE_C",
+#endif /* POLARSSL_PEM_WRITE_C */
+#if defined(POLARSSL_PK_C)
+    "POLARSSL_PK_C",
+#endif /* POLARSSL_PK_C */
+#if defined(POLARSSL_PK_PARSE_C)
+    "POLARSSL_PK_PARSE_C",
+#endif /* POLARSSL_PK_PARSE_C */
+#if defined(POLARSSL_PK_WRITE_C)
+    "POLARSSL_PK_WRITE_C",
+#endif /* POLARSSL_PK_WRITE_C */
+#if defined(POLARSSL_PKCS5_C)
+    "POLARSSL_PKCS5_C",
+#endif /* POLARSSL_PKCS5_C */
+#if defined(POLARSSL_PKCS11_C)
+    "POLARSSL_PKCS11_C",
+#endif /* POLARSSL_PKCS11_C */
+#if defined(POLARSSL_PKCS12_C)
+    "POLARSSL_PKCS12_C",
+#endif /* POLARSSL_PKCS12_C */
+#if defined(POLARSSL_PLATFORM_C)
+    "POLARSSL_PLATFORM_C",
+#endif /* POLARSSL_PLATFORM_C */
+#if defined(POLARSSL_RIPEMD160_C)
+    "POLARSSL_RIPEMD160_C",
+#endif /* POLARSSL_RIPEMD160_C */
+#if defined(POLARSSL_RSA_C)
+    "POLARSSL_RSA_C",
+#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_SHA1_C)
+    "POLARSSL_SHA1_C",
+#endif /* POLARSSL_SHA1_C */
+#if defined(POLARSSL_SHA256_C)
+    "POLARSSL_SHA256_C",
+#endif /* POLARSSL_SHA256_C */
+#if defined(POLARSSL_SHA512_C)
+    "POLARSSL_SHA512_C",
+#endif /* POLARSSL_SHA512_C */
+#if defined(POLARSSL_SSL_CACHE_C)
+    "POLARSSL_SSL_CACHE_C",
+#endif /* POLARSSL_SSL_CACHE_C */
+#if defined(POLARSSL_SSL_CLI_C)
+    "POLARSSL_SSL_CLI_C",
+#endif /* POLARSSL_SSL_CLI_C */
+#if defined(POLARSSL_SSL_SRV_C)
+    "POLARSSL_SSL_SRV_C",
+#endif /* POLARSSL_SSL_SRV_C */
+#if defined(POLARSSL_SSL_TLS_C)
+    "POLARSSL_SSL_TLS_C",
+#endif /* POLARSSL_SSL_TLS_C */
+#if defined(POLARSSL_THREADING_C)
+    "POLARSSL_THREADING_C",
+#endif /* POLARSSL_THREADING_C */
+#if defined(POLARSSL_TIMING_C)
+    "POLARSSL_TIMING_C",
+#endif /* POLARSSL_TIMING_C */
+#if defined(POLARSSL_VERSION_C)
+    "POLARSSL_VERSION_C",
+#endif /* POLARSSL_VERSION_C */
+#if defined(POLARSSL_X509_USE_C)
+    "POLARSSL_X509_USE_C",
+#endif /* POLARSSL_X509_USE_C */
+#if defined(POLARSSL_X509_CRT_PARSE_C)
+    "POLARSSL_X509_CRT_PARSE_C",
+#endif /* POLARSSL_X509_CRT_PARSE_C */
+#if defined(POLARSSL_X509_CRL_PARSE_C)
+    "POLARSSL_X509_CRL_PARSE_C",
+#endif /* POLARSSL_X509_CRL_PARSE_C */
+#if defined(POLARSSL_X509_CSR_PARSE_C)
+    "POLARSSL_X509_CSR_PARSE_C",
+#endif /* POLARSSL_X509_CSR_PARSE_C */
+#if defined(POLARSSL_X509_CREATE_C)
+    "POLARSSL_X509_CREATE_C",
+#endif /* POLARSSL_X509_CREATE_C */
+#if defined(POLARSSL_X509_CRT_WRITE_C)
+    "POLARSSL_X509_CRT_WRITE_C",
+#endif /* POLARSSL_X509_CRT_WRITE_C */
+#if defined(POLARSSL_X509_CSR_WRITE_C)
+    "POLARSSL_X509_CSR_WRITE_C",
+#endif /* POLARSSL_X509_CSR_WRITE_C */
+#if defined(POLARSSL_XTEA_C)
+    "POLARSSL_XTEA_C",
+#endif /* POLARSSL_XTEA_C */
+#endif /* POLARSSL_VERSION_FEATURES */
+    NULL
+};
+
+int version_check_feature( const char *feature )
+{
+    const char **idx = features;
+
+    if( *idx == NULL )
+        return( -2 );
+
+    if( feature == NULL )
+        return( -1 );
+
+    while( *idx != NULL )
+    {
+        if( !strcasecmp( *idx, feature ) )
+            return( 0 );
+        idx++;
+    }
+    return( -1 );
+}
+
+#endif /* POLARSSL_VERSION_C */
index 2ba1e861839623850fc14ad5f750b98924c3e7c0..17c7a7db04a957df443966aaf651cf49185abee5 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  X.509 certificate and private key decoding
+ *  X.509 common functions for parsing and verification
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 /*
  *  The ITU-T X.509 standard defines a certificate format for PKI.
  *
- *  http://www.ietf.org/rfc/rfc3279.txt
- *  http://www.ietf.org/rfc/rfc3280.txt
- *
- *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
+ *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
+ *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
  *
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_X509_USE_C)
 
 #include "polarssl/pem.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
+#define polarssl_printf     printf
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #endif
@@ -118,6 +122,223 @@ int x509_get_alg_null( unsigned char **p, const unsigned char *end,
     return( 0 );
 }
 
+/*
+ * Parse an algorithm identifier with (optional) paramaters
+ */
+int x509_get_alg( unsigned char **p, const unsigned char *end,
+                  x509_buf *alg, x509_buf *params )
+{
+    int ret;
+
+    if( ( ret = asn1_get_alg( p, end, alg, params ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    return( 0 );
+}
+
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+/*
+ * HashAlgorithm ::= AlgorithmIdentifier
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *      algorithm               OBJECT IDENTIFIER,
+ *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
+ *
+ * For HashAlgorithm, parameters MUST be NULL or absent.
+ */
+static int x509_get_hash_alg( const x509_buf *alg, md_type_t *md_alg )
+{
+    int ret;
+    unsigned char *p;
+    const unsigned char *end;
+    x509_buf md_oid;
+    size_t len;
+
+    /* Make sure we got a SEQUENCE and setup bounds */
+    if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    p = (unsigned char *) alg->p;
+    end = p + alg->len;
+
+    if( p >= end )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_OUT_OF_DATA );
+
+    /* Parse md_oid */
+    md_oid.tag = *p;
+
+    if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    md_oid.p = p;
+    p += md_oid.len;
+
+    /* Get md_alg from md_oid */
+    if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    /* Make sure params is absent of NULL */
+    if( p == end )
+        return( 0 );
+
+    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 || len != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p != end )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+
+/*
+ *    RSASSA-PSS-params  ::=  SEQUENCE  {
+ *       hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
+ *       maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
+ *       saltLength        [2] INTEGER DEFAULT 20,
+ *       trailerField      [3] INTEGER DEFAULT 1  }
+ *    -- Note that the tags in this Sequence are explicit.
+ *
+ * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
+ * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
+ * option. Enfore this at parsing time.
+ */
+int x509_get_rsassa_pss_params( const x509_buf *params,
+                                md_type_t *md_alg, md_type_t *mgf_md,
+                                int *salt_len )
+{
+    int ret;
+    unsigned char *p;
+    const unsigned char *end, *end2;
+    size_t len;
+    x509_buf alg_id, alg_params;
+
+    /* First set everything to defaults */
+    *md_alg = POLARSSL_MD_SHA1;
+    *mgf_md = POLARSSL_MD_SHA1;
+    *salt_len = 20;
+
+    /* Make sure params is a SEQUENCE and setup bounds */
+    if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
+
+    p = (unsigned char *) params->p;
+    end = p + params->len;
+
+    if( p == end )
+        return( 0 );
+
+    /*
+     * HashAlgorithm
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
+        if( ( ret = x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
+            return( ret );
+
+        if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+        if( p != end2 )
+            return( POLARSSL_ERR_X509_INVALID_ALG +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p == end )
+        return( 0 );
+
+    /*
+     * MaskGenAlgorithm
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
+        if( ( ret = x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
+            return( ret );
+
+        /* Only MFG1 is recognised for now */
+        if( ! OID_CMP( OID_MGF1, &alg_id ) )
+            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE +
+                    POLARSSL_ERR_OID_NOT_FOUND );
+
+        /* Parse HashAlgorithm */
+        if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
+            return( ret );
+
+        if( p != end2 )
+            return( POLARSSL_ERR_X509_INVALID_ALG +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p == end )
+        return( 0 );
+
+    /*
+     * salt_len
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 )
+    {
+        end2 = p + len;
+
+        if( ( ret = asn1_get_int( &p, end2, salt_len ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+        if( p != end2 )
+            return( POLARSSL_ERR_X509_INVALID_ALG +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p == end )
+        return( 0 );
+
+    /*
+     * trailer_field (if present, must be 1)
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+                    ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 )
+    {
+        int trailer_field;
+
+        end2 = p + len;
+
+        if( ( ret = asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
+            return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+        if( p != end2 )
+            return( POLARSSL_ERR_X509_INVALID_ALG +
+                    POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+        if( trailer_field != 1 )
+            return( POLARSSL_ERR_X509_INVALID_ALG );
+    }
+    else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
+        return( POLARSSL_ERR_X509_INVALID_ALG + ret );
+
+    if( p != end )
+        return( POLARSSL_ERR_X509_INVALID_ALG +
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+
+    return( 0 );
+}
+#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */
+
 /*
  *  AttributeTypeAndValue ::= SEQUENCE {
  *    type     AttributeType,
@@ -261,7 +482,7 @@ int x509_get_time( unsigned char **p, const unsigned char *end,
 
     tag = **p;
 
-    if ( tag == ASN1_UTC_TIME )
+    if( tag == ASN1_UTC_TIME )
     {
         (*p)++;
         ret = asn1_get_len( p, end, &len );
@@ -273,7 +494,7 @@ int x509_get_time( unsigned char **p, const unsigned char *end,
         memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
                 len : sizeof( date ) - 1 );
 
-        if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
+        if( sscanf( date, "%2d%2d%2d%2d%2d%2dZ",
                     &time->year, &time->mon, &time->day,
                     &time->hour, &time->min, &time->sec ) < 5 )
             return( POLARSSL_ERR_X509_INVALID_DATE );
@@ -285,7 +506,7 @@ int x509_get_time( unsigned char **p, const unsigned char *end,
 
         return( 0 );
     }
-    else if ( tag == ASN1_GENERALIZED_TIME )
+    else if( tag == ASN1_GENERALIZED_TIME )
     {
         (*p)++;
         ret = asn1_get_len( p, end, &len );
@@ -297,7 +518,7 @@ int x509_get_time( unsigned char **p, const unsigned char *end,
         memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
                 len : sizeof( date ) - 1 );
 
-        if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
+        if( sscanf( date, "%4d%2d%2d%2d%2d%2dZ",
                     &time->year, &time->mon, &time->day,
                     &time->hour, &time->min, &time->sec ) < 5 )
             return( POLARSSL_ERR_X509_INVALID_DATE );
@@ -333,14 +554,51 @@ int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
     return( 0 );
 }
 
-int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
-                      pk_type_t *pk_alg )
+/*
+ * Get signature algorithm from alg OID and optional parameters
+ */
+int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params,
+                      md_type_t *md_alg, pk_type_t *pk_alg,
+                      void **sig_opts )
 {
-    int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
+    int ret;
 
-    if( ret != 0 )
+    if( *sig_opts != NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    if( ( ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
         return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
 
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+    if( *pk_alg == POLARSSL_PK_RSASSA_PSS )
+    {
+        pk_rsassa_pss_options *pss_opts;
+
+        pss_opts = polarssl_malloc( sizeof( pk_rsassa_pss_options ) );
+        if( pss_opts == NULL )
+            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+
+        ret = x509_get_rsassa_pss_params( sig_params,
+                                          md_alg,
+                                          &pss_opts->mgf1_hash_id,
+                                          &pss_opts->expected_salt_len );
+        if( ret != 0 )
+        {
+            polarssl_free( pss_opts );
+            return( ret );
+        }
+
+        *sig_opts = (void *) pss_opts;
+    }
+    else
+#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */
+    {
+        /* Make sure parameters are absent or NULL */
+        if( ( sig_params->tag != ASN1_NULL && sig_params->tag != 0 ) ||
+              sig_params->len != 0 )
+        return( POLARSSL_ERR_X509_INVALID_ALG );
+    }
+
     return( 0 );
 }
 
@@ -444,7 +702,7 @@ int x509_load_file( const char *path, unsigned char **buf, size_t *n )
  * This fuction tries to 'fix' this by at least suggesting enlarging the
  * size by 20.
  */
-static int compat_snprintf(char *str, size_t size, const char *format, ...)
+static int compat_snprintf( char *str, size_t size, const char *format, ... )
 {
     va_list ap;
     int res = -1;
@@ -456,29 +714,29 @@ static int compat_snprintf(char *str, size_t size, const char *format, ...)
     va_end( ap );
 
     // No quick fix possible
-    if ( res < 0 )
+    if( res < 0 )
         return( (int) size + 20 );
 
-    return res;
+    return( res );
 }
 
 #define snprintf compat_snprintf
-#endif
+#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
 
 #define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
 
-#define SAFE_SNPRINTF()                         \
-{                                               \
-    if( ret == -1 )                             \
-        return( -1 );                           \
-                                                \
-    if ( (unsigned int) ret > n ) {             \
-        p[n - 1] = '\0';                        \
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
-    }                                           \
-                                                \
-    n -= (unsigned int) ret;                    \
-    p += (unsigned int) ret;                    \
+#define SAFE_SNPRINTF()                             \
+{                                                   \
+    if( ret == -1 )                                 \
+        return( -1 );                               \
+                                                    \
+    if( (unsigned int) ret > n ) {                  \
+        p[n - 1] = '\0';                            \
+        return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \
+    }                                               \
+                                                    \
+    n -= (unsigned int) ret;                        \
+    p += (unsigned int) ret;                        \
 }
 
 /*
@@ -576,6 +834,51 @@ int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
     return( (int) ( size - n ) );
 }
 
+/*
+ * Helper for writing signature algorithms
+ */
+int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid,
+                       pk_type_t pk_alg, md_type_t md_alg,
+                       const void *sig_opts )
+{
+    int ret;
+    char *p = buf;
+    size_t n = size;
+    const char *desc = NULL;
+
+    ret = oid_get_sig_alg_desc( sig_oid, &desc );
+    if( ret != 0 )
+        ret = snprintf( p, n, "???"  );
+    else
+        ret = snprintf( p, n, "%s", desc );
+    SAFE_SNPRINTF();
+
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+    if( pk_alg == POLARSSL_PK_RSASSA_PSS )
+    {
+        const pk_rsassa_pss_options *pss_opts;
+        const md_info_t *md_info, *mgf_md_info;
+
+        pss_opts = (const pk_rsassa_pss_options *) sig_opts;
+
+        md_info = md_info_from_type( md_alg );
+        mgf_md_info = md_info_from_type( pss_opts->mgf1_hash_id );
+
+        ret = snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
+                              md_info ? md_info->name : "???",
+                              mgf_md_info ? mgf_md_info->name : "???",
+                              pss_opts->expected_salt_len );
+        SAFE_SNPRINTF();
+    }
+#else
+    ((void) pk_alg);
+    ((void) md_alg);
+    ((void) sig_opts);
+#endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */
+
+    return( (int) size - n );
+}
+
 /*
  * Helper for writing "RSA key size", "EC key size", etc
  */
@@ -586,7 +889,7 @@ int x509_key_size_helper( char *buf, size_t size, const char *name )
     int ret;
 
     if( strlen( name ) + sizeof( " key size" ) > size )
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
+        return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL );
 
     ret = snprintf( p, n, "%s key size", name );
     SAFE_SNPRINTF();
@@ -620,78 +923,108 @@ int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
  * Return 0 if the x509_time is still valid, or 1 otherwise.
  */
 #if defined(POLARSSL_HAVE_TIME)
-int x509_time_expired( const x509_time *to )
-{
-    int year, mon, day;
-    int hour, min, sec;
 
+static void x509_get_current_time( x509_time *now )
+{
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
     SYSTEMTIME st;
 
-    GetLocalTime(&st);
+    GetSystemTime( &st );
 
-    year = st.wYear;
-    mon = st.wMonth;
-    day = st.wDay;
-    hour = st.wHour;
-    min = st.wMinute;
-    sec = st.wSecond;
+    now->year = st.wYear;
+    now->mon = st.wMonth;
+    now->day = st.wDay;
+    now->hour = st.wHour;
+    now->min = st.wMinute;
+    now->sec = st.wSecond;
 #else
-    struct tm *lt;
+    struct tm lt;
     time_t tt;
 
     tt = time( NULL );
-    lt = localtime( &tt );
-
-    year = lt->tm_year + 1900;
-    mon = lt->tm_mon + 1;
-    day = lt->tm_mday;
-    hour = lt->tm_hour;
-    min = lt->tm_min;
-    sec = lt->tm_sec;
-#endif
+    gmtime_r( &tt, &lt );
+
+    now->year = lt.tm_year + 1900;
+    now->mon = lt.tm_mon + 1;
+    now->day = lt.tm_mday;
+    now->hour = lt.tm_hour;
+    now->min = lt.tm_min;
+    now->sec = lt.tm_sec;
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+}
 
-    if( year  > to->year )
+/*
+ * Return 0 if before <= after, 1 otherwise
+ */
+static int x509_check_time( const x509_time *before, const x509_time *after )
+{
+    if( before->year  > after->year )
         return( 1 );
 
-    if( year == to->year &&
-        mon   > to->mon )
+    if( before->year == after->year &&
+        before->mon   > after->mon )
         return( 1 );
 
-    if( year == to->year &&
-        mon  == to->mon  &&
-        day   > to->day )
+    if( before->year == after->year &&
+        before->mon  == after->mon  &&
+        before->day   > after->day )
         return( 1 );
 
-    if( year == to->year &&
-        mon  == to->mon  &&
-        day  == to->day  &&
-        hour  > to->hour )
+    if( before->year == after->year &&
+        before->mon  == after->mon  &&
+        before->day  == after->day  &&
+        before->hour  > after->hour )
         return( 1 );
 
-    if( year == to->year &&
-        mon  == to->mon  &&
-        day  == to->day  &&
-        hour == to->hour &&
-        min   > to->min  )
+    if( before->year == after->year &&
+        before->mon  == after->mon  &&
+        before->day  == after->day  &&
+        before->hour == after->hour &&
+        before->min   > after->min  )
         return( 1 );
 
-    if( year == to->year &&
-        mon  == to->mon  &&
-        day  == to->day  &&
-        hour == to->hour &&
-        min  == to->min  &&
-        sec   > to->sec  )
+    if( before->year == after->year &&
+        before->mon  == after->mon  &&
+        before->day  == after->day  &&
+        before->hour == after->hour &&
+        before->min  == after->min  &&
+        before->sec   > after->sec  )
         return( 1 );
 
     return( 0 );
 }
+
+int x509_time_expired( const x509_time *to )
+{
+    x509_time now;
+
+    x509_get_current_time( &now );
+
+    return( x509_check_time( &now, to ) );
+}
+
+int x509_time_future( const x509_time *from )
+{
+    x509_time now;
+
+    x509_get_current_time( &now );
+
+    return( x509_check_time( from, &now ) );
+}
+
 #else  /* POLARSSL_HAVE_TIME */
+
 int x509_time_expired( const x509_time *to )
 {
     ((void) to);
     return( 0 );
 }
+
+int x509_time_future( const x509_time *from )
+{
+    ((void) from);
+    return( 0 );
+}
 #endif /* POLARSSL_HAVE_TIME */
 
 #if defined(POLARSSL_SELF_TEST)
@@ -704,14 +1037,14 @@ int x509_time_expired( const x509_time *to )
  */
 int x509_self_test( int verbose )
 {
-#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
+#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_SHA1_C)
     int ret;
     int flags;
     x509_crt cacert;
     x509_crt clicert;
 
     if( verbose != 0 )
-        printf( "  X.509 certificate load: " );
+        polarssl_printf( "  X.509 certificate load: " );
 
     x509_crt_init( &clicert );
 
@@ -720,7 +1053,7 @@ int x509_self_test( int verbose )
     if( ret != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( ret );
     }
@@ -732,27 +1065,27 @@ int x509_self_test( int verbose )
     if( ret != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
         return( ret );
     }
 
     if( verbose != 0 )
-        printf( "passed\n  X.509 signature verify: ");
+        polarssl_printf( "passed\n  X.509 signature verify: ");
 
     ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
     if( ret != 0 )
     {
         if( verbose != 0 )
-            printf( "failed\n" );
+            polarssl_printf( "failed\n" );
 
-        printf("ret = %d, &flags = %04x\n", ret, flags);
+        polarssl_printf( "ret = %d, &flags = %04x\n", ret, flags );
 
         return( ret );
     }
 
     if( verbose != 0 )
-        printf( "passed\n\n");
+        polarssl_printf( "passed\n\n");
 
     x509_crt_free( &cacert  );
     x509_crt_free( &clicert );
@@ -761,9 +1094,9 @@ int x509_self_test( int verbose )
 #else
     ((void) verbose);
     return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-#endif
+#endif /* POLARSSL_CERTS_C && POLARSSL_SHA1_C */
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
 #endif /* POLARSSL_X509_USE_C */
index fdf2a7246eeccd56c474847ee01f5cdf8dace278..1019313327c74c09640942dfbfdc25fd02d3ab9a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  X.509 base functions for creating certificates / CSRs
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_X509_CREATE_C)
 
 #define strncasecmp _strnicmp
 #endif
 
+typedef struct {
+    const char *name;
+    size_t name_len;
+    const char*oid;
+} x509_attr_descriptor_t;
+
+#define ADD_STRLEN( s )     s, sizeof( s ) - 1
+
+static const x509_attr_descriptor_t x509_attrs[] =
+{
+    { ADD_STRLEN( "CN" ),                       OID_AT_CN },
+    { ADD_STRLEN( "commonName" ),               OID_AT_CN },
+    { ADD_STRLEN( "C" ),                        OID_AT_COUNTRY },
+    { ADD_STRLEN( "countryName" ),              OID_AT_COUNTRY },
+    { ADD_STRLEN( "O" ),                        OID_AT_ORGANIZATION },
+    { ADD_STRLEN( "organizationName" ),         OID_AT_ORGANIZATION },
+    { ADD_STRLEN( "L" ),                        OID_AT_LOCALITY },
+    { ADD_STRLEN( "locality" ),                 OID_AT_LOCALITY },
+    { ADD_STRLEN( "R" ),                        OID_PKCS9_EMAIL },
+    { ADD_STRLEN( "OU" ),                       OID_AT_ORG_UNIT },
+    { ADD_STRLEN( "organizationalUnitName" ),   OID_AT_ORG_UNIT },
+    { ADD_STRLEN( "ST" ),                       OID_AT_STATE },
+    { ADD_STRLEN( "stateOrProvinceName" ),      OID_AT_STATE },
+    { ADD_STRLEN( "emailAddress" ),             OID_PKCS9_EMAIL },
+    { ADD_STRLEN( "serialNumber" ),             OID_AT_SERIAL_NUMBER },
+    { ADD_STRLEN( "postalAddress" ),            OID_AT_POSTAL_ADDRESS },
+    { ADD_STRLEN( "postalCode" ),               OID_AT_POSTAL_CODE },
+    { ADD_STRLEN( "dnQualifier" ),              OID_AT_DN_QUALIFIER },
+    { ADD_STRLEN( "title" ),                    OID_AT_TITLE },
+    { ADD_STRLEN( "surName" ),                  OID_AT_SUR_NAME },
+    { ADD_STRLEN( "SN" ),                       OID_AT_SUR_NAME },
+    { ADD_STRLEN( "givenName" ),                OID_AT_GIVEN_NAME },
+    { ADD_STRLEN( "GN" ),                       OID_AT_GIVEN_NAME },
+    { ADD_STRLEN( "initials" ),                 OID_AT_INITIALS },
+    { ADD_STRLEN( "pseudonym" ),                OID_AT_PSEUDONYM },
+    { ADD_STRLEN( "generationQualifier" ),      OID_AT_GENERATION_QUALIFIER },
+    { ADD_STRLEN( "domainComponent" ),          OID_DOMAIN_COMPONENT },
+    { ADD_STRLEN( "DC" ),                       OID_DOMAIN_COMPONENT },
+    { NULL, 0, NULL }
+};
+
+static const char *x509_at_oid_from_name( const char *name, size_t name_len )
+{
+    const x509_attr_descriptor_t *cur;
+
+    for( cur = x509_attrs; cur->name != NULL; cur++ )
+        if( cur->name_len == name_len &&
+            strncasecmp( cur->name, name, name_len ) == 0 )
+            break;
+
+    return( cur->oid );
+}
+
 int x509_string_to_names( asn1_named_data **head, const char *name )
 {
     int ret = 0;
@@ -43,7 +100,6 @@ int x509_string_to_names( asn1_named_data **head, const char *name )
     const char *end = s + strlen( s );
     const char *oid = NULL;
     int in_tag = 1;
-    asn1_named_data *cur;
 
     /* Clear existing chain if present */
     asn1_free_named_data_list( head );
@@ -52,27 +108,7 @@ int x509_string_to_names( asn1_named_data **head, const char *name )
     {
         if( in_tag && *c == '=' )
         {
-            if( c - s == 2 && strncasecmp( s, "CN", 2 ) == 0 )
-                oid = OID_AT_CN;
-            else if( c - s == 1 && strncasecmp( s, "C", 1 ) == 0 )
-                oid = OID_AT_COUNTRY;
-            else if( c - s == 1 && strncasecmp( s, "O", 1 ) == 0 )
-                oid = OID_AT_ORGANIZATION;
-            else if( c - s == 1 && strncasecmp( s, "L", 1 ) == 0 )
-                oid = OID_AT_LOCALITY;
-            else if( c - s == 1 && strncasecmp( s, "R", 1 ) == 0 )
-                oid = OID_PKCS9_EMAIL;
-            else if( c - s == 2 && strncasecmp( s, "OU", 2 ) == 0 )
-                oid = OID_AT_ORG_UNIT;
-            else if( c - s == 2 && strncasecmp( s, "ST", 2 ) == 0 )
-                oid = OID_AT_STATE;
-            else if( c - s == 12 && strncasecmp( s, "serialNumber", 12 ) == 0 )
-                oid = OID_AT_SERIAL_NUMBER;
-            else if( c - s == 13 && strncasecmp( s, "postalAddress", 13 ) == 0 )
-                oid = OID_AT_POSTAL_ADDRESS;
-            else if( c - s == 10 && strncasecmp( s, "postalCode", 10 ) == 0 )
-                oid = OID_AT_POSTAL_CODE;
-            else
+            if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL )
             {
                 ret = POLARSSL_ERR_X509_UNKNOWN_OID;
                 goto exit;
@@ -84,9 +120,9 @@ int x509_string_to_names( asn1_named_data **head, const char *name )
 
         if( !in_tag && ( *c == ',' || c == end ) )
         {
-            if( ( cur = asn1_store_named_data( head, oid, strlen( oid ),
-                                               (unsigned char *) s,
-                                               c - s ) ) == NULL )
+            if( asn1_store_named_data( head, oid, strlen( oid ),
+                                       (unsigned char *) s,
+                                       c - s ) == NULL )
             {
                 return( POLARSSL_ERR_X509_MALLOC_FAILED );
             }
@@ -165,10 +201,12 @@ static int x509_write_name( unsigned char **p, unsigned char *start,
     ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) );
 
     ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
 
     ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SET ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SET ) );
 
     return( (int) len );
 }
@@ -189,7 +227,8 @@ int x509_write_names( unsigned char **p, unsigned char *start,
     }
 
     ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
 
     return( (int) len );
 }
@@ -244,7 +283,8 @@ static int x509_write_extension( unsigned char **p, unsigned char *start,
     ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) );
 
     ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
 
     return( (int) len );
 }
index 60a54f2e70ba8d8ce9898548454d4c30e4563bbf..7dd53c2f60546b95fd1d4d7373ac1dbc4278cb90 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  X.509 certificate and private key decoding
+ *  X.509 Certidicate Revocation List (CRL) parsing
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 /*
  *  The ITU-T X.509 standard defines a certificate format for PKI.
  *
- *  http://www.ietf.org/rfc/rfc3279.txt
- *  http://www.ietf.org/rfc/rfc3280.txt
- *
- *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
+ *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
+ *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
  *
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_X509_CRL_PARSE_C)
 
@@ -44,8 +47,8 @@
 #include "polarssl/pem.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #include <stdio.h>
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  *  Version  ::=  INTEGER  {  v1(0), v2(1)  }
  */
@@ -133,7 +141,7 @@ static int x509_get_crl_entry_ext( unsigned char **p,
     size_t len = 0;
 
     /* OPTIONAL */
-    if (end <= *p)
+    if( end <= *p )
         return( 0 );
 
     ext->tag = **p;
@@ -154,7 +162,7 @@ static int x509_get_crl_entry_ext( unsigned char **p,
         return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
     }
 
-       end = *p + ext->len;
+    end = *p + ext->len;
 
     if( end != *p + ext->len )
         return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
@@ -220,13 +228,15 @@ static int x509_get_entries( unsigned char **p,
         if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
             return( ret );
 
-        if( ( ret = x509_get_time( p, end2, &cur_entry->revocation_date ) ) != 0 )
+        if( ( ret = x509_get_time( p, end2,
+                                   &cur_entry->revocation_date ) ) != 0 )
             return( ret );
 
-        if( ( ret = x509_get_crl_entry_ext( p, end2, &cur_entry->entry_ext ) ) != 0 )
+        if( ( ret = x509_get_crl_entry_ext( p, end2,
+                                            &cur_entry->entry_ext ) ) != 0 )
             return( ret );
 
-        if ( *p < end )
+        if( *p < end )
         {
             cur_entry->next = polarssl_malloc( sizeof( x509_crl_entry ) );
 
@@ -250,11 +260,16 @@ int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
     size_t len;
     unsigned char *p, *end;
     x509_crl *crl;
+    x509_buf sig_params1, sig_params2;
+
 #if defined(POLARSSL_PEM_PARSE_C)
     size_t use_len;
     pem_context pem;
 #endif
 
+    memset( &sig_params1, 0, sizeof( x509_buf ) );
+    memset( &sig_params2, 0, sizeof( x509_buf ) );
+
     crl = chain;
 
     /*
@@ -269,7 +284,7 @@ int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
     /*
      * Add new CRL on the end of the chain if needed.
      */
-    if ( crl->version != 0 && crl->next == NULL)
+    if( crl->version != 0 && crl->next == NULL )
     {
         crl->next = (x509_crl *) polarssl_malloc( sizeof( x509_crl ) );
 
@@ -312,7 +327,7 @@ int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
         return( ret );
     }
     else
-#endif
+#endif /* POLARSSL_PEM_PARSE_C */
     {
         /*
          * nope, copy the raw DER data
@@ -373,7 +388,7 @@ int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
      * signature            AlgorithmIdentifier
      */
     if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
-        ( ret = x509_get_alg_null( &p, end, &crl->sig_oid1   ) ) != 0 )
+        ( ret = x509_get_alg( &p, end, &crl->sig_oid1, &sig_params1 ) ) != 0 )
     {
         x509_crl_free( crl );
         return( ret );
@@ -387,8 +402,9 @@ int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
         return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
     }
 
-    if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &crl->sig_md,
-                                  &crl->sig_pk ) ) != 0 )
+    if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &sig_params1,
+                                  &crl->sig_md, &crl->sig_pk,
+                                  &crl->sig_opts ) ) != 0 )
     {
         x509_crl_free( crl );
         return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG );
@@ -426,9 +442,9 @@ int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
 
     if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 )
     {
-        if ( ret != ( POLARSSL_ERR_X509_INVALID_DATE +
+        if( ret != ( POLARSSL_ERR_X509_INVALID_DATE +
                         POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) &&
-             ret != ( POLARSSL_ERR_X509_INVALID_DATE +
+            ret != ( POLARSSL_ERR_X509_INVALID_DATE +
                         POLARSSL_ERR_ASN1_OUT_OF_DATA ) )
         {
             x509_crl_free( crl );
@@ -478,14 +494,16 @@ int x509_crl_parse( x509_crl *chain, const unsigned char *buf, size_t buflen )
      *  signatureAlgorithm   AlgorithmIdentifier,
      *  signatureValue       BIT STRING
      */
-    if( ( ret = x509_get_alg_null( &p, end, &crl->sig_oid2 ) ) != 0 )
+    if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2, &sig_params2 ) ) != 0 )
     {
         x509_crl_free( crl );
         return( ret );
     }
 
     if( crl->sig_oid1.len != crl->sig_oid2.len ||
-        memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 )
+        memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 ||
+        sig_params1.len != sig_params2.len ||
+        memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 )
     {
         x509_crl_free( crl );
         return( POLARSSL_ERR_X509_SIG_MISMATCH );
@@ -533,12 +551,12 @@ int x509_crl_parse_file( x509_crl *chain, const char *path )
     size_t n;
     unsigned char *buf;
 
-    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+    if( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
         return( ret );
 
     ret = x509_crl_parse( chain, buf, n );
 
-    memset( buf, 0, n + 1 );
+    polarssl_zeroize( buf, n + 1 );
     polarssl_free( buf );
 
     return( ret );
@@ -560,7 +578,7 @@ int x509_crl_parse_file( x509_crl *chain, const char *path )
  * This fuction tries to 'fix' this by at least suggesting enlarging the
  * size by 20.
  */
-static int compat_snprintf(char *str, size_t size, const char *format, ...)
+static int compat_snprintf( char *str, size_t size, const char *format, ... )
 {
     va_list ap;
     int res = -1;
@@ -572,29 +590,29 @@ static int compat_snprintf(char *str, size_t size, const char *format, ...)
     va_end( ap );
 
     // No quick fix possible
-    if ( res < 0 )
+    if( res < 0 )
         return( (int) size + 20 );
 
-    return res;
+    return( res );
 }
 
 #define snprintf compat_snprintf
-#endif
+#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
 
 #define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
 
-#define SAFE_SNPRINTF()                         \
-{                                               \
-    if( ret == -1 )                             \
-        return( -1 );                           \
-                                                \
-    if ( (unsigned int) ret > n ) {             \
-        p[n - 1] = '\0';                        \
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
-    }                                           \
-                                                \
-    n -= (unsigned int) ret;                    \
-    p += (unsigned int) ret;                    \
+#define SAFE_SNPRINTF()                             \
+{                                                   \
+    if( ret == -1 )                                 \
+        return( -1 );                               \
+                                                    \
+    if( (unsigned int) ret > n ) {                  \
+        p[n - 1] = '\0';                            \
+        return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \
+    }                                               \
+                                                    \
+    n -= (unsigned int) ret;                        \
+    p += (unsigned int) ret;                        \
 }
 
 /*
@@ -611,7 +629,6 @@ int x509_crl_info( char *buf, size_t size, const char *prefix,
     int ret;
     size_t n;
     char *p;
-    const char *desc;
     const x509_crl_entry *entry;
 
     p = buf;
@@ -652,7 +669,7 @@ int x509_crl_info( char *buf, size_t size, const char *prefix,
                                prefix );
         SAFE_SNPRINTF();
 
-        ret = x509_serial_gets( p, n, &entry->serial);
+        ret = x509_serial_gets( p, n, &entry->serial );
         SAFE_SNPRINTF();
 
         ret = snprintf( p, n, " revocation date: " \
@@ -668,11 +685,8 @@ int x509_crl_info( char *buf, size_t size, const char *prefix,
     ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
     SAFE_SNPRINTF();
 
-    ret = oid_get_sig_alg_desc( &crl->sig_oid1, &desc );
-    if( ret != 0 )
-        ret = snprintf( p, n, "???"  );
-    else
-        ret = snprintf( p, n, "%s", desc );
+    ret = x509_sig_alg_gets( p, n, &crl->sig_oid1, crl->sig_pk, crl->sig_md,
+                             crl->sig_opts );
     SAFE_SNPRINTF();
 
     ret = snprintf( p, n, "\n" );
@@ -706,12 +720,16 @@ void x509_crl_free( x509_crl *crl )
 
     do
     {
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+        polarssl_free( crl_cur->sig_opts );
+#endif
+
         name_cur = crl_cur->issuer.next;
         while( name_cur != NULL )
         {
             name_prv = name_cur;
             name_cur = name_cur->next;
-            memset( name_prv, 0, sizeof( x509_name ) );
+            polarssl_zeroize( name_prv, sizeof( x509_name ) );
             polarssl_free( name_prv );
         }
 
@@ -720,13 +738,13 @@ void x509_crl_free( x509_crl *crl )
         {
             entry_prv = entry_cur;
             entry_cur = entry_cur->next;
-            memset( entry_prv, 0, sizeof( x509_crl_entry ) );
+            polarssl_zeroize( entry_prv, sizeof( x509_crl_entry ) );
             polarssl_free( entry_prv );
         }
 
         if( crl_cur->raw.p != NULL )
         {
-            memset( crl_cur->raw.p, 0, crl_cur->raw.len );
+            polarssl_zeroize( crl_cur->raw.p, crl_cur->raw.len );
             polarssl_free( crl_cur->raw.p );
         }
 
@@ -740,11 +758,11 @@ void x509_crl_free( x509_crl *crl )
         crl_prv = crl_cur;
         crl_cur = crl_cur->next;
 
-        memset( crl_prv, 0, sizeof( x509_crl ) );
+        polarssl_zeroize( crl_prv, sizeof( x509_crl ) );
         if( crl_prv != crl )
             polarssl_free( crl_prv );
     }
     while( crl_cur != NULL );
 }
 
-#endif
+#endif /* POLARSSL_X509_CRL_PARSE_C */
index 6a127b267258054c9237112af622426a719bc6d1..03cdda807909f677ece242e98a60a0f086c9a8c6 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  X.509 certificate and private key decoding
+ *  X.509 certificate parsing and verification
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 /*
  *  The ITU-T X.509 standard defines a certificate format for PKI.
  *
- *  http://www.ietf.org/rfc/rfc3279.txt
- *  http://www.ietf.org/rfc/rfc3280.txt
- *
- *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
+ *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
+ *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
  *
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_X509_CRT_PARSE_C)
 
 #include "polarssl/pem.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #endif
 
+#if defined(POLARSSL_THREADING_C)
+#include "polarssl/threading.h"
+#endif
+
 #include <string.h>
 #include <stdlib.h>
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
 
 #if defined(POLARSSL_FS_IO)
 #include <stdio.h>
-#if !defined(_WIN32)
+#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <dirent.h>
 #endif
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
  */
@@ -188,7 +200,7 @@ static int x509_get_basic_constraints( unsigned char **p,
         return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
 
     if( *p == end )
-        return 0;
+        return( 0 );
 
     if( ( ret = asn1_get_bool( p, end, ca_istrue ) ) != 0 )
     {
@@ -203,7 +215,7 @@ static int x509_get_basic_constraints( unsigned char **p,
     }
 
     if( *p == end )
-        return 0;
+        return( 0 );
 
     if( ( ret = asn1_get_int( p, end, max_pathlen ) ) != 0 )
         return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
@@ -214,7 +226,7 @@ static int x509_get_basic_constraints( unsigned char **p,
 
     (*max_pathlen)++;
 
-    return 0;
+    return( 0 );
 }
 
 static int x509_get_ns_cert_type( unsigned char **p,
@@ -233,7 +245,7 @@ static int x509_get_ns_cert_type( unsigned char **p,
 
     /* Get actual bitstring */
     *ns_cert_type = *bs.p;
-    return 0;
+    return( 0 );
 }
 
 static int x509_get_key_usage( unsigned char **p,
@@ -252,7 +264,7 @@ static int x509_get_key_usage( unsigned char **p,
 
     /* Get actual bitstring */
     *key_usage = *bs.p;
-    return 0;
+    return( 0 );
 }
 
 /*
@@ -274,7 +286,7 @@ static int x509_get_ext_key_usage( unsigned char **p,
         return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
                 POLARSSL_ERR_ASN1_INVALID_LENGTH );
 
-    return 0;
+    return( 0 );
 }
 
 /*
@@ -337,20 +349,15 @@ static int x509_get_subject_alt_name( unsigned char **p,
             return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
                     POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
 
+        /* Skip everything but DNS name */
         if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) )
         {
             *p += tag_len;
             continue;
         }
 
-        buf = &(cur->buf);
-        buf->tag = tag;
-        buf->p = *p;
-        buf->len = tag_len;
-        *p += buf->len;
-
         /* Allocate and assign next pointer */
-        if (*p < end)
+        if( cur->buf.p != NULL )
         {
             cur->next = (asn1_sequence *) polarssl_malloc(
                  sizeof( asn1_sequence ) );
@@ -362,6 +369,12 @@ static int x509_get_subject_alt_name( unsigned char **p,
             memset( cur->next, 0, sizeof( asn1_sequence ) );
             cur = cur->next;
         }
+
+        buf = &(cur->buf);
+        buf->tag = tag;
+        buf->p = *p;
+        buf->len = tag_len;
+        *p += buf->len;
     }
 
     /* Set final sequence entry's next pointer to NULL */
@@ -458,7 +471,7 @@ static int x509_get_crt_ext( unsigned char **p,
             if( is_critical )
             {
                 /* Data is marked as critical: fail */
-                return ( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+                return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
                         POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
             }
 #endif
@@ -473,35 +486,35 @@ static int x509_get_crt_ext( unsigned char **p,
             /* Parse basic constraints */
             if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
                     &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
-                return ( ret );
+                return( ret );
             break;
 
         case EXT_KEY_USAGE:
             /* Parse key usage */
             if( ( ret = x509_get_key_usage( p, end_ext_octet,
                     &crt->key_usage ) ) != 0 )
-                return ( ret );
+                return( ret );
             break;
 
         case EXT_EXTENDED_KEY_USAGE:
             /* Parse extended key usage */
             if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
                     &crt->ext_key_usage ) ) != 0 )
-                return ( ret );
+                return( ret );
             break;
 
         case EXT_SUBJECT_ALT_NAME:
             /* Parse subject alt name */
             if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
                     &crt->subject_alt_names ) ) != 0 )
-                return ( ret );
+                return( ret );
             break;
 
         case EXT_NS_CERT_TYPE:
             /* Parse netscape certificate type */
             if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
                     &crt->ns_cert_type ) ) != 0 )
-                return ( ret );
+                return( ret );
             break;
 
         default:
@@ -525,6 +538,10 @@ static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
     int ret;
     size_t len;
     unsigned char *p, *end, *crt_end;
+    x509_buf sig_params1, sig_params2;
+
+    memset( &sig_params1, 0, sizeof( x509_buf ) );
+    memset( &sig_params2, 0, sizeof( x509_buf ) );
 
     /*
      * Check for valid input
@@ -539,8 +556,6 @@ static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
 
     memcpy( p, buf, buflen );
 
-    buflen = 0;
-
     crt->raw.p = p;
     crt->raw.len = len;
     end = p + len;
@@ -590,7 +605,8 @@ static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
      */
     if( ( ret = x509_get_version(  &p, end, &crt->version  ) ) != 0 ||
         ( ret = x509_get_serial(   &p, end, &crt->serial   ) ) != 0 ||
-        ( ret = x509_get_alg_null( &p, end, &crt->sig_oid1 ) ) != 0 )
+        ( ret = x509_get_alg(      &p, end, &crt->sig_oid1,
+                                            &sig_params1 ) ) != 0 )
     {
         x509_crt_free( crt );
         return( ret );
@@ -604,8 +620,9 @@ static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
         return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
     }
 
-    if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &crt->sig_md,
-                                  &crt->sig_pk ) ) != 0 )
+    if( ( ret = x509_get_sig_alg( &crt->sig_oid1, &sig_params1,
+                                  &crt->sig_md, &crt->sig_pk,
+                                  &crt->sig_opts ) ) != 0 )
     {
         x509_crt_free( crt );
         return( ret );
@@ -705,7 +722,7 @@ static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
     if( crt->version == 3 )
     {
 #endif
-        ret = x509_get_crt_ext( &p, end, crt);
+        ret = x509_get_crt_ext( &p, end, crt );
         if( ret != 0 )
         {
             x509_crt_free( crt );
@@ -731,14 +748,16 @@ static int x509_crt_parse_der_core( x509_crt *crt, const unsigned char *buf,
      *  signatureAlgorithm   AlgorithmIdentifier,
      *  signatureValue       BIT STRING
      */
-    if( ( ret = x509_get_alg_null( &p, end, &crt->sig_oid2 ) ) != 0 )
+    if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2, &sig_params2 ) ) != 0 )
     {
         x509_crt_free( crt );
         return( ret );
     }
 
     if( crt->sig_oid1.len != crt->sig_oid2.len ||
-        memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 )
+        memcmp( crt->sig_oid1.p, crt->sig_oid2.p, crt->sig_oid1.len ) != 0 ||
+        sig_params1.len != sig_params2.len ||
+        memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 )
     {
         x509_crt_free( crt );
         return( POLARSSL_ERR_X509_SIG_MISMATCH );
@@ -785,7 +804,7 @@ int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf,
     /*
      * Add new certificate on the end of the chain if needed.
      */
-    if ( crt->version != 0 && crt->next == NULL)
+    if( crt->version != 0 && crt->next == NULL )
     {
         crt->next = (x509_crt *) polarssl_malloc( sizeof( x509_crt ) );
 
@@ -812,7 +831,8 @@ int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf,
 }
 
 /*
- * Parse one or more PEM certificates from a buffer and add them to the chained list
+ * Parse one or more PEM certificates from a buffer and add them to the chained
+ * list
  */
 int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen )
 {
@@ -905,7 +925,7 @@ int x509_crt_parse( x509_crt *chain, const unsigned char *buf, size_t buflen )
             success = 1;
         }
     }
-#endif
+#endif /* POLARSSL_PEM_PARSE_C */
 
     if( success )
         return( total_failed );
@@ -925,17 +945,21 @@ int x509_crt_parse_file( x509_crt *chain, const char *path )
     size_t n;
     unsigned char *buf;
 
-    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+    if( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
         return( ret );
 
     ret = x509_crt_parse( chain, buf, n );
 
-    memset( buf, 0, n + 1 );
+    polarssl_zeroize( buf, n + 1 );
     polarssl_free( buf );
 
     return( ret );
 }
 
+#if defined(POLARSSL_THREADING_PTHREAD)
+static threading_mutex_t readdir_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
 int x509_crt_parse_path( x509_crt *chain, const char *path )
 {
     int ret = 0;
@@ -943,40 +967,41 @@ int x509_crt_parse_path( x509_crt *chain, const char *path )
     int w_ret;
     WCHAR szDir[MAX_PATH];
     char filename[MAX_PATH];
-       char *p;
+    char *p;
     int len = (int) strlen( path );
 
-       WIN32_FIND_DATAW file_data;
+    WIN32_FIND_DATAW file_data;
     HANDLE hFind;
 
     if( len > MAX_PATH - 3 )
         return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
 
-       memset( szDir, 0, sizeof(szDir) );
-       memset( filename, 0, MAX_PATH );
-       memcpy( filename, path, len );
-       filename[len++] = '\\';
-       p = filename + len;
+    memset( szDir, 0, sizeof(szDir) );
+    memset( filename, 0, MAX_PATH );
+    memcpy( filename, path, len );
+    filename[len++] = '\\';
+    p = filename + len;
     filename[len++] = '*';
 
-       w_ret = MultiByteToWideChar( CP_ACP, 0, path, len, szDir, MAX_PATH - 3 );
+    w_ret = MultiByteToWideChar( CP_ACP, 0, filename, len, szDir,
+                                 MAX_PATH - 3 );
 
     hFind = FindFirstFileW( szDir, &file_data );
-    if (hFind == INVALID_HANDLE_VALUE)
+    if( hFind == INVALID_HANDLE_VALUE )
         return( POLARSSL_ERR_X509_FILE_IO_ERROR );
 
     len = MAX_PATH - len;
     do
     {
-               memset( p, 0, len );
+        memset( p, 0, len );
 
         if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
             continue;
 
-               w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
-                                                                        lstrlenW(file_data.cFileName),
-                                                                        p, len - 1,
-                                                                        NULL, NULL );
+        w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
+                                     lstrlenW( file_data.cFileName ),
+                                     p, len - 1,
+                                     NULL, NULL );
 
         w_ret = x509_crt_parse_file( chain, filename );
         if( w_ret < 0 )
@@ -986,34 +1011,34 @@ int x509_crt_parse_path( x509_crt *chain, const char *path )
     }
     while( FindNextFileW( hFind, &file_data ) != 0 );
 
-    if (GetLastError() != ERROR_NO_MORE_FILES)
+    if( GetLastError() != ERROR_NO_MORE_FILES )
         ret = POLARSSL_ERR_X509_FILE_IO_ERROR;
 
     FindClose( hFind );
 #else /* _WIN32 */
-#if defined(POLARSSL_HAVE_READDIR_R)
-    int t_ret, i;
+    int t_ret;
     struct stat sb;
-    struct dirent entry, *result = NULL;
+    struct dirent *entry;
     char entry_name[255];
     DIR *dir = opendir( path );
 
-    if( dir == NULL)
+    if( dir == NULL )
         return( POLARSSL_ERR_X509_FILE_IO_ERROR );
 
-    while( ( t_ret = readdir_r( dir, &entry, &result ) ) == 0 )
-    {
-        if( result == NULL )
-            break;
-
-        snprintf( entry_name, sizeof(entry_name), "%s/%s", path, entry.d_name );
+#if defined(POLARSSL_THREADING_PTHREAD)
+    if( ( ret = polarssl_mutex_lock( &readdir_mutex ) ) != 0 )
+        return( ret );
+#endif
 
-        i = stat( entry_name, &sb );
+    while( ( entry = readdir( dir ) ) != NULL )
+    {
+        snprintf( entry_name, sizeof entry_name, "%s/%s", path, entry->d_name );
 
-        if( i == -1 )
+        if( stat( entry_name, &sb ) == -1 )
         {
             closedir( dir );
-            return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+            ret = POLARSSL_ERR_X509_FILE_IO_ERROR;
+            goto cleanup;
         }
 
         if( !S_ISREG( sb.st_mode ) )
@@ -1028,11 +1053,13 @@ int x509_crt_parse_path( x509_crt *chain, const char *path )
             ret += t_ret;
     }
     closedir( dir );
-#else /* POLARSSL_HAVE_READDIR_R */
-    ((void) chain);
-    ((void) path);
-    ret = POLARSSL_ERR_X509_FEATURE_UNAVAILABLE;
-#endif /* POLARSSL_HAVE_READDIR_R */
+
+cleanup:
+#if defined(POLARSSL_THREADING_PTHREAD)
+    if( polarssl_mutex_unlock( &readdir_mutex ) != 0 )
+        ret = POLARSSL_ERR_THREADING_MUTEX_ERROR;
+#endif
+
 #endif /* _WIN32 */
 
     return( ret );
@@ -1054,7 +1081,7 @@ int x509_crt_parse_path( x509_crt *chain, const char *path )
  * This fuction tries to 'fix' this by at least suggesting enlarging the
  * size by 20.
  */
-static int compat_snprintf(char *str, size_t size, const char *format, ...)
+static int compat_snprintf( char *str, size_t size, const char *format, ... )
 {
     va_list ap;
     int res = -1;
@@ -1066,105 +1093,330 @@ static int compat_snprintf(char *str, size_t size, const char *format, ...)
     va_end( ap );
 
     // No quick fix possible
-    if ( res < 0 )
+    if( res < 0 )
         return( (int) size + 20 );
 
-    return res;
+    return( res );
 }
 
 #define snprintf compat_snprintf
-#endif
+#endif /* _MSC_VER  && !snprintf && !EFIX64 && !EFI32 */
 
 #define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
 
-#define SAFE_SNPRINTF()                         \
-{                                               \
-    if( ret == -1 )                             \
-        return( -1 );                           \
-                                                \
-    if ( (unsigned int) ret > n ) {             \
-        p[n - 1] = '\0';                        \
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
-    }                                           \
-                                                \
-    n -= (unsigned int) ret;                    \
-    p += (unsigned int) ret;                    \
+#define SAFE_SNPRINTF()                             \
+{                                                   \
+    if( ret == -1 )                                 \
+        return( -1 );                               \
+                                                    \
+    if( (unsigned int) ret > n ) {                  \
+        p[n - 1] = '\0';                            \
+        return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \
+    }                                               \
+                                                    \
+    n -= (unsigned int) ret;                        \
+    p += (unsigned int) ret;                        \
+}
+
+static int x509_info_subject_alt_name( char **buf, size_t *size,
+                                       const x509_sequence *subject_alt_name )
+{
+    size_t i;
+    size_t n = *size;
+    char *p = *buf;
+    const x509_sequence *cur = subject_alt_name;
+    const char *sep = "";
+    size_t sep_len = 0;
+
+    while( cur != NULL )
+    {
+        if( cur->buf.len + sep_len >= n )
+        {
+            *p = '\0';
+            return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL );
+        }
+
+        n -= cur->buf.len + sep_len;
+        for( i = 0; i < sep_len; i++ )
+            *p++ = sep[i];
+        for( i = 0; i < cur->buf.len; i++ )
+            *p++ = cur->buf.p[i];
+
+        sep = ", ";
+        sep_len = 2;
+
+        cur = cur->next;
+    }
+
+    *p = '\0';
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
+
+#define PRINT_ITEM(i)                           \
+    {                                           \
+        ret = snprintf( p, n, "%s" i, sep );    \
+        SAFE_SNPRINTF();                        \
+        sep = ", ";                             \
+    }
+
+#define CERT_TYPE(type,name)                    \
+    if( ns_cert_type & type )                   \
+        PRINT_ITEM( name );
+
+static int x509_info_cert_type( char **buf, size_t *size,
+                                unsigned char ns_cert_type )
+{
+    int ret;
+    size_t n = *size;
+    char *p = *buf;
+    const char *sep = "";
+
+    CERT_TYPE( NS_CERT_TYPE_SSL_CLIENT,         "SSL Client" );
+    CERT_TYPE( NS_CERT_TYPE_SSL_SERVER,         "SSL Server" );
+    CERT_TYPE( NS_CERT_TYPE_EMAIL,              "Email" );
+    CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING,     "Object Signing" );
+    CERT_TYPE( NS_CERT_TYPE_RESERVED,           "Reserved" );
+    CERT_TYPE( NS_CERT_TYPE_SSL_CA,             "SSL CA" );
+    CERT_TYPE( NS_CERT_TYPE_EMAIL_CA,           "Email CA" );
+    CERT_TYPE( NS_CERT_TYPE_OBJECT_SIGNING_CA,  "Object Signing CA" );
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
+
+#define KEY_USAGE(code,name)    \
+    if( key_usage & code )      \
+        PRINT_ITEM( name );
+
+static int x509_info_key_usage( char **buf, size_t *size,
+                                unsigned char key_usage )
+{
+    int ret;
+    size_t n = *size;
+    char *p = *buf;
+    const char *sep = "";
+
+    KEY_USAGE( KU_DIGITAL_SIGNATURE,    "Digital Signature" );
+    KEY_USAGE( KU_NON_REPUDIATION,      "Non Repudiation" );
+    KEY_USAGE( KU_KEY_ENCIPHERMENT,     "Key Encipherment" );
+    KEY_USAGE( KU_DATA_ENCIPHERMENT,    "Data Encipherment" );
+    KEY_USAGE( KU_KEY_AGREEMENT,        "Key Agreement" );
+    KEY_USAGE( KU_KEY_CERT_SIGN,        "Key Cert Sign" );
+    KEY_USAGE( KU_CRL_SIGN,             "CRL Sign" );
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
+}
+
+static int x509_info_ext_key_usage( char **buf, size_t *size,
+                                    const x509_sequence *extended_key_usage )
+{
+    int ret;
+    const char *desc;
+    size_t n = *size;
+    char *p = *buf;
+    const x509_sequence *cur = extended_key_usage;
+    const char *sep = "";
+
+    while( cur != NULL )
+    {
+        if( oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
+            desc = "???";
+
+        ret = snprintf( p, n, "%s%s", sep, desc );
+        SAFE_SNPRINTF();
+
+        sep = ", ";
+
+        cur = cur->next;
+    }
+
+    *size = n;
+    *buf = p;
+
+    return( 0 );
 }
 
 /*
  * Return an informational string about the certificate.
  */
-#define BEFORE_COLON    14
-#define BC              "14"
+#define BEFORE_COLON    18
+#define BC              "18"
 int x509_crt_info( char *buf, size_t size, const char *prefix,
                    const x509_crt *crt )
 {
     int ret;
     size_t n;
     char *p;
-    const char *desc = NULL;
     char key_size_str[BEFORE_COLON];
 
     p = buf;
     n = size;
 
-    ret = snprintf( p, n, "%scert. version : %d\n",
+    ret = snprintf( p, n, "%scert. version     : %d\n",
                                prefix, crt->version );
     SAFE_SNPRINTF();
-    ret = snprintf( p, n, "%sserial number : ",
+    ret = snprintf( p, n, "%sserial number     : ",
                                prefix );
     SAFE_SNPRINTF();
 
-    ret = x509_serial_gets( p, n, &crt->serial);
+    ret = x509_serial_gets( p, n, &crt->serial );
     SAFE_SNPRINTF();
 
-    ret = snprintf( p, n, "\n%sissuer name   : ", prefix );
+    ret = snprintf( p, n, "\n%sissuer name       : ", prefix );
     SAFE_SNPRINTF();
     ret = x509_dn_gets( p, n, &crt->issuer  );
     SAFE_SNPRINTF();
 
-    ret = snprintf( p, n, "\n%ssubject name  : ", prefix );
+    ret = snprintf( p, n, "\n%ssubject name      : ", prefix );
     SAFE_SNPRINTF();
     ret = x509_dn_gets( p, n, &crt->subject );
     SAFE_SNPRINTF();
 
-    ret = snprintf( p, n, "\n%sissued  on    : " \
+    ret = snprintf( p, n, "\n%sissued  on        : " \
                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
                    crt->valid_from.year, crt->valid_from.mon,
                    crt->valid_from.day,  crt->valid_from.hour,
                    crt->valid_from.min,  crt->valid_from.sec );
     SAFE_SNPRINTF();
 
-    ret = snprintf( p, n, "\n%sexpires on    : " \
+    ret = snprintf( p, n, "\n%sexpires on        : " \
                    "%04d-%02d-%02d %02d:%02d:%02d", prefix,
                    crt->valid_to.year, crt->valid_to.mon,
                    crt->valid_to.day,  crt->valid_to.hour,
                    crt->valid_to.min,  crt->valid_to.sec );
     SAFE_SNPRINTF();
 
-    ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
+    ret = snprintf( p, n, "\n%ssigned using      : ", prefix );
     SAFE_SNPRINTF();
 
-    ret = oid_get_sig_alg_desc( &crt->sig_oid1, &desc );
-    if( ret != 0 )
-        ret = snprintf( p, n, "???"  );
-    else
-        ret = snprintf( p, n, "%s", desc );
+    ret = x509_sig_alg_gets( p, n, &crt->sig_oid1, crt->sig_pk,
+                             crt->sig_md, crt->sig_opts );
     SAFE_SNPRINTF();
 
+    /* Key size */
     if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
                                       pk_get_name( &crt->pk ) ) ) != 0 )
     {
         return( ret );
     }
 
-    ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
+    ret = snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
                           (int) pk_get_size( &crt->pk ) );
     SAFE_SNPRINTF();
 
+    /*
+     * Optional extensions
+     */
+
+    if( crt->ext_types & EXT_BASIC_CONSTRAINTS )
+    {
+        ret = snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
+                        crt->ca_istrue ? "true" : "false" );
+        SAFE_SNPRINTF();
+
+        if( crt->max_pathlen > 0 )
+        {
+            ret = snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
+            SAFE_SNPRINTF();
+        }
+    }
+
+    if( crt->ext_types & EXT_SUBJECT_ALT_NAME )
+    {
+        ret = snprintf( p, n, "\n%ssubject alt name  : ", prefix );
+        SAFE_SNPRINTF();
+
+        if( ( ret = x509_info_subject_alt_name( &p, &n,
+                                            &crt->subject_alt_names ) ) != 0 )
+            return( ret );
+    }
+
+    if( crt->ext_types & EXT_NS_CERT_TYPE )
+    {
+        ret = snprintf( p, n, "\n%scert. type        : ", prefix );
+        SAFE_SNPRINTF();
+
+        if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
+            return( ret );
+    }
+
+    if( crt->ext_types & EXT_KEY_USAGE )
+    {
+        ret = snprintf( p, n, "\n%skey usage         : ", prefix );
+        SAFE_SNPRINTF();
+
+        if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
+            return( ret );
+    }
+
+    if( crt->ext_types & EXT_EXTENDED_KEY_USAGE )
+    {
+        ret = snprintf( p, n, "\n%sext key usage     : ", prefix );
+        SAFE_SNPRINTF();
+
+        if( ( ret = x509_info_ext_key_usage( &p, &n,
+                                             &crt->ext_key_usage ) ) != 0 )
+            return( ret );
+    }
+
+    ret = snprintf( p, n, "\n" );
+    SAFE_SNPRINTF();
+
     return( (int) ( size - n ) );
 }
 
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+int x509_crt_check_key_usage( const x509_crt *crt, int usage )
+{
+    if( ( crt->ext_types & EXT_KEY_USAGE ) != 0 &&
+        ( crt->key_usage & usage ) != usage )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+    return( 0 );
+}
+#endif
+
+#if defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE)
+int x509_crt_check_extended_key_usage( const x509_crt *crt,
+                                       const char *usage_oid,
+                                       size_t usage_len )
+{
+    const x509_sequence *cur;
+
+    /* Extension is not mandatory, absent means no restriction */
+    if( ( crt->ext_types & EXT_EXTENDED_KEY_USAGE ) == 0 )
+        return( 0 );
+
+    /*
+     * Look for the requested usage (or wildcard ANY) in our list
+     */
+    for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
+    {
+        const x509_buf *cur_oid = &cur->buf;
+
+        if( cur_oid->len == usage_len &&
+            memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
+        {
+            return( 0 );
+        }
+
+        if( OID_CMP( OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) )
+            return( 0 );
+    }
+
+    return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+}
+#endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */
+
 #if defined(POLARSSL_X509_CRL_PARSE_C)
 /*
  * Return 1 if the certificate is revoked, or 0 otherwise.
@@ -1218,6 +1470,17 @@ static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca,
             continue;
         }
 
+        /*
+         * Check if the CA is configured to sign CRLs
+         */
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+        if( x509_crt_check_key_usage( ca, KU_CRL_SIGN ) != 0 )
+        {
+            flags |= BADCRL_NOT_TRUSTED;
+            break;
+        }
+#endif
+
         /*
          * Check if CRL is correctly signed by the trusted CA
          */
@@ -1233,9 +1496,9 @@ static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca,
 
         md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash );
 
-        if( pk_can_do( &ca->pk, crl_list->sig_pk ) == 0 ||
-            pk_verify( &ca->pk, crl_list->sig_md, hash, md_info->size,
-                       crl_list->sig.p, crl_list->sig.len ) != 0 )
+        if( pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
+                           crl_list->sig_md, hash, md_info->size,
+                           crl_list->sig.p, crl_list->sig.len ) != 0 )
         {
             flags |= BADCRL_NOT_TRUSTED;
             break;
@@ -1247,10 +1510,13 @@ static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca,
         if( x509_time_expired( &crl_list->next_update ) )
             flags |= BADCRL_EXPIRED;
 
+        if( x509_time_future( &crl_list->this_update ) )
+            flags |= BADCRL_FUTURE;
+
         /*
          * Check if certificate is revoked
          */
-        if( x509_crt_revoked(crt, crl_list) )
+        if( x509_crt_revoked( crt, crl_list ) )
         {
             flags |= BADCERT_REVOKED;
             break;
@@ -1258,7 +1524,7 @@ static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca,
 
         crl_list = crl_list->next;
     }
-    return flags;
+    return( flags );
 }
 #endif /* POLARSSL_X509_CRL_PARSE_C */
 
@@ -1273,11 +1539,15 @@ static int x509_name_cmp( const void *s1, const void *s2, size_t len )
     {
         diff = n1[i] ^ n2[i];
 
-        if( ( n1[i] >= 'a' || n1[i] <= 'z' ) && ( diff == 0 || diff == 32 ) )
+        if( diff == 0 )
             continue;
 
-        if( ( n1[i] >= 'A' || n1[i] <= 'Z' ) && ( diff == 0 || diff == 32 ) )
+        if( diff == 32 &&
+            ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
+              ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
+        {
             continue;
+        }
 
         return( 1 );
     }
@@ -1288,12 +1558,12 @@ static int x509_name_cmp( const void *s1, const void *s2, size_t len )
 static int x509_wildcard_verify( const char *cn, x509_buf *name )
 {
     size_t i;
-    size_t cn_idx = 0;
+    size_t cn_idx = 0, cn_len = strlen( cn );
 
     if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
         return( 0 );
 
-    for( i = 0; i < strlen( cn ); ++i )
+    for( i = 0; i < cn_len; ++i )
     {
         if( cn[i] == '.' )
         {
@@ -1305,7 +1575,7 @@ static int x509_wildcard_verify( const char *cn, x509_buf *name )
     if( cn_idx == 0 )
         return( 0 );
 
-    if( strlen( cn ) - cn_idx == name->len - 1 &&
+    if( cn_len - cn_idx == name->len - 1 &&
         x509_name_cmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
     {
         return( 1 );
@@ -1314,6 +1584,56 @@ static int x509_wildcard_verify( const char *cn, x509_buf *name )
     return( 0 );
 }
 
+/*
+ * Check if 'parent' is a suitable parent (signing CA) for 'child'.
+ * Return 0 if yes, -1 if not.
+ *
+ * top means parent is a locally-trusted certificate
+ * bottom means child is the end entity cert
+ */
+static int x509_crt_check_parent( const x509_crt *child,
+                                  const x509_crt *parent,
+                                  int top, int bottom )
+{
+    int need_ca_bit;
+
+    /* Parent must be the issuer */
+    if( child->issuer_raw.len != parent->subject_raw.len ||
+        memcmp( child->issuer_raw.p, parent->subject_raw.p,
+                child->issuer_raw.len ) != 0 )
+    {
+        return( -1 );
+    }
+
+    /* Parent must have the basicConstraints CA bit set as a general rule */
+    need_ca_bit = 1;
+
+    /* Exception: v1/v2 certificates that are locally trusted. */
+    if( top && parent->version < 3 )
+        need_ca_bit = 0;
+
+    /* Exception: self-signed end-entity certs that are locally trusted. */
+    if( top && bottom &&
+        child->raw.len == parent->raw.len &&
+        memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 )
+    {
+        need_ca_bit = 0;
+    }
+
+    if( need_ca_bit && ! parent->ca_istrue )
+        return( -1 );
+
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    if( need_ca_bit &&
+        x509_crt_check_key_usage( parent, KU_KEY_CERT_SIGN ) != 0 )
+    {
+        return( -1 );
+    }
+#endif
+
+    return( 0 );
+}
+
 static int x509_crt_verify_top(
                 x509_crt *child, x509_crt *trust_ca,
                 x509_crl *ca_crl, int path_cnt, int *flags,
@@ -1328,6 +1648,9 @@ static int x509_crt_verify_top(
     if( x509_time_expired( &child->valid_to ) )
         *flags |= BADCERT_EXPIRED;
 
+    if( x509_time_future( &child->valid_from ) )
+        *flags |= BADCERT_FUTURE;
+
     /*
      * Child is the top of the chain. Check against the trust_ca list.
      */
@@ -1344,16 +1667,10 @@ static int x509_crt_verify_top(
     else
         md( md_info, child->tbs.p, child->tbs.len, hash );
 
-    while( trust_ca != NULL )
+    for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next )
     {
-        if( trust_ca->version == 0 ||
-            child->issuer_raw.len != trust_ca->subject_raw.len ||
-            memcmp( child->issuer_raw.p, trust_ca->subject_raw.p,
-                    child->issuer_raw.len ) != 0 )
-        {
-            trust_ca = trust_ca->next;
+        if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 )
             continue;
-        }
 
         /*
          * Reduce path_len to check against if top of the chain is
@@ -1369,15 +1686,13 @@ static int x509_crt_verify_top(
         if( trust_ca->max_pathlen > 0 &&
             trust_ca->max_pathlen < check_path_cnt )
         {
-            trust_ca = trust_ca->next;
             continue;
         }
 
-        if( pk_can_do( &trust_ca->pk, child->sig_pk ) == 0 ||
-            pk_verify( &trust_ca->pk, child->sig_md, hash, md_info->size,
-                       child->sig.p, child->sig.len ) != 0 )
+        if( pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk,
+                           child->sig_md, hash, md_info->size,
+                           child->sig.p, child->sig.len ) != 0 )
         {
-            trust_ca = trust_ca->next;
             continue;
         }
 
@@ -1408,17 +1723,23 @@ static int x509_crt_verify_top(
         if( x509_time_expired( &trust_ca->valid_to ) )
             ca_flags |= BADCERT_EXPIRED;
 
+        if( x509_time_future( &trust_ca->valid_from ) )
+            ca_flags |= BADCERT_FUTURE;
+
         if( NULL != f_vrfy )
         {
-            if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, &ca_flags ) ) != 0 )
+            if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1,
+                                &ca_flags ) ) != 0 )
+            {
                 return( ret );
+            }
         }
     }
 
     /* Call callback on top cert */
     if( NULL != f_vrfy )
     {
-        if( ( ret = f_vrfy(p_vrfy, child, path_cnt, flags ) ) != 0 )
+        if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 )
             return( ret );
     }
 
@@ -1442,6 +1763,9 @@ static int x509_crt_verify_child(
     if( x509_time_expired( &child->valid_to ) )
         *flags |= BADCERT_EXPIRED;
 
+    if( x509_time_future( &child->valid_from ) )
+        *flags |= BADCERT_FUTURE;
+
     md_info = md_info_from_type( child->sig_md );
     if( md_info == NULL )
     {
@@ -1454,9 +1778,9 @@ static int x509_crt_verify_child(
     {
         md( md_info, child->tbs.p, child->tbs.len, hash );
 
-        if( pk_can_do( &parent->pk, child->sig_pk ) == 0 ||
-            pk_verify( &parent->pk, child->sig_md, hash, md_info->size,
-                       child->sig.p, child->sig.len ) != 0 )
+        if( pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
+                           child->sig_md, hash, md_info->size,
+                           child->sig.p, child->sig.len ) != 0 )
         {
             *flags |= BADCERT_NOT_TRUSTED;
         }
@@ -1467,34 +1791,28 @@ static int x509_crt_verify_child(
     *flags |= x509_crt_verifycrl(child, parent, ca_crl);
 #endif
 
-    grandparent = parent->next;
-
-    while( grandparent != NULL )
+    /* Look for a grandparent upwards the chain */
+    for( grandparent = parent->next;
+         grandparent != NULL;
+         grandparent = grandparent->next )
     {
-        if( grandparent->version == 0 ||
-            grandparent->ca_istrue == 0 ||
-            parent->issuer_raw.len != grandparent->subject_raw.len ||
-            memcmp( parent->issuer_raw.p, grandparent->subject_raw.p,
-                    parent->issuer_raw.len ) != 0 )
-        {
-            grandparent = grandparent->next;
-            continue;
-        }
-        break;
+        if( x509_crt_check_parent( parent, grandparent,
+                                   0, path_cnt == 0 ) == 0 )
+            break;
     }
 
+    /* Is our parent part of the chain or at the top? */
     if( grandparent != NULL )
     {
-        /*
-         * Part of the chain
-         */
-        ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
+        ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl,
+                                path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     }
     else
     {
-        ret = x509_crt_verify_top( parent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
+        ret = x509_crt_verify_top( parent, trust_ca, ca_crl,
+                                path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     }
@@ -1578,37 +1896,25 @@ int x509_crt_verify( x509_crt *crt,
         }
     }
 
-    /*
-     * Iterate upwards in the given cert chain, to find our crt parent.
-     * Ignore any upper cert with CA != TRUE.
-     */
-    parent = crt->next;
-
-    while( parent != NULL && parent->version != 0 )
+    /* Look for a parent upwards the chain */
+    for( parent = crt->next; parent != NULL; parent = parent->next )
     {
-        if( parent->ca_istrue == 0 ||
-            crt->issuer_raw.len != parent->subject_raw.len ||
-            memcmp( crt->issuer_raw.p, parent->subject_raw.p,
-                    crt->issuer_raw.len ) != 0 )
-        {
-            parent = parent->next;
-            continue;
-        }
-        break;
+        if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 )
+            break;
     }
 
+    /* Are we part of the chain or at the top? */
     if( parent != NULL )
     {
-        /*
-         * Part of the chain
-         */
-        ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy );
+        ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl,
+                                     pathlen, flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     }
     else
     {
-        ret = x509_crt_verify_top( crt, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy );
+        ret = x509_crt_verify_top( crt, trust_ca, ca_crl,
+                                   pathlen, flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     }
@@ -1646,12 +1952,16 @@ void x509_crt_free( x509_crt *crt )
     {
         pk_free( &cert_cur->pk );
 
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+        polarssl_free( cert_cur->sig_opts );
+#endif
+
         name_cur = cert_cur->issuer.next;
         while( name_cur != NULL )
         {
             name_prv = name_cur;
             name_cur = name_cur->next;
-            memset( name_prv, 0, sizeof( x509_name ) );
+            polarssl_zeroize( name_prv, sizeof( x509_name ) );
             polarssl_free( name_prv );
         }
 
@@ -1660,7 +1970,7 @@ void x509_crt_free( x509_crt *crt )
         {
             name_prv = name_cur;
             name_cur = name_cur->next;
-            memset( name_prv, 0, sizeof( x509_name ) );
+            polarssl_zeroize( name_prv, sizeof( x509_name ) );
             polarssl_free( name_prv );
         }
 
@@ -1669,7 +1979,7 @@ void x509_crt_free( x509_crt *crt )
         {
             seq_prv = seq_cur;
             seq_cur = seq_cur->next;
-            memset( seq_prv, 0, sizeof( x509_sequence ) );
+            polarssl_zeroize( seq_prv, sizeof( x509_sequence ) );
             polarssl_free( seq_prv );
         }
 
@@ -1678,13 +1988,13 @@ void x509_crt_free( x509_crt *crt )
         {
             seq_prv = seq_cur;
             seq_cur = seq_cur->next;
-            memset( seq_prv, 0, sizeof( x509_sequence ) );
+            polarssl_zeroize( seq_prv, sizeof( x509_sequence ) );
             polarssl_free( seq_prv );
         }
 
         if( cert_cur->raw.p != NULL )
         {
-            memset( cert_cur->raw.p, 0, cert_cur->raw.len );
+            polarssl_zeroize( cert_cur->raw.p, cert_cur->raw.len );
             polarssl_free( cert_cur->raw.p );
         }
 
@@ -1698,11 +2008,11 @@ void x509_crt_free( x509_crt *crt )
         cert_prv = cert_cur;
         cert_cur = cert_cur->next;
 
-        memset( cert_prv, 0, sizeof( x509_crt ) );
+        polarssl_zeroize( cert_prv, sizeof( x509_crt ) );
         if( cert_prv != crt )
             polarssl_free( cert_prv );
     }
     while( cert_cur != NULL );
 }
 
-#endif
+#endif /* POLARSSL_X509_CRT_PARSE_C */
index c0c7679c0339c6957c3d7315a2dbad840a024e61..0b4f771f922b30132441c5efefc32d74d208b991 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  X.509 Certificate Signing Request (CSR) parsing
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 /*
  *  The ITU-T X.509 standard defines a certificate format for PKI.
  *
- *  http://www.ietf.org/rfc/rfc3279.txt
- *  http://www.ietf.org/rfc/rfc3280.txt
- *
- *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
+ *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
+ *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
+ *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
  *
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_X509_CSR_PARSE_C)
 
@@ -44,8 +47,8 @@
 #include "polarssl/pem.h"
 #endif
 
-#if defined(POLARSSL_MEMORY_C)
-#include "polarssl/memory.h"
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
 #else
 #define polarssl_malloc     malloc
 #define polarssl_free       free
 #include <stdio.h>
 #endif
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  *  Version  ::=  INTEGER  {  v1(0)  }
  */
@@ -82,17 +90,17 @@ static int x509_csr_get_version( unsigned char **p,
 }
 
 /*
- * Parse a CSR
+ * Parse a CSR in DER format
  */
-int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
+int x509_csr_parse_der( x509_csr *csr,
+                        const unsigned char *buf, size_t buflen )
 {
     int ret;
     size_t len;
     unsigned char *p, *end;
-#if defined(POLARSSL_PEM_PARSE_C)
-    size_t use_len;
-    pem_context pem;
-#endif
+    x509_buf sig_params;
+
+    memset( &sig_params, 0, sizeof( x509_buf ) );
 
     /*
      * Check for valid input
@@ -102,49 +110,15 @@ int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
 
     x509_csr_init( csr );
 
-#if defined(POLARSSL_PEM_PARSE_C)
-    pem_init( &pem );
-    ret = pem_read_buffer( &pem,
-                           "-----BEGIN CERTIFICATE REQUEST-----",
-                           "-----END CERTIFICATE REQUEST-----",
-                           buf, NULL, 0, &use_len );
-
-    if( ret == 0 )
-    {
-        /*
-         * Was PEM encoded
-         */
-        buflen -= use_len;
-        buf += use_len;
-
-        /*
-         * Steal PEM buffer
-         */
-        p = pem.buf;
-        pem.buf = NULL;
-        len = pem.buflen;
-        pem_free( &pem );
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-    {
-        pem_free( &pem );
-        return( ret );
-    }
-    else
-#endif
-    {
-        /*
-         * nope, copy the raw DER data
-         */
-        p = (unsigned char *) polarssl_malloc( len = buflen );
+    /*
+     * first copy the raw DER data
+     */
+    p = (unsigned char *) polarssl_malloc( len = buflen );
 
-        if( p == NULL )
-            return( POLARSSL_ERR_X509_MALLOC_FAILED );
+    if( p == NULL )
+        return( POLARSSL_ERR_X509_MALLOC_FAILED );
 
-        memcpy( p, buf, buflen );
-
-        buflen = 0;
-    }
+    memcpy( p, buf, buflen );
 
     csr->raw.p = p;
     csr->raw.len = len;
@@ -251,14 +225,15 @@ int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
      *  signatureAlgorithm   AlgorithmIdentifier,
      *  signature            BIT STRING
      */
-    if( ( ret = x509_get_alg_null( &p, end, &csr->sig_oid ) ) != 0 )
+    if( ( ret = x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 )
     {
         x509_csr_free( csr );
         return( ret );
     }
 
-    if( ( ret = x509_get_sig_alg( &csr->sig_oid, &csr->sig_md,
-                                  &csr->sig_pk ) ) != 0 )
+    if( ( ret = x509_get_sig_alg( &csr->sig_oid, &sig_params,
+                                  &csr->sig_md, &csr->sig_pk,
+                                  &csr->sig_opts ) ) != 0 )
     {
         x509_csr_free( csr );
         return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG );
@@ -280,6 +255,51 @@ int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
     return( 0 );
 }
 
+/*
+ * Parse a CSR, allowing for PEM or raw DER encoding
+ */
+int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
+{
+    int ret;
+#if defined(POLARSSL_PEM_PARSE_C)
+    size_t use_len;
+    pem_context pem;
+#endif
+
+    /*
+     * Check for valid input
+     */
+    if( csr == NULL || buf == NULL )
+        return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
+
+#if defined(POLARSSL_PEM_PARSE_C)
+    pem_init( &pem );
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN CERTIFICATE REQUEST-----",
+                           "-----END CERTIFICATE REQUEST-----",
+                           buf, NULL, 0, &use_len );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded, parse the result
+         */
+        if( ( ret = x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 )
+            return( ret );
+
+        pem_free( &pem );
+        return( 0 );
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    {
+        pem_free( &pem );
+        return( ret );
+    }
+    else
+#endif /* POLARSSL_PEM_PARSE_C */
+    return( x509_csr_parse_der( csr, buf, buflen ) );
+}
+
 #if defined(POLARSSL_FS_IO)
 /*
  * Load a CSR into the structure
@@ -290,12 +310,12 @@ int x509_csr_parse_file( x509_csr *csr, const char *path )
     size_t n;
     unsigned char *buf;
 
-    if ( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
+    if( ( ret = x509_load_file( path, &buf, &n ) ) != 0 )
         return( ret );
 
     ret = x509_csr_parse( csr, buf, n );
 
-    memset( buf, 0, n + 1 );
+    polarssl_zeroize( buf, n + 1 );
     polarssl_free( buf );
 
     return( ret );
@@ -317,7 +337,7 @@ int x509_csr_parse_file( x509_csr *csr, const char *path )
  * This fuction tries to 'fix' this by at least suggesting enlarging the
  * size by 20.
  */
-static int compat_snprintf(char *str, size_t size, const char *format, ...)
+static int compat_snprintf( char *str, size_t size, const char *format, ... )
 {
     va_list ap;
     int res = -1;
@@ -329,29 +349,29 @@ static int compat_snprintf(char *str, size_t size, const char *format, ...)
     va_end( ap );
 
     // No quick fix possible
-    if ( res < 0 )
+    if( res < 0 )
         return( (int) size + 20 );
 
-    return res;
+    return( res );
 }
 
 #define snprintf compat_snprintf
-#endif
+#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
 
 #define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
 
-#define SAFE_SNPRINTF()                         \
-{                                               \
-    if( ret == -1 )                             \
-        return( -1 );                           \
-                                                \
-    if ( (unsigned int) ret > n ) {             \
-        p[n - 1] = '\0';                        \
-        return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
-    }                                           \
-                                                \
-    n -= (unsigned int) ret;                    \
-    p += (unsigned int) ret;                    \
+#define SAFE_SNPRINTF()                             \
+{                                                   \
+    if( ret == -1 )                                 \
+        return( -1 );                               \
+                                                    \
+    if( (unsigned int) ret > n ) {                  \
+        p[n - 1] = '\0';                            \
+        return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \
+    }                                               \
+                                                    \
+    n -= (unsigned int) ret;                        \
+    p += (unsigned int) ret;                        \
 }
 
 #define BEFORE_COLON    14
@@ -365,7 +385,6 @@ int x509_csr_info( char *buf, size_t size, const char *prefix,
     int ret;
     size_t n;
     char *p;
-    const char *desc;
     char key_size_str[BEFORE_COLON];
 
     p = buf;
@@ -383,11 +402,8 @@ int x509_csr_info( char *buf, size_t size, const char *prefix,
     ret = snprintf( p, n, "\n%ssigned using  : ", prefix );
     SAFE_SNPRINTF();
 
-    ret = oid_get_sig_alg_desc( &csr->sig_oid, &desc );
-    if( ret != 0 )
-        ret = snprintf( p, n, "???"  );
-    else
-        ret = snprintf( p, n, "%s", desc );
+    ret = x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
+                             csr->sig_opts );
     SAFE_SNPRINTF();
 
     if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
@@ -424,22 +440,26 @@ void x509_csr_free( x509_csr *csr )
 
     pk_free( &csr->pk );
 
+#if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
+    polarssl_free( csr->sig_opts );
+#endif
+
     name_cur = csr->subject.next;
     while( name_cur != NULL )
     {
         name_prv = name_cur;
         name_cur = name_cur->next;
-        memset( name_prv, 0, sizeof( x509_name ) );
+        polarssl_zeroize( name_prv, sizeof( x509_name ) );
         polarssl_free( name_prv );
     }
 
     if( csr->raw.p != NULL )
     {
-        memset( csr->raw.p, 0, csr->raw.len );
+        polarssl_zeroize( csr->raw.p, csr->raw.len );
         polarssl_free( csr->raw.p );
     }
 
-    memset( csr, 0, sizeof( x509_csr ) );
+    polarssl_zeroize( csr, sizeof( x509_csr ) );
 }
 
 #endif /* POLARSSL_X509_CSR_PARSE_C */
index 15a1194ed7a951e7f2179efef8a0ce951a93cc3a..e298c24ecf02f7c4712f707e023fa2c73a525532 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  X.509 certificate writing
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  * - attributes: PKCS#9 v2.0 aka RFC 2985
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_X509_CRT_WRITE_C)
 
 #include "polarssl/pem.h"
 #endif /* POLARSSL_PEM_WRITE_C */
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 void x509write_crt_init( x509write_cert *ctx )
 {
     memset( ctx, 0, sizeof(x509write_cert) );
@@ -58,7 +67,7 @@ void x509write_crt_free( x509write_cert *ctx )
     asn1_free_named_data_list( &ctx->issuer );
     asn1_free_named_data_list( &ctx->extensions );
 
-    memset( ctx, 0, sizeof(x509write_cert) );
+    polarssl_zeroize( ctx, sizeof(x509write_cert) );
 }
 
 void x509write_crt_set_version( x509write_cert *ctx, int version )
@@ -106,8 +115,8 @@ int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
 int x509write_crt_set_validity( x509write_cert *ctx, const char *not_before,
                                 const char *not_after )
 {
-    if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
-        strlen(not_after)  != X509_RFC5280_UTC_TIME_LEN - 1 )
+    if( strlen( not_before ) != X509_RFC5280_UTC_TIME_LEN - 1 ||
+        strlen( not_after )  != X509_RFC5280_UTC_TIME_LEN - 1 )
     {
         return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
     }
@@ -151,7 +160,8 @@ int x509write_crt_set_basic_constraints( x509write_cert *ctx,
     }
 
     ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                ASN1_SEQUENCE ) );
 
     return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
                                         OID_SIZE( OID_BASIC_CONSTRAINTS ),
@@ -166,7 +176,7 @@ int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
     unsigned char *c = buf + sizeof(buf);
     size_t len = 0;
 
-    memset( buf, 0, sizeof(buf));
+    memset( buf, 0, sizeof(buf) );
     ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) );
 
     sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
@@ -188,7 +198,7 @@ int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
     unsigned char *c = buf + sizeof(buf);
     size_t len = 0;
 
-    memset( buf, 0, sizeof(buf));
+    memset( buf, 0, sizeof(buf) );
     ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) );
 
     sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
@@ -199,7 +209,8 @@ int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
     ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
 
     ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
+                                                ASN1_SEQUENCE ) );
 
     return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
                                    OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
@@ -313,9 +324,11 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
      */
     ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC |
+                                                    ASN1_CONSTRUCTED | 3 ) );
 
     /*
      *  SubjectPublicKeyInfo
@@ -345,7 +358,8 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
 
     len += sub_len;
     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
 
     /*
      *  Issuer  ::=  Name
@@ -370,10 +384,12 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
     ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
     len += sub_len;
     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC |
+                                                    ASN1_CONSTRUCTED | 0 ) );
 
     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
 
     /*
      * Make signature
@@ -398,7 +414,8 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
 
     len += sig_and_oid_len;
     ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
 
     return( (int) len );
 }
index 3a49aee94eb4e1b14c0b8a96c80da6c90a09d507..53ae9c63b744d98e1bed367a99e7467fb4f87ea9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  X.509 Certificate Signing Request writing
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  * - attributes: PKCS#9 v2.0 aka RFC 2985
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_X509_CSR_WRITE_C)
 
 #include <string.h>
 #include <stdlib.h>
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 void x509write_csr_init( x509write_csr *ctx )
 {
     memset( ctx, 0, sizeof(x509write_csr) );
@@ -53,7 +62,7 @@ void x509write_csr_free( x509write_csr *ctx )
     asn1_free_named_data_list( &ctx->subject );
     asn1_free_named_data_list( &ctx->extensions );
 
-    memset( ctx, 0, sizeof(x509write_csr) );
+    polarssl_zeroize( ctx, sizeof(x509write_csr) );
 }
 
 void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
@@ -146,20 +155,24 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
     if( len )
     {
         ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                        ASN1_SEQUENCE ) );
 
         ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                        ASN1_SET ) );
 
         ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
                                           OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
 
         ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+        ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                        ASN1_SEQUENCE ) );
     }
 
     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_CONTEXT_SPECIFIC ) );
 
     ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
                                                 tmp_buf, c - tmp_buf ) );
@@ -177,7 +190,8 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
     ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
 
     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
+                                                    ASN1_SEQUENCE ) );
 
     /*
      * Prepare signature
@@ -208,7 +222,8 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
 
     len += sig_and_oid_len;
     ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
-    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) );
+    ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
+                                                 ASN1_SEQUENCE ) );
 
     return( (int) len );
 }
index 2cb2f30d1b89d41653d164f2426bb2840a775405..75215c50af8add7da27582b56d8bab77116a0cca 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  An 32-bit implementation of the XTEA algorithm
  *
- *  Copyright (C) 2006-2013, Brainspark B.V.
+ *  Copyright (C) 2006-2014, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#if !defined(POLARSSL_CONFIG_FILE)
 #include "polarssl/config.h"
+#else
+#include POLARSSL_CONFIG_FILE
+#endif
 
 #if defined(POLARSSL_XTEA_C)
 
 #include "polarssl/xtea.h"
 
+#if defined(POLARSSL_PLATFORM_C)
+#include "polarssl/platform.h"
+#else
+#define polarssl_printf printf
+#endif
+
 #if !defined(POLARSSL_XTEA_ALT)
 
+/* Implementation that should never be optimized out by the compiler */
+static void polarssl_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
 /*
  * 32-bit integer manipulation macros (big endian)
  */
 }
 #endif
 
+void xtea_init( xtea_context *ctx )
+{
+    memset( ctx, 0, sizeof( xtea_context ) );
+}
+
+void xtea_free( xtea_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    polarssl_zeroize( ctx, sizeof( xtea_context ) );
+}
+
 /*
  * XTEA key schedule
  */
@@ -61,7 +89,7 @@ void xtea_setup( xtea_context *ctx, const unsigned char key[16] )
 {
     int i;
 
-    memset(ctx, 0, sizeof(xtea_context));
+    memset( ctx, 0, sizeof(xtea_context) );
 
     for( i = 0; i < 4; i++ )
     {
@@ -132,7 +160,7 @@ int xtea_crypt_cbc( xtea_context *ctx, int mode, size_t length,
             memcpy( temp, input, 8 );
             xtea_crypt_ecb( ctx, mode, input, output );
 
-            for(i = 0; i < 8; i++)
+            for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
 
             memcpy( iv, temp, 8 );
@@ -213,14 +241,15 @@ static const unsigned char xtea_test_ct[6][8] =
  */
 int xtea_self_test( int verbose )
 {
-    int i;
+    int i, ret = 0;
     unsigned char buf[8];
     xtea_context ctx;
 
+    xtea_init( &ctx );
     for( i = 0; i < 6; i++ )
     {
         if( verbose != 0 )
-            printf( "  XTEA test #%d: ", i + 1 );
+            polarssl_printf( "  XTEA test #%d: ", i + 1 );
 
         memcpy( buf, xtea_test_pt[i], 8 );
 
@@ -230,21 +259,25 @@ int xtea_self_test( int verbose )
         if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 )
         {
             if( verbose != 0 )
-                printf( "failed\n" );
+                polarssl_printf( "failed\n" );
 
-            return( 1 );
+            ret = 1;
+            goto exit;
         }
 
         if( verbose != 0 )
-            printf( "passed\n" );
+            polarssl_printf( "passed\n" );
     }
 
     if( verbose != 0 )
-        printf( "\n" );
+        polarssl_printf( "\n" );
 
-    return( 0 );
+exit:
+    xtea_free( &ctx );
+
+    return( ret );
 }
 
-#endif
+#endif /* POLARSSL_SELF_TEST */
 
-#endif
+#endif /* POLARSSL_XTEA_C */