From 86cc97e55fe346502462284d2e636a2b3708163e Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 24 Feb 2020 14:43:11 +0300 Subject: [PATCH] Squashed 'Sources/OpenVPN3/' content from commit 0a6e0b6e54 git-subtree-dir: Sources/OpenVPN3 git-subtree-split: 0a6e0b6e542c2d19de1f416c4caccd899d72831a --- .gitignore | 4 + .travis.yml | 58 + .travis/build-check.sh | 75 + .travis/build-deps.sh | 133 + CLA.rst | 63 + CMakeLists.txt | 7 + CONTRIBUTING.rst | 7 + COPYRIGHT.AGPLV3 | 661 + LICENSE.rst | 15 + README.rst | 617 + VersionNumbering.rst | 63 + appveyor.yml | 32 + client/ovpncli.cpp | 1420 ++ client/ovpncli.hpp | 633 + cmake/CMakeLists.txt.in | 15 + cmake/FindLZ4.cmake | 9 + cmake/FindmbedTLS.cmake | 63 + cmake/dlgoogletest.cmake | 35 + cmake/findcoredeps.cmake | 107 + cmake/mypragmaonce.cmake | 8 + deps/asio/build-asio | 44 + ...4-support-when-both-ASIO_HAS_GETADDR.patch | 48 + ...method-to-asio-ip-tcp-resolver-resul.patch | 38 + ...hook-async_connect_post_open-to-be-c.patch | 38 + ...se-English-for-Windows-error-message.patch | 29 + deps/asio/snapshot-asio | 4 + deps/boost/atomic-1.55.0.patch | 87 + deps/boost/build-boost | 75 + deps/boost/intrusive_ptr.patch | 29 + deps/boost/page_size.patch | 16 + deps/cityhash/build-cityhash | 64 + deps/functions.sh | 47 + deps/lib-versions | 24 + deps/lz4/build-lz4 | 66 + deps/lz4/snapshot-lz4 | 4 + deps/lzo/build-lzo | 80 + deps/mbedtls/build-mbedtls | 102 + .../0001-relax-x509-date-format-check.patch | 55 + ...unsupported-critical-extensions-in-r.patch | 361 + .../patches/0003-fix-gcc-android-build.patch | 13 + deps/minicrypto/aes-armv4.pl.patch | 32 + deps/minicrypto/arm-as-to-ios | 759 ++ deps/minicrypto/arm-as-to-ios.orig | 730 ++ deps/minicrypto/build-minicrypto | 137 + deps/minicrypto/build-minicrypto-osx | 139 + deps/minicrypto/sha512-armv4.pl.patch | 32 + deps/openssl/build-openssl | 77 + deps/polarssl/.gitignore | 1 + deps/polarssl/CMakeLists.txt | 86 + deps/polarssl/README.txt | 12 + deps/polarssl/android.cmake | 17 + deps/polarssl/apple.cmake | 4 + deps/polarssl/bignum-arm.patch | 32 + deps/polarssl/build-detail-patch | 24 + deps/polarssl/build-mini-openssl | 52 + deps/polarssl/build-polarssl | 167 + deps/polarssl/build-polarssl-patch | 30 + deps/polarssl/config.h | 2227 ++++ deps/polarssl/config.h.orig | 2180 ++++ deps/polarssl/config12.h | 959 ++ deps/polarssl/crypto-alt.txt | 16 + deps/polarssl/dhm.patch | 12 + deps/polarssl/entropy-printf.patch | 12 + deps/polarssl/gitar | 9 + deps/polarssl/intel_cpu.c | 22 + deps/polarssl/linux-arm.cmake | 17 + deps/polarssl/polar-openssl.patch | 782 ++ deps/polarssl/polarssl-minicrypto.patch | 446 + deps/polarssl/ref | 24 + deps/polarssl/ref-aesni | 24 + deps/polarssl/relaxed-x509-date.patch | 118 + deps/polarssl/testpatch | 13 + .../unused/polarssl-const-ciphersuite.patch | 37 + deps/polarssl/unused/polarssl-enum.patch | 15 + deps/polarssl/unused/polarssl-epki.patch | 181 + .../unused/polarssl-invalid-mac.patch | 12 + deps/polarssl/unused/trustex.patch | 44 + deps/snappy/build-snappy | 66 + doc/openvpn-protocol-extensions.txt | 198 + docker-build.sh | 12 + dockerfiles/Dockerfile.centos | 19 + dockerfiles/Dockerfile.debian | 17 + dockerfiles/Dockerfile.ubu | 17 + javacli/.gitignore | 7 + javacli/Client.java | 144 + javacli/Main.java | 97 + javacli/OpenVPNClientThread.java | 359 + javacli/android/cpu.cpp | 62 + javacli/android/jellybean_hack.cpp | 178 + javacli/build-android | 126 + javacli/build-linux | 95 + javacli/ovpncli.i | 55 + mac/.gitignore | 1 + .../ovpn3-core.xcodeproj/project.pbxproj | 342 + .../contents.xcworkspacedata | 7 + openvpn/addr/addrlist.hpp | 65 + openvpn/addr/addrpair.hpp | 218 + openvpn/addr/addrspacesplit.hpp | 109 + openvpn/addr/ip.hpp | 992 ++ openvpn/addr/iperr.hpp | 75 + openvpn/addr/ipv4.hpp | 588 + openvpn/addr/ipv6.hpp | 847 ++ openvpn/addr/macaddr.hpp | 67 + openvpn/addr/pool.hpp | 164 + openvpn/addr/quoteip.hpp | 36 + openvpn/addr/randaddr.hpp | 68 + openvpn/addr/range.hpp | 137 + openvpn/addr/regex.hpp | 59 + openvpn/addr/route.hpp | 344 + openvpn/apple/cf/cf.hpp | 459 + openvpn/apple/cf/cfhelper.hpp | 261 + openvpn/apple/cf/cfhost.hpp | 33 + openvpn/apple/cf/cfrunloop.hpp | 34 + openvpn/apple/cf/cfsec.hpp | 58 + openvpn/apple/cf/cfsocket.hpp | 33 + openvpn/apple/cf/cfstream.hpp | 34 + openvpn/apple/cf/cftimer.hpp | 33 + openvpn/apple/cf/error.hpp | 67 + openvpn/apple/iosactiveiface.hpp | 74 + openvpn/apple/maclife.hpp | 325 + openvpn/apple/macsleep.hpp | 129 + openvpn/apple/macver.hpp | 75 + openvpn/apple/reach.hpp | 43 + openvpn/apple/reachable.hpp | 468 + openvpn/apple/scdynstore.hpp | 52 + openvpn/apple/ver.hpp | 81 + openvpn/applecrypto/crypto/api.hpp | 46 + openvpn/applecrypto/crypto/cipher.hpp | 201 + openvpn/applecrypto/crypto/digest.hpp | 255 + openvpn/applecrypto/crypto/hmac.hpp | 145 + openvpn/applecrypto/ssl/sslctx.hpp | 493 + openvpn/applecrypto/util/rand.hpp | 78 + openvpn/asio/asioboundsock.hpp | 99 + openvpn/asio/asiocontext.hpp | 51 + openvpn/asio/asioerr.hpp | 41 + openvpn/asio/asiopolysock.hpp | 377 + openvpn/asio/asioresolverres.hpp | 49 + openvpn/asio/asiosignal.hpp | 104 + openvpn/asio/asiostop.hpp | 52 + openvpn/asio/asiowork.hpp | 44 + openvpn/asio/scoped_asio_stream.hpp | 108 + openvpn/auth/authcert.hpp | 284 + openvpn/auth/authcreds.hpp | 92 + openvpn/auth/cr.hpp | 228 + openvpn/auth/validatecreds.hpp | 71 + openvpn/buffer/asiobuf.hpp | 56 + openvpn/buffer/bufclamp.hpp | 52 + openvpn/buffer/bufcomplete.hpp | 112 + openvpn/buffer/bufcomposed.hpp | 94 + openvpn/buffer/buffer.hpp | 911 ++ openvpn/buffer/bufhex.hpp | 61 + openvpn/buffer/buflimit.hpp | 92 + openvpn/buffer/buflineiter.hpp | 58 + openvpn/buffer/buflist.hpp | 122 + openvpn/buffer/bufread.hpp | 67 + openvpn/buffer/bufstatic.hpp | 45 + openvpn/buffer/bufstr.hpp | 110 + openvpn/buffer/bufstream.hpp | 83 + openvpn/buffer/lz4.hpp | 96 + openvpn/buffer/memq.hpp | 96 + openvpn/buffer/safestr.hpp | 186 + openvpn/buffer/zlib.hpp | 145 + openvpn/client/async_resolve.hpp | 37 + openvpn/client/async_resolve/asio.hpp | 163 + openvpn/client/async_resolve/generic.hpp | 79 + openvpn/client/cliconnect.hpp | 684 + openvpn/client/cliconstants.hpp | 41 + openvpn/client/clicreds.hpp | 227 + openvpn/client/cliemuexr.hpp | 177 + openvpn/client/clievent.hpp | 486 + openvpn/client/clihalt.hpp | 119 + openvpn/client/clilife.hpp | 50 + openvpn/client/cliopt.hpp | 918 ++ openvpn/client/cliopthelper.hpp | 722 ++ openvpn/client/cliproto.hpp | 1139 ++ openvpn/client/ipverflags.hpp | 99 + openvpn/client/optfilt.hpp | 104 + openvpn/client/remotelist.hpp | 926 ++ openvpn/client/rgopt.hpp | 158 + openvpn/common/abort.hpp | 30 + openvpn/common/action.hpp | 212 + openvpn/common/actionthread.hpp | 113 + openvpn/common/appversion.hpp | 35 + openvpn/common/arch.hpp | 37 + openvpn/common/argv.hpp | 133 + openvpn/common/arraysize.hpp | 34 + openvpn/common/asyncsleep.hpp | 57 + openvpn/common/autoreset.hpp | 55 + openvpn/common/base64.hpp | 318 + openvpn/common/bigmutex.hpp | 52 + openvpn/common/binprefix.hpp | 67 + openvpn/common/circ_list.hpp | 124 + openvpn/common/clamp.hpp | 39 + openvpn/common/cleanup.hpp | 60 + openvpn/common/core.hpp | 70 + openvpn/common/count.hpp | 29 + openvpn/common/daemon.hpp | 153 + openvpn/common/demangle.hpp | 48 + openvpn/common/destruct.hpp | 40 + openvpn/common/endian.hpp | 82 + openvpn/common/endian_platform.hpp | 35 + openvpn/common/enumdir.hpp | 80 + openvpn/common/environ.hpp | 126 + openvpn/common/exception.hpp | 146 + openvpn/common/extern.hpp | 33 + openvpn/common/ffs.hpp | 159 + openvpn/common/file.hpp | 213 + openvpn/common/fileatomic.hpp | 83 + openvpn/common/fileunix.hpp | 186 + openvpn/common/format.hpp | 337 + openvpn/common/function.hpp | 257 + openvpn/common/getopt.hpp | 226 + openvpn/common/getpw.hpp | 48 + openvpn/common/glob.hpp | 75 + openvpn/common/hash.hpp | 192 + openvpn/common/hexstr.hpp | 487 + openvpn/common/hostlist.hpp | 159 + openvpn/common/hostname.hpp | 44 + openvpn/common/hostport.hpp | 150 + openvpn/common/jsonlib.hpp | 31 + openvpn/common/lex.hpp | 102 + openvpn/common/likely.hpp | 36 + openvpn/common/link.hpp | 53 + openvpn/common/logrotate.hpp | 45 + openvpn/common/logsetup.hpp | 36 + openvpn/common/memneq.hpp | 159 + openvpn/common/mode.hpp | 70 + openvpn/common/modstat.hpp | 77 + openvpn/common/msfind.hpp | 90 + openvpn/common/msgwin.hpp | 165 + openvpn/common/number.hpp | 152 + openvpn/common/olong.hpp | 38 + openvpn/common/option_error.hpp | 30 + openvpn/common/options.hpp | 1477 +++ openvpn/common/ostream.hpp | 40 + openvpn/common/path.hpp | 207 + openvpn/common/peercred.hpp | 93 + openvpn/common/persistfile.hpp | 106 + openvpn/common/pipe.hpp | 147 + openvpn/common/platform.hpp | 57 + openvpn/common/platform_name.hpp | 56 + openvpn/common/platform_string.hpp | 74 + openvpn/common/process.hpp | 184 + openvpn/common/pthreadcond.hpp | 143 + openvpn/common/rc.hpp | 733 ++ openvpn/common/redir.hpp | 310 + openvpn/common/runcontext.hpp | 441 + openvpn/common/scoped_fd.hpp | 140 + openvpn/common/sess_id.hpp | 200 + openvpn/common/signal.hpp | 162 + openvpn/common/signal_name.hpp | 50 + openvpn/common/size.hpp | 42 + openvpn/common/sleep.hpp | 50 + openvpn/common/sockopt.hpp | 87 + openvpn/common/socktypes.hpp | 35 + openvpn/common/split.hpp | 157 + openvpn/common/splitlines.hpp | 119 + openvpn/common/stat.hpp | 70 + openvpn/common/stop.hpp | 119 + openvpn/common/strerror.hpp | 50 + openvpn/common/string.hpp | 652 + openvpn/common/stringize.hpp | 30 + openvpn/common/stringtempl.hpp | 82 + openvpn/common/strneq.hpp | 65 + openvpn/common/tempfile.hpp | 157 + openvpn/common/to_string.hpp | 63 + openvpn/common/umask.hpp | 68 + openvpn/common/unicode-impl.hpp | 653 + openvpn/common/unicode.hpp | 301 + openvpn/common/uniqueptr.hpp | 33 + openvpn/common/usecount.hpp | 49 + openvpn/common/usergroup.hpp | 195 + openvpn/common/userpass.hpp | 123 + openvpn/common/valgrind.hpp | 29 + openvpn/common/version.hpp | 28 + openvpn/common/waitbarrier.hpp | 58 + openvpn/common/write.hpp | 50 + openvpn/common/wstring.hpp | 73 + openvpn/compress/compnull.hpp | 44 + openvpn/compress/compress.hpp | 548 + openvpn/compress/compstub.hpp | 140 + openvpn/compress/lz4.hpp | 227 + openvpn/compress/lzo.hpp | 169 + openvpn/compress/lzoasym.hpp | 119 + openvpn/compress/lzoasym_impl.hpp | 345 + openvpn/compress/lzoselect.hpp | 40 + openvpn/compress/snappy.hpp | 136 + openvpn/crypto/bs64_data_limit.hpp | 45 + openvpn/crypto/cipher.hpp | 133 + openvpn/crypto/crypto_aead.hpp | 350 + openvpn/crypto/crypto_chm.hpp | 182 + openvpn/crypto/cryptoalgs.hpp | 261 + openvpn/crypto/cryptodc.hpp | 212 + openvpn/crypto/cryptodcsel.hpp | 72 + openvpn/crypto/decrypt_chm.hpp | 140 + openvpn/crypto/digestapi.hpp | 210 + openvpn/crypto/encrypt_chm.hpp | 136 + openvpn/crypto/hashstr.hpp | 95 + openvpn/crypto/ovpnhmac.hpp | 240 + openvpn/crypto/packet_id.hpp | 447 + openvpn/crypto/selftest.hpp | 65 + openvpn/crypto/static_key.hpp | 183 + openvpn/crypto/tls_crypt.hpp | 323 + openvpn/crypto/tls_crypt_v2.hpp | 196 + openvpn/dco/dcocli.hpp | 727 ++ openvpn/dco/ipcollbase.hpp | 44 + openvpn/error/error.hpp | 186 + openvpn/error/excode.hpp | 91 + openvpn/frame/frame.hpp | 309 + openvpn/frame/frame_init.hpp | 80 + openvpn/frame/memq_dgram.hpp | 77 + openvpn/frame/memq_stream.hpp | 110 + openvpn/http/header.hpp | 112 + openvpn/http/htmlskip.hpp | 283 + openvpn/http/method.hpp | 47 + openvpn/http/parseutil.hpp | 86 + openvpn/http/reply.hpp | 398 + openvpn/http/request.hpp | 398 + openvpn/http/status.hpp | 79 + openvpn/http/urlencode.hpp | 120 + openvpn/http/urlparm.hpp | 211 + openvpn/http/urlparse.hpp | 262 + openvpn/http/validate_uri.hpp | 52 + openvpn/http/webexcept.hpp | 70 + openvpn/init/cryptoinit.hpp | 46 + openvpn/init/engineinit.hpp | 55 + openvpn/init/initprocess.hpp | 92 + openvpn/io/io.hpp | 32 + openvpn/ip/csum.hpp | 171 + openvpn/ip/dhcp.hpp | 90 + openvpn/ip/eth.hpp | 42 + openvpn/ip/icmp4.hpp | 67 + openvpn/ip/icmp6.hpp | 64 + openvpn/ip/ip4.hpp | 68 + openvpn/ip/ip6.hpp | 50 + openvpn/ip/ipcommon.hpp | 50 + openvpn/ip/ping4.hpp | 113 + openvpn/ip/ping6.hpp | 171 + openvpn/ip/ptb.hpp | 136 + openvpn/ip/tcp.hpp | 90 + openvpn/ip/udp.hpp | 83 + openvpn/kovpn/kocrypto.hpp | 389 + openvpn/kovpn/kodev.hpp | 391 + openvpn/kovpn/korekey.hpp | 195 + openvpn/kovpn/koroute.hpp | 69 + openvpn/kovpn/kostats.hpp | 166 + openvpn/kovpn/kovpn.hpp | 38 + openvpn/legal/copyright.hpp | 32 + openvpn/linux/core.hpp | 64 + openvpn/linux/cputime.hpp | 72 + openvpn/linux/daemon_alive.hpp | 59 + openvpn/linux/procfs.hpp | 108 + openvpn/log/logbase.hpp | 54 + openvpn/log/logbasesimple.hpp | 57 + openvpn/log/logbasesimplemac.hpp | 59 + openvpn/log/logdatetime.hpp | 49 + openvpn/log/lognull.hpp | 34 + openvpn/log/logperiod.hpp | 174 + openvpn/log/logsimple.hpp | 51 + openvpn/log/logthread.hpp | 168 + openvpn/log/sessionstats.hpp | 176 + openvpn/mbedtls/crypto/api.hpp | 46 + openvpn/mbedtls/crypto/cipher.hpp | 196 + openvpn/mbedtls/crypto/ciphergcm.hpp | 170 + openvpn/mbedtls/crypto/digest.hpp | 157 + openvpn/mbedtls/crypto/hmac.hpp | 134 + openvpn/mbedtls/pki/dh.hpp | 124 + openvpn/mbedtls/pki/pkctx.hpp | 163 + openvpn/mbedtls/pki/x509cert.hpp | 167 + openvpn/mbedtls/pki/x509crl.hpp | 119 + openvpn/mbedtls/ssl/sslctx.hpp | 1476 +++ openvpn/mbedtls/util/error.hpp | 141 + openvpn/mbedtls/util/pem.hpp | 77 + openvpn/mbedtls/util/pkcs1.hpp | 71 + openvpn/mbedtls/util/rand.hpp | 135 + openvpn/mbedtls/util/selftest.hpp | 56 + openvpn/netconf/enumiface.hpp | 218 + openvpn/netconf/hwaddr.hpp | 74 + openvpn/netconf/ios/net-route.h | 248 + openvpn/netconf/linux/gw.hpp | 211 + openvpn/netconf/linux/gwnetlink.hpp | 159 + openvpn/netconf/linux/route.hpp | 160 + openvpn/openssl/bio/bio_memq_dgram.hpp | 262 + openvpn/openssl/bio/bio_memq_stream.hpp | 233 + openvpn/openssl/compat.hpp | 349 + openvpn/openssl/crypto/api.hpp | 46 + openvpn/openssl/crypto/cipher.hpp | 200 + openvpn/openssl/crypto/ciphergcm.hpp | 245 + openvpn/openssl/crypto/digest.hpp | 168 + openvpn/openssl/crypto/hmac.hpp | 148 + openvpn/openssl/pki/crl.hpp | 169 + openvpn/openssl/pki/dh.hpp | 163 + openvpn/openssl/pki/pkey.hpp | 214 + openvpn/openssl/pki/x509.hpp | 178 + openvpn/openssl/pki/x509store.hpp | 104 + openvpn/openssl/sign/pkcs7verify.hpp | 87 + openvpn/openssl/sign/verify.hpp | 99 + openvpn/openssl/ssl/sess_cache.hpp | 186 + openvpn/openssl/ssl/sslctx.hpp | 2145 ++++ openvpn/openssl/util/engine.hpp | 61 + openvpn/openssl/util/error.hpp | 200 + openvpn/openssl/util/init.hpp | 39 + openvpn/openssl/util/pem.hpp | 103 + openvpn/openssl/util/rand.hpp | 78 + openvpn/openssl/util/reseed.hpp | 40 + openvpn/openssl/util/tokenencrypt.hpp | 121 + openvpn/options/continuation.hpp | 106 + openvpn/options/merge.hpp | 496 + openvpn/options/sanitize.hpp | 109 + openvpn/options/servpush.hpp | 85 + openvpn/pki/cclist.hpp | 160 + openvpn/pki/epkibase.hpp | 42 + openvpn/pki/pkcs1.hpp | 117 + openvpn/pki/pktype.hpp | 39 + openvpn/pki/x509track.hpp | 230 + openvpn/proxy/httpdigest.hpp | 113 + openvpn/proxy/ntlm.hpp | 229 + openvpn/proxy/proxyauth.hpp | 86 + openvpn/random/devurand.hpp | 88 + openvpn/random/mtrandapi.hpp | 121 + openvpn/random/rand2.hpp | 55 + openvpn/random/randapi.hpp | 152 + openvpn/random/randbytestore.hpp | 67 + openvpn/random/randistrib.hpp | 37 + openvpn/reliable/relack.hpp | 119 + openvpn/reliable/relcommon.hpp | 63 + openvpn/reliable/relrecv.hpp | 97 + openvpn/reliable/relsend.hpp | 148 + openvpn/server/listenlist.hpp | 345 + openvpn/server/manage.hpp | 150 + openvpn/server/peeraddr.hpp | 70 + openvpn/server/peerstats.hpp | 45 + openvpn/server/servhalt.hpp | 38 + openvpn/server/servproto.hpp | 752 ++ openvpn/server/vpnservnetblock.hpp | 223 + openvpn/server/vpnservpool.hpp | 159 + openvpn/ssl/datalimit.hpp | 206 + openvpn/ssl/is_openvpn_protocol.hpp | 58 + openvpn/ssl/kuparse.hpp | 140 + openvpn/ssl/mssparms.hpp | 68 + openvpn/ssl/nscert.hpp | 64 + openvpn/ssl/peerinfo.hpp | 128 + openvpn/ssl/proto.hpp | 3844 ++++++ openvpn/ssl/proto_context_options.hpp | 64 + openvpn/ssl/protostack.hpp | 486 + openvpn/ssl/psid.hpp | 108 + openvpn/ssl/sess_ticket.hpp | 242 + openvpn/ssl/sni_handler.hpp | 52 + openvpn/ssl/sni_metadata.hpp | 44 + openvpn/ssl/sslapi.hpp | 202 + openvpn/ssl/sslchoose.hpp | 98 + openvpn/ssl/sslconsts.hpp | 84 + openvpn/ssl/ssllog.hpp | 29 + openvpn/ssl/tls_cert_profile.hpp | 145 + openvpn/ssl/tls_remote.hpp | 96 + openvpn/ssl/tlsprf.hpp | 395 + openvpn/ssl/tlsver.hpp | 117 + openvpn/time/asiotimer.hpp | 84 + openvpn/time/asiotimersafe.hpp | 91 + openvpn/time/coarsetime.hpp | 70 + openvpn/time/durhelper.hpp | 105 + openvpn/time/epoch.hpp | 52 + openvpn/time/skew.hpp | 53 + openvpn/time/time.hpp | 379 + openvpn/time/timestr.hpp | 204 + openvpn/transport/altproxy.hpp | 77 + openvpn/transport/client/extern/config.hpp | 47 + openvpn/transport/client/extern/fw.hpp | 43 + openvpn/transport/client/httpcli.hpp | 1037 ++ openvpn/transport/client/relay.hpp | 165 + openvpn/transport/client/tcpcli.hpp | 399 + openvpn/transport/client/transbase.hpp | 105 + openvpn/transport/client/udpcli.hpp | 336 + openvpn/transport/dco.hpp | 73 + openvpn/transport/gremlin.hpp | 224 + openvpn/transport/mssfix.hpp | 150 + openvpn/transport/mutate.hpp | 40 + openvpn/transport/pktstream.hpp | 163 + openvpn/transport/protocol.hpp | 314 + openvpn/transport/reconnect_notify.hpp | 36 + openvpn/transport/server/transbase.hpp | 150 + openvpn/transport/socket_protect.hpp | 47 + openvpn/transport/tcplink.hpp | 98 + openvpn/transport/tcplinkbase.hpp | 39 + openvpn/transport/tcplinkcommon.hpp | 457 + openvpn/transport/udplink.hpp | 246 + openvpn/tun/builder/base.hpp | 254 + openvpn/tun/builder/capture.hpp | 821 ++ openvpn/tun/builder/client.hpp | 317 + openvpn/tun/builder/rgwflags.hpp | 35 + openvpn/tun/builder/setup.hpp | 62 + openvpn/tun/client/dhcp_capture.hpp | 320 + openvpn/tun/client/emuexr.hpp | 50 + openvpn/tun/client/tunbase.hpp | 92 + openvpn/tun/client/tunnull.hpp | 120 + openvpn/tun/client/tunprop.hpp | 654 + openvpn/tun/extern/config.hpp | 45 + openvpn/tun/extern/fw.hpp | 49 + openvpn/tun/ipv6_setting.hpp | 89 + openvpn/tun/layer.hpp | 130 + openvpn/tun/linux/client/sitnl.hpp | 1016 ++ openvpn/tun/linux/client/tuncli.hpp | 356 + openvpn/tun/linux/client/tuniproute.hpp | 351 + openvpn/tun/linux/client/tunnetlink.hpp | 700 + openvpn/tun/linux/client/tunsetup.hpp | 244 + openvpn/tun/mac/client/tuncli.hpp | 379 + openvpn/tun/mac/client/tunsetup.hpp | 507 + openvpn/tun/mac/dsdict.hpp | 184 + openvpn/tun/mac/gwv4.hpp | 282 + openvpn/tun/mac/macdns.hpp | 374 + openvpn/tun/mac/macdns_watchdog.hpp | 291 + openvpn/tun/mac/macgw.hpp | 88 + openvpn/tun/mac/macproxy.hpp | 99 + openvpn/tun/mac/tunutil.hpp | 76 + openvpn/tun/mac/utun.hpp | 114 + openvpn/tun/persist/tunpersist.hpp | 164 + openvpn/tun/persist/tunwrap.hpp | 116 + openvpn/tun/persist/tunwrapasio.hpp | 80 + openvpn/tun/proxy.hpp | 84 + openvpn/tun/server/tunbase.hpp | 117 + openvpn/tun/tunio.hpp | 280 + openvpn/tun/tunlog.hpp | 45 + openvpn/tun/tunmtu.hpp | 34 + openvpn/tun/tunspec.hpp | 65 + openvpn/tun/win/client/clientconfig.hpp | 99 + openvpn/tun/win/client/setupbase.hpp | 78 + openvpn/tun/win/client/tuncli.hpp | 410 + openvpn/tun/win/client/tunsetup.hpp | 921 ++ openvpn/tun/win/client/wintun.hpp | 318 + openvpn/tun/win/nrpt.hpp | 198 + openvpn/tun/win/ringbuffer.hpp | 172 + openvpn/tun/win/tunutil.hpp | 1222 ++ openvpn/tun/win/wfp.hpp | 314 + openvpn/tun/win/winproxy.hpp | 182 + openvpn/win/call.hpp | 167 + openvpn/win/cmd.hpp | 65 + openvpn/win/console.hpp | 152 + openvpn/win/event.hpp | 108 + openvpn/win/handle.hpp | 45 + openvpn/win/impersonate.hpp | 220 + openvpn/win/modname.hpp | 57 + openvpn/win/reg.hpp | 117 + openvpn/win/scoped_handle.hpp | 132 + openvpn/win/sleep.hpp | 60 + openvpn/win/unicode.hpp | 96 + openvpn/win/winerr.hpp | 51 + scripts/build | 386 + scripts/build-extras/zlib.sh | 8 + scripts/linux/build-all | 22 + scripts/linux/build-boost | 18 + scripts/linux/build-cityhash | 14 + scripts/linux/build-lz4 | 14 + scripts/linux/build-lzo | 14 + scripts/linux/build-mbedtls | 19 + scripts/linux/build-openssl | 35 + scripts/linux/build-polarssl | 20 + scripts/linux/build-polarssl-ovpn2 | 15 + scripts/linux/build-snappy | 13 + scripts/linux/consolidate-so | 10 + scripts/mac/build-all | 37 + scripts/mac/build-boost | 23 + scripts/mac/build-lz4 | 27 + scripts/mac/build-lzo | 28 + scripts/mac/build-mbedtls | 37 + scripts/mac/build-minicrypto | 27 + scripts/mac/build-openssl | 39 + scripts/mac/build-polarssl | 41 + scripts/mac/build-snappy | 27 + scripts/snapshot | 36 + scripts/update-copyright | 51 + scripts/version | 34 + test/ovpncli/.gitignore | 3 + test/ovpncli/CMakeLists.txt | 13 + test/ovpncli/README.txt | 24 + test/ovpncli/cli.cpp | 1202 ++ test/ovpncli/go | 45 + test/ssl/.gitignore | 5 + test/ssl/README.txt | 80 + test/ssl/ca.crt | 35 + test/ssl/client.crt | 103 + test/ssl/client.key | 28 + test/ssl/dh.pem | 8 + test/ssl/go | 23 + test/ssl/proto.cpp | 1148 ++ test/ssl/protowin.h | 2 + test/ssl/server.crt | 113 + test/ssl/server.key | 28 + test/ssl/tls-auth.key | 21 + test/ssl/tls-crypt-v2-client.key | 14 + test/ssl/tls-crypt-v2-server.key | 5 + test/unittests/CMakeLists.txt | 51 + test/unittests/README-comp.txt | 3 + test/unittests/comp-testdata/alice29.txt | 3609 ++++++ test/unittests/comp-testdata/asyoulik.txt | 4122 ++++++ test/unittests/comp-testdata/baddata1.snappy | Bin 0 -> 27512 bytes test/unittests/comp-testdata/baddata2.snappy | Bin 0 -> 27483 bytes test/unittests/comp-testdata/baddata3.snappy | Bin 0 -> 28384 bytes test/unittests/comp-testdata/cp.html | 645 + test/unittests/comp-testdata/fields.c | 431 + test/unittests/comp-testdata/geo.protodata | Bin 0 -> 118588 bytes test/unittests/comp-testdata/grammar.lsp | 94 + test/unittests/comp-testdata/house.jpg | Bin 0 -> 126958 bytes test/unittests/comp-testdata/html | 1 + test/unittests/comp-testdata/html_x_4 | 1 + test/unittests/comp-testdata/kennedy.xls | Bin 0 -> 1029744 bytes test/unittests/comp-testdata/kppkn.gtb | Bin 0 -> 184320 bytes test/unittests/comp-testdata/lcet10.txt | 7518 +++++++++++ .../comp-testdata/mapreduce-osdi-1.pdf | Bin 0 -> 94330 bytes test/unittests/comp-testdata/plrabn12.txt | 10699 ++++++++++++++++ test/unittests/comp-testdata/ptt5 | Bin 0 -> 513216 bytes test/unittests/comp-testdata/sum | Bin 0 -> 38240 bytes test/unittests/comp-testdata/urls.10K | 10000 +++++++++++++++ test/unittests/comp-testdata/xargs.1 | 112 + test/unittests/core_tests.cpp | 37 + test/unittests/test_b64.cpp | 181 + test/unittests/test_common.h | 36 + test/unittests/test_comp.cpp | 262 + test/unittests/test_cpu_time.cpp | 222 + test/unittests/test_log.cpp | 53 + test/unittests/test_route_emulation.cpp | 296 + test/unittests/test_sitnl.cpp | 326 + test/unittests/unittests.vcxproj | 116 + test/unittests/unittests.vcxproj.filters | 22 + test/unused | 402 + vars/o3 | 1 + vars/setlibpath | 1 + vars/setpath | 1 + vars/vars-android-a7a | 15 + vars/vars-android-a7a-dbg | 15 + vars/vars-android-a8a | 15 + vars/vars-android-a8a-dbg | 15 + vars/vars-android-srconly | 1 + vars/vars-android-x86 | 15 + vars/vars-arm-cross | 5 + vars/vars-ios | 10 + vars/vars-ios-dbg | 11 + vars/vars-iossim | 10 + vars/vars-iossim-dbg | 11 + vars/vars-linux | 13 + vars/vars-linux-dbg | 12 + vars/vars-osx | 12 + vars/vars-osx-dbg | 12 + vars/vars-osx64 | 12 + vars/vars-osx64-dbg | 12 + vars/vars-reset | 21 + vars/vars-win | 1 + win/.gitignore | 12 + win/build.py | 100 + win/buildep.py | 170 + win/ovpn3-core.sln | 56 + win/ovpn3-core.vcxproj | 746 ++ win/ovpn3-core.vcxproj.filters | 439 + win/unused/buildep.py | 59 + win/utils.py | 317 + win/vcvarsall.patch | 27 + 655 files changed, 146468 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100755 .travis/build-check.sh create mode 100755 .travis/build-deps.sh create mode 100644 CLA.rst create mode 100644 CMakeLists.txt create mode 100644 CONTRIBUTING.rst create mode 100644 COPYRIGHT.AGPLV3 create mode 100644 LICENSE.rst create mode 100644 README.rst create mode 100644 VersionNumbering.rst create mode 100644 appveyor.yml create mode 100644 client/ovpncli.cpp create mode 100644 client/ovpncli.hpp create mode 100644 cmake/CMakeLists.txt.in create mode 100644 cmake/FindLZ4.cmake create mode 100644 cmake/FindmbedTLS.cmake create mode 100644 cmake/dlgoogletest.cmake create mode 100644 cmake/findcoredeps.cmake create mode 100644 cmake/mypragmaonce.cmake create mode 100755 deps/asio/build-asio create mode 100644 deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch create mode 100644 deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch create mode 100644 deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch create mode 100644 deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch create mode 100755 deps/asio/snapshot-asio create mode 100644 deps/boost/atomic-1.55.0.patch create mode 100755 deps/boost/build-boost create mode 100644 deps/boost/intrusive_ptr.patch create mode 100644 deps/boost/page_size.patch create mode 100755 deps/cityhash/build-cityhash create mode 100644 deps/functions.sh create mode 100644 deps/lib-versions create mode 100755 deps/lz4/build-lz4 create mode 100755 deps/lz4/snapshot-lz4 create mode 100755 deps/lzo/build-lzo create mode 100755 deps/mbedtls/build-mbedtls create mode 100644 deps/mbedtls/patches/0001-relax-x509-date-format-check.patch create mode 100644 deps/mbedtls/patches/0002-Enable-allowing-unsupported-critical-extensions-in-r.patch create mode 100644 deps/mbedtls/patches/0003-fix-gcc-android-build.patch create mode 100644 deps/minicrypto/aes-armv4.pl.patch create mode 100755 deps/minicrypto/arm-as-to-ios create mode 100755 deps/minicrypto/arm-as-to-ios.orig create mode 100755 deps/minicrypto/build-minicrypto create mode 100755 deps/minicrypto/build-minicrypto-osx create mode 100644 deps/minicrypto/sha512-armv4.pl.patch create mode 100755 deps/openssl/build-openssl create mode 100644 deps/polarssl/.gitignore create mode 100644 deps/polarssl/CMakeLists.txt create mode 100644 deps/polarssl/README.txt create mode 100644 deps/polarssl/android.cmake create mode 100644 deps/polarssl/apple.cmake create mode 100644 deps/polarssl/bignum-arm.patch create mode 100755 deps/polarssl/build-detail-patch create mode 100755 deps/polarssl/build-mini-openssl create mode 100755 deps/polarssl/build-polarssl create mode 100755 deps/polarssl/build-polarssl-patch create mode 100644 deps/polarssl/config.h create mode 100644 deps/polarssl/config.h.orig create mode 100644 deps/polarssl/config12.h create mode 100644 deps/polarssl/crypto-alt.txt create mode 100644 deps/polarssl/dhm.patch create mode 100644 deps/polarssl/entropy-printf.patch create mode 100755 deps/polarssl/gitar create mode 100644 deps/polarssl/intel_cpu.c create mode 100644 deps/polarssl/linux-arm.cmake create mode 100644 deps/polarssl/polar-openssl.patch create mode 100644 deps/polarssl/polarssl-minicrypto.patch create mode 100644 deps/polarssl/ref create mode 100644 deps/polarssl/ref-aesni create mode 100644 deps/polarssl/relaxed-x509-date.patch create mode 100755 deps/polarssl/testpatch create mode 100644 deps/polarssl/unused/polarssl-const-ciphersuite.patch create mode 100644 deps/polarssl/unused/polarssl-enum.patch create mode 100644 deps/polarssl/unused/polarssl-epki.patch create mode 100644 deps/polarssl/unused/polarssl-invalid-mac.patch create mode 100644 deps/polarssl/unused/trustex.patch create mode 100755 deps/snappy/build-snappy create mode 100644 doc/openvpn-protocol-extensions.txt create mode 100755 docker-build.sh create mode 100644 dockerfiles/Dockerfile.centos create mode 100644 dockerfiles/Dockerfile.debian create mode 100644 dockerfiles/Dockerfile.ubu create mode 100644 javacli/.gitignore create mode 100644 javacli/Client.java create mode 100644 javacli/Main.java create mode 100644 javacli/OpenVPNClientThread.java create mode 100644 javacli/android/cpu.cpp create mode 100644 javacli/android/jellybean_hack.cpp create mode 100755 javacli/build-android create mode 100755 javacli/build-linux create mode 100644 javacli/ovpncli.i create mode 100644 mac/.gitignore create mode 100644 mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj create mode 100644 mac/ovpn3-core/ovpn3-core.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 openvpn/addr/addrlist.hpp create mode 100644 openvpn/addr/addrpair.hpp create mode 100644 openvpn/addr/addrspacesplit.hpp create mode 100644 openvpn/addr/ip.hpp create mode 100644 openvpn/addr/iperr.hpp create mode 100644 openvpn/addr/ipv4.hpp create mode 100644 openvpn/addr/ipv6.hpp create mode 100644 openvpn/addr/macaddr.hpp create mode 100644 openvpn/addr/pool.hpp create mode 100644 openvpn/addr/quoteip.hpp create mode 100644 openvpn/addr/randaddr.hpp create mode 100644 openvpn/addr/range.hpp create mode 100644 openvpn/addr/regex.hpp create mode 100644 openvpn/addr/route.hpp create mode 100644 openvpn/apple/cf/cf.hpp create mode 100644 openvpn/apple/cf/cfhelper.hpp create mode 100644 openvpn/apple/cf/cfhost.hpp create mode 100644 openvpn/apple/cf/cfrunloop.hpp create mode 100644 openvpn/apple/cf/cfsec.hpp create mode 100644 openvpn/apple/cf/cfsocket.hpp create mode 100644 openvpn/apple/cf/cfstream.hpp create mode 100644 openvpn/apple/cf/cftimer.hpp create mode 100644 openvpn/apple/cf/error.hpp create mode 100644 openvpn/apple/iosactiveiface.hpp create mode 100644 openvpn/apple/maclife.hpp create mode 100644 openvpn/apple/macsleep.hpp create mode 100644 openvpn/apple/macver.hpp create mode 100644 openvpn/apple/reach.hpp create mode 100644 openvpn/apple/reachable.hpp create mode 100644 openvpn/apple/scdynstore.hpp create mode 100644 openvpn/apple/ver.hpp create mode 100644 openvpn/applecrypto/crypto/api.hpp create mode 100644 openvpn/applecrypto/crypto/cipher.hpp create mode 100644 openvpn/applecrypto/crypto/digest.hpp create mode 100644 openvpn/applecrypto/crypto/hmac.hpp create mode 100644 openvpn/applecrypto/ssl/sslctx.hpp create mode 100644 openvpn/applecrypto/util/rand.hpp create mode 100644 openvpn/asio/asioboundsock.hpp create mode 100644 openvpn/asio/asiocontext.hpp create mode 100644 openvpn/asio/asioerr.hpp create mode 100644 openvpn/asio/asiopolysock.hpp create mode 100644 openvpn/asio/asioresolverres.hpp create mode 100644 openvpn/asio/asiosignal.hpp create mode 100644 openvpn/asio/asiostop.hpp create mode 100644 openvpn/asio/asiowork.hpp create mode 100644 openvpn/asio/scoped_asio_stream.hpp create mode 100644 openvpn/auth/authcert.hpp create mode 100644 openvpn/auth/authcreds.hpp create mode 100644 openvpn/auth/cr.hpp create mode 100644 openvpn/auth/validatecreds.hpp create mode 100644 openvpn/buffer/asiobuf.hpp create mode 100644 openvpn/buffer/bufclamp.hpp create mode 100644 openvpn/buffer/bufcomplete.hpp create mode 100644 openvpn/buffer/bufcomposed.hpp create mode 100644 openvpn/buffer/buffer.hpp create mode 100644 openvpn/buffer/bufhex.hpp create mode 100644 openvpn/buffer/buflimit.hpp create mode 100644 openvpn/buffer/buflineiter.hpp create mode 100644 openvpn/buffer/buflist.hpp create mode 100644 openvpn/buffer/bufread.hpp create mode 100644 openvpn/buffer/bufstatic.hpp create mode 100644 openvpn/buffer/bufstr.hpp create mode 100644 openvpn/buffer/bufstream.hpp create mode 100644 openvpn/buffer/lz4.hpp create mode 100644 openvpn/buffer/memq.hpp create mode 100644 openvpn/buffer/safestr.hpp create mode 100644 openvpn/buffer/zlib.hpp create mode 100644 openvpn/client/async_resolve.hpp create mode 100644 openvpn/client/async_resolve/asio.hpp create mode 100644 openvpn/client/async_resolve/generic.hpp create mode 100644 openvpn/client/cliconnect.hpp create mode 100644 openvpn/client/cliconstants.hpp create mode 100644 openvpn/client/clicreds.hpp create mode 100644 openvpn/client/cliemuexr.hpp create mode 100644 openvpn/client/clievent.hpp create mode 100644 openvpn/client/clihalt.hpp create mode 100644 openvpn/client/clilife.hpp create mode 100644 openvpn/client/cliopt.hpp create mode 100644 openvpn/client/cliopthelper.hpp create mode 100644 openvpn/client/cliproto.hpp create mode 100644 openvpn/client/ipverflags.hpp create mode 100644 openvpn/client/optfilt.hpp create mode 100644 openvpn/client/remotelist.hpp create mode 100644 openvpn/client/rgopt.hpp create mode 100644 openvpn/common/abort.hpp create mode 100644 openvpn/common/action.hpp create mode 100644 openvpn/common/actionthread.hpp create mode 100644 openvpn/common/appversion.hpp create mode 100644 openvpn/common/arch.hpp create mode 100644 openvpn/common/argv.hpp create mode 100644 openvpn/common/arraysize.hpp create mode 100644 openvpn/common/asyncsleep.hpp create mode 100644 openvpn/common/autoreset.hpp create mode 100644 openvpn/common/base64.hpp create mode 100644 openvpn/common/bigmutex.hpp create mode 100644 openvpn/common/binprefix.hpp create mode 100644 openvpn/common/circ_list.hpp create mode 100644 openvpn/common/clamp.hpp create mode 100644 openvpn/common/cleanup.hpp create mode 100644 openvpn/common/core.hpp create mode 100644 openvpn/common/count.hpp create mode 100644 openvpn/common/daemon.hpp create mode 100644 openvpn/common/demangle.hpp create mode 100644 openvpn/common/destruct.hpp create mode 100644 openvpn/common/endian.hpp create mode 100644 openvpn/common/endian_platform.hpp create mode 100644 openvpn/common/enumdir.hpp create mode 100644 openvpn/common/environ.hpp create mode 100644 openvpn/common/exception.hpp create mode 100644 openvpn/common/extern.hpp create mode 100644 openvpn/common/ffs.hpp create mode 100644 openvpn/common/file.hpp create mode 100644 openvpn/common/fileatomic.hpp create mode 100644 openvpn/common/fileunix.hpp create mode 100644 openvpn/common/format.hpp create mode 100644 openvpn/common/function.hpp create mode 100644 openvpn/common/getopt.hpp create mode 100644 openvpn/common/getpw.hpp create mode 100644 openvpn/common/glob.hpp create mode 100644 openvpn/common/hash.hpp create mode 100644 openvpn/common/hexstr.hpp create mode 100644 openvpn/common/hostlist.hpp create mode 100644 openvpn/common/hostname.hpp create mode 100644 openvpn/common/hostport.hpp create mode 100644 openvpn/common/jsonlib.hpp create mode 100644 openvpn/common/lex.hpp create mode 100644 openvpn/common/likely.hpp create mode 100644 openvpn/common/link.hpp create mode 100644 openvpn/common/logrotate.hpp create mode 100644 openvpn/common/logsetup.hpp create mode 100644 openvpn/common/memneq.hpp create mode 100644 openvpn/common/mode.hpp create mode 100644 openvpn/common/modstat.hpp create mode 100644 openvpn/common/msfind.hpp create mode 100644 openvpn/common/msgwin.hpp create mode 100644 openvpn/common/number.hpp create mode 100644 openvpn/common/olong.hpp create mode 100644 openvpn/common/option_error.hpp create mode 100644 openvpn/common/options.hpp create mode 100644 openvpn/common/ostream.hpp create mode 100644 openvpn/common/path.hpp create mode 100644 openvpn/common/peercred.hpp create mode 100644 openvpn/common/persistfile.hpp create mode 100644 openvpn/common/pipe.hpp create mode 100644 openvpn/common/platform.hpp create mode 100644 openvpn/common/platform_name.hpp create mode 100644 openvpn/common/platform_string.hpp create mode 100644 openvpn/common/process.hpp create mode 100644 openvpn/common/pthreadcond.hpp create mode 100644 openvpn/common/rc.hpp create mode 100644 openvpn/common/redir.hpp create mode 100644 openvpn/common/runcontext.hpp create mode 100644 openvpn/common/scoped_fd.hpp create mode 100644 openvpn/common/sess_id.hpp create mode 100644 openvpn/common/signal.hpp create mode 100644 openvpn/common/signal_name.hpp create mode 100644 openvpn/common/size.hpp create mode 100644 openvpn/common/sleep.hpp create mode 100644 openvpn/common/sockopt.hpp create mode 100644 openvpn/common/socktypes.hpp create mode 100644 openvpn/common/split.hpp create mode 100644 openvpn/common/splitlines.hpp create mode 100644 openvpn/common/stat.hpp create mode 100644 openvpn/common/stop.hpp create mode 100644 openvpn/common/strerror.hpp create mode 100644 openvpn/common/string.hpp create mode 100644 openvpn/common/stringize.hpp create mode 100644 openvpn/common/stringtempl.hpp create mode 100644 openvpn/common/strneq.hpp create mode 100644 openvpn/common/tempfile.hpp create mode 100644 openvpn/common/to_string.hpp create mode 100644 openvpn/common/umask.hpp create mode 100644 openvpn/common/unicode-impl.hpp create mode 100644 openvpn/common/unicode.hpp create mode 100644 openvpn/common/uniqueptr.hpp create mode 100644 openvpn/common/usecount.hpp create mode 100644 openvpn/common/usergroup.hpp create mode 100644 openvpn/common/userpass.hpp create mode 100644 openvpn/common/valgrind.hpp create mode 100644 openvpn/common/version.hpp create mode 100644 openvpn/common/waitbarrier.hpp create mode 100644 openvpn/common/write.hpp create mode 100644 openvpn/common/wstring.hpp create mode 100644 openvpn/compress/compnull.hpp create mode 100644 openvpn/compress/compress.hpp create mode 100644 openvpn/compress/compstub.hpp create mode 100644 openvpn/compress/lz4.hpp create mode 100644 openvpn/compress/lzo.hpp create mode 100644 openvpn/compress/lzoasym.hpp create mode 100644 openvpn/compress/lzoasym_impl.hpp create mode 100644 openvpn/compress/lzoselect.hpp create mode 100644 openvpn/compress/snappy.hpp create mode 100644 openvpn/crypto/bs64_data_limit.hpp create mode 100644 openvpn/crypto/cipher.hpp create mode 100644 openvpn/crypto/crypto_aead.hpp create mode 100644 openvpn/crypto/crypto_chm.hpp create mode 100644 openvpn/crypto/cryptoalgs.hpp create mode 100644 openvpn/crypto/cryptodc.hpp create mode 100644 openvpn/crypto/cryptodcsel.hpp create mode 100644 openvpn/crypto/decrypt_chm.hpp create mode 100644 openvpn/crypto/digestapi.hpp create mode 100644 openvpn/crypto/encrypt_chm.hpp create mode 100644 openvpn/crypto/hashstr.hpp create mode 100644 openvpn/crypto/ovpnhmac.hpp create mode 100644 openvpn/crypto/packet_id.hpp create mode 100644 openvpn/crypto/selftest.hpp create mode 100644 openvpn/crypto/static_key.hpp create mode 100644 openvpn/crypto/tls_crypt.hpp create mode 100644 openvpn/crypto/tls_crypt_v2.hpp create mode 100644 openvpn/dco/dcocli.hpp create mode 100644 openvpn/dco/ipcollbase.hpp create mode 100644 openvpn/error/error.hpp create mode 100644 openvpn/error/excode.hpp create mode 100644 openvpn/frame/frame.hpp create mode 100644 openvpn/frame/frame_init.hpp create mode 100644 openvpn/frame/memq_dgram.hpp create mode 100644 openvpn/frame/memq_stream.hpp create mode 100644 openvpn/http/header.hpp create mode 100644 openvpn/http/htmlskip.hpp create mode 100644 openvpn/http/method.hpp create mode 100644 openvpn/http/parseutil.hpp create mode 100644 openvpn/http/reply.hpp create mode 100644 openvpn/http/request.hpp create mode 100644 openvpn/http/status.hpp create mode 100644 openvpn/http/urlencode.hpp create mode 100644 openvpn/http/urlparm.hpp create mode 100644 openvpn/http/urlparse.hpp create mode 100644 openvpn/http/validate_uri.hpp create mode 100644 openvpn/http/webexcept.hpp create mode 100644 openvpn/init/cryptoinit.hpp create mode 100644 openvpn/init/engineinit.hpp create mode 100644 openvpn/init/initprocess.hpp create mode 100644 openvpn/io/io.hpp create mode 100644 openvpn/ip/csum.hpp create mode 100644 openvpn/ip/dhcp.hpp create mode 100644 openvpn/ip/eth.hpp create mode 100644 openvpn/ip/icmp4.hpp create mode 100644 openvpn/ip/icmp6.hpp create mode 100644 openvpn/ip/ip4.hpp create mode 100644 openvpn/ip/ip6.hpp create mode 100644 openvpn/ip/ipcommon.hpp create mode 100644 openvpn/ip/ping4.hpp create mode 100644 openvpn/ip/ping6.hpp create mode 100644 openvpn/ip/ptb.hpp create mode 100644 openvpn/ip/tcp.hpp create mode 100644 openvpn/ip/udp.hpp create mode 100644 openvpn/kovpn/kocrypto.hpp create mode 100644 openvpn/kovpn/kodev.hpp create mode 100644 openvpn/kovpn/korekey.hpp create mode 100644 openvpn/kovpn/koroute.hpp create mode 100644 openvpn/kovpn/kostats.hpp create mode 100644 openvpn/kovpn/kovpn.hpp create mode 100644 openvpn/legal/copyright.hpp create mode 100644 openvpn/linux/core.hpp create mode 100644 openvpn/linux/cputime.hpp create mode 100644 openvpn/linux/daemon_alive.hpp create mode 100644 openvpn/linux/procfs.hpp create mode 100644 openvpn/log/logbase.hpp create mode 100644 openvpn/log/logbasesimple.hpp create mode 100644 openvpn/log/logbasesimplemac.hpp create mode 100644 openvpn/log/logdatetime.hpp create mode 100644 openvpn/log/lognull.hpp create mode 100644 openvpn/log/logperiod.hpp create mode 100644 openvpn/log/logsimple.hpp create mode 100644 openvpn/log/logthread.hpp create mode 100644 openvpn/log/sessionstats.hpp create mode 100644 openvpn/mbedtls/crypto/api.hpp create mode 100644 openvpn/mbedtls/crypto/cipher.hpp create mode 100644 openvpn/mbedtls/crypto/ciphergcm.hpp create mode 100644 openvpn/mbedtls/crypto/digest.hpp create mode 100644 openvpn/mbedtls/crypto/hmac.hpp create mode 100644 openvpn/mbedtls/pki/dh.hpp create mode 100644 openvpn/mbedtls/pki/pkctx.hpp create mode 100644 openvpn/mbedtls/pki/x509cert.hpp create mode 100644 openvpn/mbedtls/pki/x509crl.hpp create mode 100644 openvpn/mbedtls/ssl/sslctx.hpp create mode 100644 openvpn/mbedtls/util/error.hpp create mode 100644 openvpn/mbedtls/util/pem.hpp create mode 100644 openvpn/mbedtls/util/pkcs1.hpp create mode 100644 openvpn/mbedtls/util/rand.hpp create mode 100644 openvpn/mbedtls/util/selftest.hpp create mode 100644 openvpn/netconf/enumiface.hpp create mode 100644 openvpn/netconf/hwaddr.hpp create mode 100644 openvpn/netconf/ios/net-route.h create mode 100644 openvpn/netconf/linux/gw.hpp create mode 100644 openvpn/netconf/linux/gwnetlink.hpp create mode 100644 openvpn/netconf/linux/route.hpp create mode 100644 openvpn/openssl/bio/bio_memq_dgram.hpp create mode 100644 openvpn/openssl/bio/bio_memq_stream.hpp create mode 100644 openvpn/openssl/compat.hpp create mode 100644 openvpn/openssl/crypto/api.hpp create mode 100644 openvpn/openssl/crypto/cipher.hpp create mode 100644 openvpn/openssl/crypto/ciphergcm.hpp create mode 100644 openvpn/openssl/crypto/digest.hpp create mode 100644 openvpn/openssl/crypto/hmac.hpp create mode 100644 openvpn/openssl/pki/crl.hpp create mode 100644 openvpn/openssl/pki/dh.hpp create mode 100644 openvpn/openssl/pki/pkey.hpp create mode 100644 openvpn/openssl/pki/x509.hpp create mode 100644 openvpn/openssl/pki/x509store.hpp create mode 100644 openvpn/openssl/sign/pkcs7verify.hpp create mode 100644 openvpn/openssl/sign/verify.hpp create mode 100644 openvpn/openssl/ssl/sess_cache.hpp create mode 100644 openvpn/openssl/ssl/sslctx.hpp create mode 100644 openvpn/openssl/util/engine.hpp create mode 100644 openvpn/openssl/util/error.hpp create mode 100644 openvpn/openssl/util/init.hpp create mode 100644 openvpn/openssl/util/pem.hpp create mode 100644 openvpn/openssl/util/rand.hpp create mode 100644 openvpn/openssl/util/reseed.hpp create mode 100644 openvpn/openssl/util/tokenencrypt.hpp create mode 100644 openvpn/options/continuation.hpp create mode 100644 openvpn/options/merge.hpp create mode 100644 openvpn/options/sanitize.hpp create mode 100644 openvpn/options/servpush.hpp create mode 100644 openvpn/pki/cclist.hpp create mode 100644 openvpn/pki/epkibase.hpp create mode 100644 openvpn/pki/pkcs1.hpp create mode 100644 openvpn/pki/pktype.hpp create mode 100644 openvpn/pki/x509track.hpp create mode 100644 openvpn/proxy/httpdigest.hpp create mode 100644 openvpn/proxy/ntlm.hpp create mode 100644 openvpn/proxy/proxyauth.hpp create mode 100644 openvpn/random/devurand.hpp create mode 100644 openvpn/random/mtrandapi.hpp create mode 100644 openvpn/random/rand2.hpp create mode 100644 openvpn/random/randapi.hpp create mode 100644 openvpn/random/randbytestore.hpp create mode 100644 openvpn/random/randistrib.hpp create mode 100644 openvpn/reliable/relack.hpp create mode 100644 openvpn/reliable/relcommon.hpp create mode 100644 openvpn/reliable/relrecv.hpp create mode 100644 openvpn/reliable/relsend.hpp create mode 100644 openvpn/server/listenlist.hpp create mode 100644 openvpn/server/manage.hpp create mode 100644 openvpn/server/peeraddr.hpp create mode 100644 openvpn/server/peerstats.hpp create mode 100644 openvpn/server/servhalt.hpp create mode 100644 openvpn/server/servproto.hpp create mode 100644 openvpn/server/vpnservnetblock.hpp create mode 100644 openvpn/server/vpnservpool.hpp create mode 100644 openvpn/ssl/datalimit.hpp create mode 100644 openvpn/ssl/is_openvpn_protocol.hpp create mode 100644 openvpn/ssl/kuparse.hpp create mode 100644 openvpn/ssl/mssparms.hpp create mode 100644 openvpn/ssl/nscert.hpp create mode 100644 openvpn/ssl/peerinfo.hpp create mode 100644 openvpn/ssl/proto.hpp create mode 100644 openvpn/ssl/proto_context_options.hpp create mode 100644 openvpn/ssl/protostack.hpp create mode 100644 openvpn/ssl/psid.hpp create mode 100644 openvpn/ssl/sess_ticket.hpp create mode 100644 openvpn/ssl/sni_handler.hpp create mode 100644 openvpn/ssl/sni_metadata.hpp create mode 100644 openvpn/ssl/sslapi.hpp create mode 100644 openvpn/ssl/sslchoose.hpp create mode 100644 openvpn/ssl/sslconsts.hpp create mode 100644 openvpn/ssl/ssllog.hpp create mode 100644 openvpn/ssl/tls_cert_profile.hpp create mode 100644 openvpn/ssl/tls_remote.hpp create mode 100644 openvpn/ssl/tlsprf.hpp create mode 100644 openvpn/ssl/tlsver.hpp create mode 100644 openvpn/time/asiotimer.hpp create mode 100644 openvpn/time/asiotimersafe.hpp create mode 100644 openvpn/time/coarsetime.hpp create mode 100644 openvpn/time/durhelper.hpp create mode 100644 openvpn/time/epoch.hpp create mode 100644 openvpn/time/skew.hpp create mode 100644 openvpn/time/time.hpp create mode 100644 openvpn/time/timestr.hpp create mode 100644 openvpn/transport/altproxy.hpp create mode 100644 openvpn/transport/client/extern/config.hpp create mode 100644 openvpn/transport/client/extern/fw.hpp create mode 100644 openvpn/transport/client/httpcli.hpp create mode 100644 openvpn/transport/client/relay.hpp create mode 100644 openvpn/transport/client/tcpcli.hpp create mode 100644 openvpn/transport/client/transbase.hpp create mode 100644 openvpn/transport/client/udpcli.hpp create mode 100644 openvpn/transport/dco.hpp create mode 100644 openvpn/transport/gremlin.hpp create mode 100644 openvpn/transport/mssfix.hpp create mode 100644 openvpn/transport/mutate.hpp create mode 100644 openvpn/transport/pktstream.hpp create mode 100644 openvpn/transport/protocol.hpp create mode 100644 openvpn/transport/reconnect_notify.hpp create mode 100644 openvpn/transport/server/transbase.hpp create mode 100644 openvpn/transport/socket_protect.hpp create mode 100644 openvpn/transport/tcplink.hpp create mode 100644 openvpn/transport/tcplinkbase.hpp create mode 100644 openvpn/transport/tcplinkcommon.hpp create mode 100644 openvpn/transport/udplink.hpp create mode 100644 openvpn/tun/builder/base.hpp create mode 100644 openvpn/tun/builder/capture.hpp create mode 100644 openvpn/tun/builder/client.hpp create mode 100644 openvpn/tun/builder/rgwflags.hpp create mode 100644 openvpn/tun/builder/setup.hpp create mode 100644 openvpn/tun/client/dhcp_capture.hpp create mode 100644 openvpn/tun/client/emuexr.hpp create mode 100644 openvpn/tun/client/tunbase.hpp create mode 100644 openvpn/tun/client/tunnull.hpp create mode 100644 openvpn/tun/client/tunprop.hpp create mode 100644 openvpn/tun/extern/config.hpp create mode 100644 openvpn/tun/extern/fw.hpp create mode 100644 openvpn/tun/ipv6_setting.hpp create mode 100644 openvpn/tun/layer.hpp create mode 100644 openvpn/tun/linux/client/sitnl.hpp create mode 100644 openvpn/tun/linux/client/tuncli.hpp create mode 100644 openvpn/tun/linux/client/tuniproute.hpp create mode 100644 openvpn/tun/linux/client/tunnetlink.hpp create mode 100644 openvpn/tun/linux/client/tunsetup.hpp create mode 100644 openvpn/tun/mac/client/tuncli.hpp create mode 100644 openvpn/tun/mac/client/tunsetup.hpp create mode 100644 openvpn/tun/mac/dsdict.hpp create mode 100644 openvpn/tun/mac/gwv4.hpp create mode 100644 openvpn/tun/mac/macdns.hpp create mode 100644 openvpn/tun/mac/macdns_watchdog.hpp create mode 100644 openvpn/tun/mac/macgw.hpp create mode 100644 openvpn/tun/mac/macproxy.hpp create mode 100644 openvpn/tun/mac/tunutil.hpp create mode 100644 openvpn/tun/mac/utun.hpp create mode 100644 openvpn/tun/persist/tunpersist.hpp create mode 100644 openvpn/tun/persist/tunwrap.hpp create mode 100644 openvpn/tun/persist/tunwrapasio.hpp create mode 100644 openvpn/tun/proxy.hpp create mode 100644 openvpn/tun/server/tunbase.hpp create mode 100644 openvpn/tun/tunio.hpp create mode 100644 openvpn/tun/tunlog.hpp create mode 100644 openvpn/tun/tunmtu.hpp create mode 100644 openvpn/tun/tunspec.hpp create mode 100644 openvpn/tun/win/client/clientconfig.hpp create mode 100644 openvpn/tun/win/client/setupbase.hpp create mode 100644 openvpn/tun/win/client/tuncli.hpp create mode 100644 openvpn/tun/win/client/tunsetup.hpp create mode 100644 openvpn/tun/win/client/wintun.hpp create mode 100644 openvpn/tun/win/nrpt.hpp create mode 100644 openvpn/tun/win/ringbuffer.hpp create mode 100644 openvpn/tun/win/tunutil.hpp create mode 100644 openvpn/tun/win/wfp.hpp create mode 100644 openvpn/tun/win/winproxy.hpp create mode 100644 openvpn/win/call.hpp create mode 100644 openvpn/win/cmd.hpp create mode 100644 openvpn/win/console.hpp create mode 100644 openvpn/win/event.hpp create mode 100644 openvpn/win/handle.hpp create mode 100644 openvpn/win/impersonate.hpp create mode 100644 openvpn/win/modname.hpp create mode 100644 openvpn/win/reg.hpp create mode 100644 openvpn/win/scoped_handle.hpp create mode 100644 openvpn/win/sleep.hpp create mode 100644 openvpn/win/unicode.hpp create mode 100644 openvpn/win/winerr.hpp create mode 100755 scripts/build create mode 100644 scripts/build-extras/zlib.sh create mode 100755 scripts/linux/build-all create mode 100755 scripts/linux/build-boost create mode 100755 scripts/linux/build-cityhash create mode 100755 scripts/linux/build-lz4 create mode 100755 scripts/linux/build-lzo create mode 100755 scripts/linux/build-mbedtls create mode 100755 scripts/linux/build-openssl create mode 100755 scripts/linux/build-polarssl create mode 100755 scripts/linux/build-polarssl-ovpn2 create mode 100755 scripts/linux/build-snappy create mode 100755 scripts/linux/consolidate-so create mode 100755 scripts/mac/build-all create mode 100755 scripts/mac/build-boost create mode 100755 scripts/mac/build-lz4 create mode 100755 scripts/mac/build-lzo create mode 100755 scripts/mac/build-mbedtls create mode 100755 scripts/mac/build-minicrypto create mode 100755 scripts/mac/build-openssl create mode 100755 scripts/mac/build-polarssl create mode 100755 scripts/mac/build-snappy create mode 100755 scripts/snapshot create mode 100755 scripts/update-copyright create mode 100755 scripts/version create mode 100644 test/ovpncli/.gitignore create mode 100644 test/ovpncli/CMakeLists.txt create mode 100644 test/ovpncli/README.txt create mode 100644 test/ovpncli/cli.cpp create mode 100755 test/ovpncli/go create mode 100644 test/ssl/.gitignore create mode 100644 test/ssl/README.txt create mode 100644 test/ssl/ca.crt create mode 100644 test/ssl/client.crt create mode 100644 test/ssl/client.key create mode 100644 test/ssl/dh.pem create mode 100755 test/ssl/go create mode 100644 test/ssl/proto.cpp create mode 100644 test/ssl/protowin.h create mode 100644 test/ssl/server.crt create mode 100644 test/ssl/server.key create mode 100644 test/ssl/tls-auth.key create mode 100644 test/ssl/tls-crypt-v2-client.key create mode 100644 test/ssl/tls-crypt-v2-server.key create mode 100644 test/unittests/CMakeLists.txt create mode 100644 test/unittests/README-comp.txt create mode 100644 test/unittests/comp-testdata/alice29.txt create mode 100644 test/unittests/comp-testdata/asyoulik.txt create mode 100644 test/unittests/comp-testdata/baddata1.snappy create mode 100644 test/unittests/comp-testdata/baddata2.snappy create mode 100644 test/unittests/comp-testdata/baddata3.snappy create mode 100644 test/unittests/comp-testdata/cp.html create mode 100644 test/unittests/comp-testdata/fields.c create mode 100644 test/unittests/comp-testdata/geo.protodata create mode 100644 test/unittests/comp-testdata/grammar.lsp create mode 100644 test/unittests/comp-testdata/house.jpg create mode 100644 test/unittests/comp-testdata/html create mode 100644 test/unittests/comp-testdata/html_x_4 create mode 100644 test/unittests/comp-testdata/kennedy.xls create mode 100644 test/unittests/comp-testdata/kppkn.gtb create mode 100644 test/unittests/comp-testdata/lcet10.txt create mode 100644 test/unittests/comp-testdata/mapreduce-osdi-1.pdf create mode 100644 test/unittests/comp-testdata/plrabn12.txt create mode 100644 test/unittests/comp-testdata/ptt5 create mode 100644 test/unittests/comp-testdata/sum create mode 100644 test/unittests/comp-testdata/urls.10K create mode 100644 test/unittests/comp-testdata/xargs.1 create mode 100644 test/unittests/core_tests.cpp create mode 100644 test/unittests/test_b64.cpp create mode 100644 test/unittests/test_common.h create mode 100644 test/unittests/test_comp.cpp create mode 100644 test/unittests/test_cpu_time.cpp create mode 100644 test/unittests/test_log.cpp create mode 100644 test/unittests/test_route_emulation.cpp create mode 100644 test/unittests/test_sitnl.cpp create mode 100644 test/unittests/unittests.vcxproj create mode 100644 test/unittests/unittests.vcxproj.filters create mode 100644 test/unused create mode 100644 vars/o3 create mode 100644 vars/setlibpath create mode 100644 vars/setpath create mode 100644 vars/vars-android-a7a create mode 100644 vars/vars-android-a7a-dbg create mode 100644 vars/vars-android-a8a create mode 100644 vars/vars-android-a8a-dbg create mode 100644 vars/vars-android-srconly create mode 100644 vars/vars-android-x86 create mode 100644 vars/vars-arm-cross create mode 100644 vars/vars-ios create mode 100644 vars/vars-ios-dbg create mode 100644 vars/vars-iossim create mode 100644 vars/vars-iossim-dbg create mode 100644 vars/vars-linux create mode 100644 vars/vars-linux-dbg create mode 100644 vars/vars-osx create mode 100644 vars/vars-osx-dbg create mode 100644 vars/vars-osx64 create mode 100644 vars/vars-osx64-dbg create mode 100644 vars/vars-reset create mode 100644 vars/vars-win create mode 100644 win/.gitignore create mode 100644 win/build.py create mode 100644 win/buildep.py create mode 100644 win/ovpn3-core.sln create mode 100644 win/ovpn3-core.vcxproj create mode 100644 win/ovpn3-core.vcxproj.filters create mode 100644 win/unused/buildep.py create mode 100644 win/utils.py create mode 100644 win/vcvarsall.patch diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4a2d375 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +README.html +x64 +*.vcxproj.user +*.ipch diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6b44bdb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,58 @@ +dist: bionic +os: linux +language: cpp + +env: + global: + - secure: "dqiLqbzug/xs6F4Q9ei1pGpNf9Q6H3+iKN1W+P0TtODbCXPr/mLWdvHGVMIMqr7H7rBrIUPFPrfqd80nu3jQuQonjcHK/XyJJfmf5hUdhGAszSaixhWnGfVmn/VSV7/5+9DGAU3l9S6YZg4lvi12+cOrlblNgx8GeI5VdN/6HBSHkEqKNI56qn3Y+ugSdLeL1opmzlY58vRsCCmpBH8Ronn4tmSyi85/WZXfF43o9FGGJcygdh6QVWA1CDdNMeLTCt9ld+oToUIiFLiUrhfS1JpSvzysz2xsuEntxZaTMDYPyL4+O8Mj/scl6ejLLXzxTNa7AZOgySLBahf+F4b+yhL1deSVuu40MfxPW6XiM1jKy3KPH/GlYgM8CZQ3D1hQIq1CIUg8DgnTa06RUzevsR5DqDvz+EcPanFHE7dHGrPy9Rs/0y59dNHp3qWKjWMoSA06GerbF61XFOb4mcE29053kV8uxqIa5ZShZ/ndoLeVpQ4mZ+/XSkUybysVl0gWrKnnNNEPtqrdmKf+jlmKY0jyRPdwf425Ldn+wcbGw9ZEnkosYzqAhDBDX4OETAKLi8G0FEYECKKQcd1OX+HNvsOIyOAoLOj7H30F8UkPsjR3ysdIEmc6702ly06gDYjWmwQaCigL/1ktRKgf7ePB0HS+8fOa5SML7619kQrGrWA=" + - PREFIX="${HOME}/opt" + - ASIO_VERSION="90f32660cd503494b3707840cfbd5434d8e9dabe" + - LZ4_VERSION="1.8.3" + - MBEDTLS_VERSION="2.7.5" + - MBEDTLS_CFLAGS="-I${PREFIX}/include" + - MBEDTLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto" + - OPENSSL_VERSION="1.0.2s" + - OPENSSL_CFLAGS="-I${PREFIX}/include" + - OPENSSL_LIBS="-lssl -lcrypto" + - COVERITY_BRANCH="master" + +matrix: + include: + - env: SSLLIB="openssl" + os: osx + osx_image: xcode10.2 + compiler: clang + - env: SSLLIB="mbedtls" + os: osx + osx_image: xcode10.2 + compiler: clang + - env: SSLLIB="openssl" RUN_COVERITY_SCAN="1" + os: linux + compiler: gcc + - env: SSLLIB="openssl" + os: linux + compiler: clang + - env: SSLLIB="mbedtls" + os: linux + compiler: gcc + - env: SSLLIB="mbedtls" + os: linux + compiler: clang + +addons: + apt: + packages: + - libboost-all-dev + - linux-libc-dev + +cache: + ccache: true + directories: + - download-cache + - ${HOME}/opt + +install: + - .travis/build-deps.sh + +script: + - .travis/build-check.sh diff --git a/.travis/build-check.sh b/.travis/build-check.sh new file mode 100755 index 0000000..5c8f2fa --- /dev/null +++ b/.travis/build-check.sh @@ -0,0 +1,75 @@ +#!/bin/sh +set -eux + +PREFIX="${PREFIX:-${HOME}/opt}" +RUN_COVERITY_SCAN="${RUN_COVERITY_SCAN:-0}" + +if [ "${TRAVIS_OS_NAME}" = "linux" ]; then + export LD_LIBRARY_PATH="${PREFIX}/lib:${LD_LIBRARY_PATH:-}" +fi + +if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + export DYLD_LIBRARY_PATH="${PREFIX}/lib:${DYLD_LIBRARY_PATH:-}" +fi + + +if [ "${SSLLIB}" = "openssl" ]; then + SSL_LIBS="${OPENSSL_LIBS}" + SSL_CFLAGS="-DUSE_OPENSSL" +elif [ "${SSLLIB}" = "mbedtls" ]; then + SSL_LIBS="${MBEDTLS_LIBS}" + SSL_CFLAGS="-DUSE_MBEDTLS" +else + echo "Invalid crypto lib: ${SSLLIB}" + exit 1 +fi + +LIBS="${SSL_LIBS} -llz4" +CXXFLAGS="-O3 -std=c++14 -Wall -pthread \ + -DOPENVPN_SHOW_SESSION_TOKEN -DHAVE_LZ4 \ + -DUSE_ASIO -DASIO_STANDALONE -DASIO_NO_DEPRECATED ${SSL_CFLAGS}" + +if [ "${CC}" = "gcc" ]; then + CXXFLAGS="${CXXFLAGS} -fwhole-program -flto=4" +fi + +INCLUDEDIRS="-I../../asio/asio/include -I${PREFIX}/include -I../../" +LDFLAGS="-L${PREFIX}/lib" + +if [ "${TRAVIS_OS_NAME}" = "linux" ]; then + LDFLAGS="${LDFLAGS} -Wl,--no-as-needed" +fi + +if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + CXXFLAGS="${CXXFLAGS} -stdlib=libc++ -arch x86_64" + LIBS="${LIBS} -framework Security \ + -framework CoreFoundation \ + -framework SystemConfiguration \ + -framework IOKit \ + -framework ApplicationServices" +fi + +( + cd test/ovpncli + ${CXX} ${CXXFLAGS} ${INCLUDEDIRS} ${LDFLAGS} cli.cpp -o cli ${LIBS} +) + +( + cd test/ssl + ${CXX} ${CXXFLAGS} -DNOERR ${INCLUDEDIRS} ${LDFLAGS} proto.cpp -o proto ${LIBS} + ./proto +) + +if [ "${RUN_COVERITY_SCAN}" = "1" -a "${TRAVIS_BRANCH}" = "${COVERITY_BRANCH}" ]; then + unset LD_LIBRARY_PATH #don't mess up SSL for curl/wget + + export COVERITY_SCAN_PROJECT_NAME="OpenVPN/openvpn3" + export COVERITY_SCAN_BRANCH_PATTERN="${COVERITY_BRANCH}" + export COVERITY_SCAN_NOTIFICATION_EMAIL="scan-reports@openvpn.net" + export COVERITY_SCAN_BUILD_COMMAND_PREPEND="cd test/ssl" + export COVERITY_SCAN_BUILD_COMMAND="${CXX} ${CXXFLAGS} ${INCLUDEDIRS} \ + ${LDFLAGS} proto.cpp -o proto ${LIBS}" + + # Ignore exit code, script exits with 1 if we're not on the right branch + curl -s "https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh" | bash || true +fi diff --git a/.travis/build-deps.sh b/.travis/build-deps.sh new file mode 100755 index 0000000..184dd4c --- /dev/null +++ b/.travis/build-deps.sh @@ -0,0 +1,133 @@ +#!/bin/sh +set -eux + +# Set defaults +PREFIX="${PREFIX:-${HOME}/opt}" + +download_asio () { + if [ ! -d "download-cache/asio" ]; then + git clone https://github.com/chriskohlhoff/asio.git \ + download-cache/asio + else + ( + cd download-cache/asio + if [ "$(git log -1 --format=%H)" != "${ASIO_VERSION}" ]; then + git checkout master + git pull + git checkout ${ASIO_VERSION} + fi + ) + fi +} + +build_asio () { + ( + if [ ! -L asio ]; then + rm -Rf asio + ln -s download-cache/asio asio + fi + ) +} + +download_lz4 () { + if [ ! -f "download-cache/lz4-${LZ4_VERSION}.tar.gz" ]; then + wget "https://github.com/lz4/lz4/archive/v${LZ4_VERSION}.tar.gz" \ + -O download-cache/lz4-${LZ4_VERSION}.tar.gz + fi +} + +build_lz4 () { + if [ "$(cat ${PREFIX}/.lz4-version)" != "${LZ4_VERSION}" ]; then + tar zxf download-cache/lz4-${LZ4_VERSION}.tar.gz + ( + cd "lz4-${LZ4_VERSION}" + make default CC=$CC CXX=$CXX + make install PREFIX="${PREFIX}" + ) + echo "${LZ4_VERSION}" > "${PREFIX}/.lz4-version" + fi +} + +download_mbedtls () { + if [ ! -f "download-cache/mbedtls-${MBEDTLS_VERSION}-apache.tgz" ]; then + wget -P download-cache/ \ + "https://tls.mbed.org/download/mbedtls-${MBEDTLS_VERSION}-apache.tgz" + fi +} + +build_mbedtls () { + if [ "$(cat ${PREFIX}/.mbedtls-version)" != "${MBEDTLS_VERSION}" ]; then + tar zxf download-cache/mbedtls-${MBEDTLS_VERSION}-apache.tgz + ( + cd "mbedtls-${MBEDTLS_VERSION}" + make CC=$CC CXX=$CXX + make install DESTDIR="${PREFIX}" + ) + echo "${MBEDTLS_VERSION}" > "${PREFIX}/.mbedtls-version" + fi +} + +download_openssl () { + if [ ! -f "download-cache/openssl-${OPENSSL_VERSION}.tar.gz" ]; then + wget -P download-cache/ \ + "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz" + fi +} + +build_openssl_linux () { + ( + cd "openssl-${OPENSSL_VERSION}/" + ./config shared --prefix="${PREFIX}" --openssldir="${PREFIX}" -DPURIFY + make all install_sw + ) +} + +build_openssl_osx () { + ( + cd "openssl-${OPENSSL_VERSION}/" + ./Configure darwin64-x86_64-cc shared \ + --prefix="${PREFIX}" --openssldir="${PREFIX}" -DPURIFY + make depend all install_sw + ) +} + +build_openssl () { + if [ "$(cat ${PREFIX}/.openssl-version)" != "${OPENSSL_VERSION}" ]; then + tar zxf "download-cache/openssl-${OPENSSL_VERSION}.tar.gz" + if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + build_openssl_osx + elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then + build_openssl_linux + fi + echo "${OPENSSL_VERSION}" > "${PREFIX}/.openssl-version" + fi +} + +# Enable ccache +if [ "${TRAVIS_OS_NAME}" != "osx" ] && [ -z ${CHOST+x} ]; then + # ccache not available on osx, see: + # https://github.com/travis-ci/travis-ci/issues/5567 + # also ccache not enabled for cross builds + mkdir -p "${HOME}/bin" + ln -s "$(which ccache)" "${HOME}/bin/${CXX}" + ln -s "$(which ccache)" "${HOME}/bin/${CC}" + PATH="${HOME}/bin:${PATH}" +fi + +# Download and build crypto lib +if [ "${SSLLIB}" = "openssl" ]; then + download_openssl + build_openssl +elif [ "${SSLLIB}" = "mbedtls" ]; then + download_mbedtls + build_mbedtls +else + echo "Invalid crypto lib: ${SSLLIB}" + exit 1 +fi + +download_asio +build_asio + +download_lz4 +build_lz4 diff --git a/CLA.rst b/CLA.rst new file mode 100644 index 0000000..594c636 --- /dev/null +++ b/CLA.rst @@ -0,0 +1,63 @@ +Contributor agreement for the OpenVPN project version 1.3 - December 2017 +######################################################################### + +This Contributor Agreement consists of two parts. Part I is the +Developer Certificate of Origin available at +http://developercertificate.org/. + +In this contributor agreement, "This project" refers to the OpenVPN +project and +"open source license indicated in `the file `_" refers to +the AGPLv3 license with an additional permission that allows linking +the OpenSSL software, https://www.openssl.org/, with the OpenVPN +software. + +Part I +###### + +Developer Certificate of Origin Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 1 +Letterman Drive Suite D4700 San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I have +the right to submit it under the open source license indicated in the +file; or + +(b) The contribution is based upon previous work that, to the best of +my knowledge, is covered under an appropriate open source license and +I have the right under that license to submit that work with +modifications, whether created in whole or in part by me, under the +same open source license (unless I am permitted to submit under a +different license), as indicated in the file; or + +(c) The contribution was provided directly to me by some other person +who certified (a), (b) or (c) and I have not modified it. + +(d) I understand and agree that this project and the contribution are +public and that a record of the contribution (including all personal +information I submit with it, including my sign-off) is maintained +indefinitely and may be redistributed consistent with this project or +the open source license(s) involved. + +Part II +####### + +Copyright (C) 2017 OpenVPN Inc. + +In addition: + +(e) I understand that OpenVPN Inc. may relicense this project, this +contribution, and any modification to it under any license. I certify that I, +or the person on whose behalf I am submitting the contribution, have the +right to grant and hereby grant OpenVPN Inc. a license to do so for this +contribution. My grant is made on the condition that OpenVPN Inc. will make +any modification to this contribution available to the OpenVPN project under +the open source license indicated in the file. diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7c6bf76 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +# Cmake in OpenVPN3 core is mainly used to get Clion editior support and to run unit tests. For normal +# Build instructions see the README.rst + +cmake_minimum_required(VERSION 3.5) + +add_subdirectory(test/unittests) +add_subdirectory(test/ovpncli) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..48213fd --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,7 @@ +Contributing to OpenVPN 3 +========================= + +Patches can be sent as GitHub pull requests. + +Note that by contributing to the OpenVPN 3 project you accept the Contributor +License Agreement described in `CLA.rst `_. diff --git a/COPYRIGHT.AGPLV3 b/COPYRIGHT.AGPLV3 new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/COPYRIGHT.AGPLV3 @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/LICENSE.rst b/LICENSE.rst new file mode 100644 index 0000000..8bf238b --- /dev/null +++ b/LICENSE.rst @@ -0,0 +1,15 @@ +OpenVPN 3 is distributed under +`GNU Affero General Public License version 3 `_ +with a special permission to link against OpenSSL: + +:: + + Additional permission under GNU AGPL version 3 section 7 + + If you modify this Program, or any covered work, by linking or combining + it with OpenSSL (or a modified version of that library), containing parts + covered by the terms of the OpenSSL License or the Original SSLeay License, + the licensors of this Program grant you additional permission to convey the + resulting work. Corresponding Source for a non-source form of such a + combination shall include the source code for the parts of OpenSSL used as + well as that of the covered work. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..550b0d4 --- /dev/null +++ b/README.rst @@ -0,0 +1,617 @@ +OpenVPN 3 +========= + +OpenVPN 3 is a C++ class library that implements the functionality +of an OpenVPN client, and is protocol-compatible with the OpenVPN +2.x branch. + +OpenVPN 3 includes a minimal client wrapper (``cli``) that links in with +the library and provides basic command line functionality. + +OpenVPN 3 is currently used in production as the core of the +OpenVPN Connect clients for iOS, Android, Linux, Windows, and Mac OS X. + +NOTE: As of 2017, OpenVPN 3 is primarily of interest to developers, +as it does not yet replicate the full functionality of OpenVPN 2.x. +In particular, server functionality is not yet implemented. + +.. contents:: Table of Contents + +OpenVPN 3 Client API +-------------------- + +OpenVPN 3 is organized as a C++ class library, and the API is defined in +``_. + +A simple command-line wrapper for the API is provided in +``_. + +Building the OpenVPN 3 client on Linux +-------------------------------------- + +These instructions were tested on Ubuntu 16. + +Get prerequisites to allow for either mbedTLS or OpenSSL linkage:: + + $ sudo apt-get install g++ make libmbedtls-dev libssl-dev liblz4-dev + +Get Asio C++ library:: + + $ cd ~ + $ git clone https://github.com/chriskohlhoff/asio.git + +Set environmental variable used by OpenVPN 3 build scripts:: + + $ export O3=~/ovpn3 + +Clone the OpenVPN 3 source repo:: + + $ mkdir ~/ovpn3 + $ cd ~/ovpn3 + $ git clone https://github.com/OpenVPN/openvpn3.git core + +Build the OpenVPN 3 client wrapper (cli) with mbedTLS crypto/ssl library +and LZ4 compression:: + + $ cd $O3/core/test/ovpncli + $ ECHO=1 PROF=linux ASIO_DIR=~/asio MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli + +Or alternatively build with OpenSSL:: + + $ cd $O3/core/test/ovpncli + $ ECHO=1 PROF=linux ASIO_DIR=~/asio OPENSSL_SYS=1 LZ4_SYS=1 $O3/core/scripts/build cli + +Run OpenVPN 3 client:: + + $ sudo ./cli -a -c yes myprofile.ovpn route-nopull + +Options used:: + + -a : use autologin sessions, if supported + -c yes : negotiate LZ4 compression + myprofile.ovpn : OpenVPN config file (must have .ovpn extension) + route-nopull : if you are connected via ssh, prevent ssh session lockout + + +Building the OpenVPN 3 client on Mac OS X +----------------------------------------- + +OpenVPN 3 should be built in a non-root Mac OS X account. +Make sure that Xcode is installed with optional command-line tools. +(These instructions have been tested with Xcode 5.1.1). + +Create the directories ``~/src`` and ``~/src/mac``:: + + $ mkdir -p ~/src/mac + +Clone the OpenVPN 3 repo:: + + $ cd ~/src + $ mkdir ovpn3 + $ cd ovpn3 + $ git clone https://github.com/OpenVPN/openvpn3.git core + +Export the shell variable ``O3`` to point to the OpenVPN 3 top level +directory:: + + export O3=~/src/ovpn3 + +Download source tarballs (``.tar.gz`` or ``.tgz``) for these dependency +libraries into ``~/Downloads`` + +See the file ``$O3/core/deps/lib-versions`` for the expected +version numbers of each dependency. If you want to use a different +version of the library than listed here, you can edit this file. + +1. Asio — https://github.com/chriskohlhoff/asio +2. mbed TLS (2.3.0 or higher) — https://tls.mbed.org/ +3. LZ4 — https://github.com/Cyan4973/lz4 + +For dependencies that are typically cloned from github vs. +provided as a .tar.gz file, tools are provided to convert +the github to a .tar.gz file. See "snapshot" scripts under +``$O3/core/deps`` + +Note that while OpenSSL is listed in lib-versions, it is +not required for Mac builds. + +Build the dependencies:: + + $ DL=~/Downloads + $ OSX_ONLY=1 $O3/core/scripts/mac/build-all + +Now build the OpenVPN 3 client executable:: + + $ cd $O3/core + $ . vars/vars-osx64 + $ . vars/setpath + $ cd test/ovpncli + $ MTLS=1 LZ4=1 ASIO=1 build cli + +This will build the OpenVPN 3 client library with a small client +wrapper (``cli``). It will also statically link in all external +dependencies (Asio, mbedTLS, and LZ4), so ``cli`` may be distributed +to other Macs and will run as a standalone executable. + +These build scripts will create a **x86_x64** Mac OS X executable, +with a minimum deployment target of 10.8.x. The Mac OS X tuntap driver is not +required, as OpenVPN 3 can use the integrated utun interface if +available. + +To view the client wrapper options:: + + $ ./cli -h + +To connect:: + + $ ./cli client.ovpn + + +Building the OpenVPN 3 client on Windows +---------------------------------------- + +Prerequisites: + +* Visual Studio 2017 +* Python 2.7 +* Perl (for building openssl) + +Clone the OpenVPN 3 source repo:: + + > c:\Temp>mkdir O3 + > c:\Temp>cd O3 + > c:\Temp\O3>git clone https://github.com/OpenVPN/openvpn3.git core + +Add environment variable ``O3`` with value ``c:\Temp\O3`` and reopen commmand prompt. + +Download and build dependencies:: + + > c:\Temp\O3>cd core\win + > c:\Temp\O3\core\win>set STATIC=1&& set DEBUG=1&& python buildep.py + +Now you can open project in Visual Studio. Project and solution files are +located in ``O3\core\win`` directory. + +You can also build the test client from command prompt:: + + > c:\Temp\O3\core\win>set STATIC=1&& set DEBUG=1&& python build.py + +Testing +------- + +The OpenVPN 3 core includes a stress/performance test of +the OpenVPN protocol implementation. The test basically +creates a virtualized lossy network between two OpenVPN +protocol objects, triggers TLS negotiations between them, +passes control/data channel messages, and measures the ability +of the OpenVPN protocol objects to perform and remain in +a valid state. + +The OpenVPN protocol implementation that is being tested +is here: ``_ + +The test code itself is here: ``_ + +Build the test:: + + $ cd ovpn3/core/test/ssl + $ ECHO=1 PROF=linux ASIO_DIR=~/asio MTLS_SYS=1 NOSSL=1 $O3/core/scripts/build proto + +Run the test:: + + $ time ./proto + *** app bytes=72777936 net_bytes=122972447 data_bytes=415892854 prog=0000216599/0000216598 D=12700/600/12700/600 N=109/109 SH=17400/15300 HE=0/0 + + real 0m15.813s + user 0m15.800s + sys 0m0.004s + +The OpenVPN 3 core also includes unit tests, which are based on +Google Test framework. To run unit tests, you need to install +CMake and build Google Test. + +Building Google Test on Linux:: + + $ git clone https://github.com/google/googletest.git + $ cd googletest + $ cmake . && cmake --build . + +Building Google Test on Windows:: + + > git clone https://github.com/google/googletest.git + > cd googletest + > cmake -G "Visual Studio 14 2015 Win64" . + > cmake --build . + +After Google Test is built you are ready to build and run unit tests. + +Build and run tests on Linux:: + + $ cd ovpn3/core/test/unittests + $ GTEST_DIR=~/googletest ECHO=1 PROF=linux ASIO_DIR=~/asio MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build test_log + $ ./test_log + +Build and run tests on Windows:: + + $ cd ovpn3/core/win + $ python build.py ../test/unittests/test_log.cpp unittest + $ test_log.exe + +Developer Guide +--------------- + +OpenVPN 3 is written in C++11 and developers who are moving +from C to C++ should take some time to familiarize themselves with +key C++ design patterns such as *RAII*: + +https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization + +OpenVPN 3 Client Core ++++++++++++++++++++++ + +OpenVPN 3 is designed as a class library, with an API that +is essentially defined inside of namespace ``ClientAPI`` +with headers and implementation in ``_ and +header-only library files under ``_. + +The consise definition of the client API is essentially ``class OpenVPNClient`` +in ``_ with several imporant extensions to +the API found in: + +* **class TunBuilderBase** in ``_ — + Provides an abstraction layer defining the *tun* interface, + and is especially useful for interfacing with an OS-layer VPN API. + +* **class ExternalPKIBase** in ``_ — + Provides a callback for external private key operations, and + is useful for interfacing with an OS-layer Keychain such as + the Keychain on iOS, Mac OS X, and Android, and the Crypto API + on Windows. + +* **class LogReceiver** in ``_ — + Provides an abstraction layer for the delivery of logging messages. + +OpenVPN 3 includes a command-line reference client (``cli``) for +testing the API. See ``_. + +The basic approach to building an OpenVPN 3 client is +to define a client class that derives from +``ClientAPI::OpenVPNClient``, then provide implementations +for callbacks including event and logging notifications: + +.. code:: c++ + + class Client : public ClientAPI::OpenVPNClient + { + public: + virtual void event(const Event&) override { // events delivered here + ... + } + virtual void log(const LogInfo&) override { // logging delivered here + ... + } + + ... + }; + +To start the client, first create a ``ClientAPI::Config`` object +and initialize it with the OpenVPN config file and other options: + +.. code:: c++ + + ClientAPI::Config config; + config.content = ; + ... + +Next, create a client object and evaluate the configuration: + +.. code:: c++ + + Client client; + ClientAPI::EvalConfig eval = client.eval_config(config); + if (eval.error) + throw ...; + +Finally, in a new worker thread, start the connection: + +.. code:: c++ + + ClientAPI::Status connect_status = client.connect(); + +Note that ``client.connect()`` will not return until +the session has terminated. + +Top Layer +......... + +The top layer of the OpenVPN 3 client is implemented +in ``_ and ``_. +Most of what this code does is marshalling the configuration and +dispatching the higher-level objects that implement the OpenVPN +client session. + +Connection +.......... + +``class ClientConnect`` in ``_ +implements the top-level connection logic for an OpenVPN client +connection. It is concerned with starting, stopping, pausing, and resuming +OpenVPN client connections. It deals with retrying a connection and handles +the connection timeout. It also deals with connection exceptions and understands +the difference between an exception that should halt any further reconnection +attempts (such as ``AUTH_FAILED``), and other exceptions such as network errors +that would justify a retry. + +Some of the methods in the class +(such as ``stop``, ``pause``, and ``reconnect``) are often +called by another thread that is controlling the connection, therefore +thread-safe methods are provided where the thread-safe function posts a message +to the actual connection thread. + +In an OpenVPN client connection, the following object stack would be used: + +1. **class ClientConnect** in ``_ — + The top-layer object in an OpenVPN client connection. +2. **class ClientProto::Session** in ``_ — + The OpenVPN client protocol object that subinstantiates the transport + and tun layer objects. +3. **class ProtoContext** in ``_ — + The core OpenVPN protocol implementation that is common to both + client and server. +4. **class ProtoStackBase** in ``_ — + The bottom-layer class that implements + the basic functionality of tunneling a protocol over a reliable or + unreliable transport layer, but isn't specific to OpenVPN per-se. + +Transport Layer +............... + +OpenVPN 3 defines abstract base classes for Transport layer +implementations in ``_. + +Currently, transport layer implementations are provided for: + +* **UDP** — ``_ +* **TCP** — ``_ +* **HTTP Proxy** — ``_ + +Tun Layer +......... + +OpenVPN 3 defines abstract base classes for Tun layer +implementations in ``_. + +There are two possible approaches to define a Tun +layer implementation: + +1. Use a VPN API-centric model (such as for Android + or iOS). These models derive from **class TunBuilderBase** + in ``_ + +2. Use an OS-specific model such as: + + * **Linux** — ``_ + * **Windows** — ``_ + * **Mac OS X** — ``_ + +Protocol Layer +.............. + +The OpenVPN protocol is implemented in **class ProtoContext** +in ``_. + +Options Processing +.................. + +The parsing and query of the OpenVPN config file +is implemented by ``class OptionList`` in +``_. + +Note that OpenVPN 3 always assumes an *inline* style of +configuration, where all certs, keys, etc. are +defined inline rather than through an external file +reference. + +For config files that do use external file references, +``class ProfileMerge`` in ``_ +is provided to merge those external +file references into an inline form. + +Calling the Client API from other languages +........................................... + +The OpenVPN 3 client API, as defined by ``class OpenVPNClient`` +in ``_, can be wrapped by the +Swig_ tool to create bindings for other languages. + +.. _Swig: http://www.swig.org/ + +For example, OpenVPN Connect for Android creates a Java +binding of the API using ``_. + +Security +++++++++ + +When developing security software in C++, it's very important to +take advantage of the language and OpenVPN library code +to insulate code from the kinds of +bugs that can introduce security vulnerabilities. + +Here is a brief set of guidelines: + +* When dealing with strings, use a ``std::string`` + rather than a ``char *``. + +* When dealing with binary data or buffers, always try to use a ``Buffer``, + ``ConstBuffer``, ``BufferAllocated``, or ``BufferPtr`` object to + provide managed access to the buffer, to protect against security + bugs that arise when using raw buffer pointers. + See ``_ for the OpenVPN ``Buffer`` classes. + +* When it's necessary to have a pointer to an object, use + ``std::unique_ptr<>`` for non-shared objects and reference-counted + smart pointers for shared objects. For shared-pointers, + OpenVPN code should use the smart pointer classes defined + in ``_. Please see the comments in + this file for documentation. + +* Never use ``malloc`` or ``free``. When allocating objects, + use the C++ ``new`` operator and then immediately construct + a smart pointer to reference the object: + + .. code:: c++ + + std::unique_ptr ptr = new MyObject(); + ptr->method(); + +* When interfacing with C functions that deal with + raw pointers, memory allocation, etc., consider wrapping + the functionality in C++. For an example, see ``enum_dir()`` + in ``_, + a function that returns a list of files in + a directory (Unix only) via a high-level + string vector, while internally calling + the low level libc methods + ``opendir``, ``readdir``, and ``closedir``. + Notice how ``unique_ptr_del`` is used to wrap the + ``DIR`` struct in a smart pointer with a custom + deletion function. + +* When grabbing random entropy that is to be used + for cryptographic purposes (i.e. for keys, tokens, etc.), + always ensure that the RNG is crypto-grade by calling + ``assert_crypto()`` on the RNG. This will throw + an exception if the RNG is not crypto-grade: + + .. code:: c++ + + void set_rng(RandomAPI::Ptr rng_arg) { + rng_arg->assert_crypto(); + rng = std::move(rng_arg); + } + +* Any variable whose value is not expected to change should + be declared ``const``. + +* Don't use non-const global or static variables unless absolutely + necessary. + +* When formatting strings, don't use ``snprintf``. Instead, use + ``std::ostringstream`` or build the string using the '+' ``std::string`` + operator: + + .. code:: c++ + + std::string format_reconnecting(const int n_seconds) { + return "Reconnecting in " + openvpn::to_string(n_seconds) + " seconds."; + } + + or: + + .. code:: c++ + + std::string format_reconnecting(const int n_seconds) { + std::ostringstream os; + os << "Reconnecting in " << n_seconds << " seconds."; + return os.str(); + } + +* OpenVPN 3 is a "header-only" library, therefore all free functions + outside of classes should have the ``inline`` attribute. + +Conventions ++++++++++++ + +* Use the **Asio** library for I/O and timers. + Don't deal with sockets directly. + +* Never block. If you need to wait for something, use **Asio** timers + or sockets. + +* Use the ``OPENVPN_LOG()`` macro to log stuff. Don't use ``printf``. + +* Don't call crypto/ssl libraries directly. Instead use the abstraction + layers (``_ and ``_) that allow OpenVPN + to link with different crypto/ssl libraries (such as **OpenSSL** + or **mbed TLS**). + +* Use ``RandomAPI`` as a wrapper for random number + generators (``_). + +* If you need to deal with configuration file options, + see ``class OptionList`` in ``_. + +* If you need to deal with time or time durations, use the + classes under ``_. + +* If you need to deal with IP addresses, see the comprehensive classes + under ``_. + +* In general, if you need a general-purpose library class or function, + look under ``_. Chances are good that it's already + been implemented. + +* The OpenVPN 3 approach to errors is to count them, rather than + unconditionally log them. If you need to add a new error + counter, see ``_. + +* If you need to create a new event type which can be transmitted + as a notification back to the client API user, see + ``_. + +* Raw pointers or references can be okay when used by an object to + point back to its parent (or container), if you can guarantee that + the object will not outlive its parent. Backreferences to a parent + object is also a common use case for weak pointers. + +* Use C++ exceptions for error handling and as an alternative + to ``goto``. See OpenVPN's general exception classes + and macros in ``_. + +* Use C++ destructors for automatic object cleanup, and so + that thrown exceptions will not leak objects. Alternatively, + use ``Cleanup`` in ``_ when + you need to specify a code block to execute prior to scope + exit. For example, ensure that the file ``pid_fn`` is + deleted before scope exit: + + .. code:: c++ + + auto clean = Cleanup([pid_fn]() { + if (pid_fn) + ::unlink(pid_fn); + }); + +* When calling global methods (such as libc ``fork``), + prepend "::" to the symbol name, e.g.: + + .. code:: c++ + + struct dirent *e; + while ((e = ::readdir(dir.get())) != nullptr) { + ... + } + +* Use ``nullptr`` instead of ``NULL``. + +Threading ++++++++++ + +The OpenVPN 3 client core is designed to run in a single thread, with +the UI or controller driving the OpenVPN API running in a different +thread. + +It's almost never necessary to create additional threads within +the OpenVPN 3 client core. + + +Contributing +------------ + +See ``_. + +License +------- + +See ``_. + \ No newline at end of file diff --git a/VersionNumbering.rst b/VersionNumbering.rst new file mode 100644 index 0000000..0d32e58 --- /dev/null +++ b/VersionNumbering.rst @@ -0,0 +1,63 @@ +OpenVPN 3 version numbering and release process +=============================================== + +OpenVPN 3 version numbers will always be prefixed with ``3.`` which +indicates the OpenVPN generation. This library is the third +generation of the OpenVPN protocol implementation. + +As of OpenVPN 3.2, we will use a single positive integer indicating a +release number as the version reference. + + +Git branches and versioning +--------------------------- +Main development will happen on the git master branch. This will not +contain any specific version. It is will be set to ``3.git:master``. +This branch will contain both stable and unstable code, which will be +bleeding edge at any time. Do not depend on git master for production code. + +Once features and fixes in git master has stabilized, they will be +merged into the ``stable`` branch. Code extracted from the stable branch +will contain the release number of the last release. The stable +branch is suitable for production code. + +It is not set up a specific plan for when releases will occur. We +might want to collect up a smaller set of features before defining it +ready as a release, depending on the size of the changes. At the +release time, the version string will be updated and tagged (with +a PGP signature). + +We should not pile up too many features for each release. It is +better to release often with smaller changesets. + + +Hot-fixes +--------- + +We will not do any patch number releases unless strictly needed for +older releases numbers. Such releases will be called hot-fixes and +will be handled in separate branches only when needed. These branches +will be named ``hotfix/3.X``; where X denotes the release number the +hotfix targets. Hotfixes need to update the version string as well +as attaching a git tag with the proper version number. + +**Hot-fixes should be avoided as much as possible** and we should +**encourage users to base their work on the stable branch** primarily. +Hot-fixes will only be used for highly critical issues which cannot +wait for a release or the feature gap to move to a newer release is +considered too big. But it should also only occur for releases which +are still relevant. + + +Examples +-------- + +git ``master`` branch: version string will be ``3.git:master`` + +git ``stable`` branch: version string will be ``3.2``, ``3.3``, etc + +hotfix for v3.2 will be in ``hotfix/3.2`` and the version string will be +``3.2.1`` + +Similarly, hotfix for v3.3 will be found in ``hotfix/3.3`` and the version +string will be ``3.3.1``. diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..06884d1 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,32 @@ +version: 1.0.{build} + +image: Visual Studio 2019 + +clone_folder: c:\ovpn3\core + +install: +- pip install rfc6266 requests +- if not exist "C:\strawberry" choco install strawberryperl -y +- set PATH=C:\strawberry\c\bin;C:\strawberry\perl\site\bin;C:\strawberry\perl\bin;%PATH% + +environment: + MSVC_DIR: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community + O3: C:\ovpn3 + STATIC: 1 + +before_build: +- cmd: cd win && python buildep.py + +after_build: +- cmd: copy c:\ovpn3\deps\amd64\openssl\out32dll\ssleay32.dll c:\ovpn3\core\win\x64\ReleaseOpenSSL\ +- cmd: copy c:\ovpn3\deps\amd64\openssl\out32dll\libeay32.dll c:\ovpn3\core\win\x64\ReleaseOpenSSL\ + +platform: x64 + +configuration: ReleaseOpenSSL + +artifacts: + - path: win\x64\ReleaseOpenSSL\cli.exe + - path: win\x64\ReleaseOpenSSL\*.dll + + diff --git a/client/ovpncli.cpp b/client/ovpncli.cpp new file mode 100644 index 0000000..6d23519 --- /dev/null +++ b/client/ovpncli.cpp @@ -0,0 +1,1420 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Implementation file for OpenVPNClient API defined in ovpncli.hpp. + +#include +#include +#include +#include +#include + +#include + +// Set up export of our public interface unless +// OPENVPN_CORE_API_VISIBILITY_HIDDEN is defined +#if defined(__GNUC__) +#define OPENVPN_CLIENT_EXPORT +#ifndef OPENVPN_CORE_API_VISIBILITY_HIDDEN +#pragma GCC visibility push(default) +#endif +#include "ovpncli.hpp" // public interface +#ifndef OPENVPN_CORE_API_VISIBILITY_HIDDEN +#pragma GCC visibility pop +#endif +#else +// no public interface export defined for this compiler +#define OPENVPN_CLIENT_EXPORT +#include "ovpncli.hpp" // public interface +#endif + +// debug settings (production setting in parentheses) + +//#define OPENVPN_DUMP_CONFIG // dump parsed configuration (comment out) +//#define OPENVPN_DEBUG_CLIPROTO // shows packets in/out (comment out) +#define OPENVPN_DEBUG_PROTO 1 // increases low-level protocol verbosity (1) +//#define OPENVPN_DEBUG_PROTO_DUMP // dump hex of transport-layer packets, requires OPENVPN_DEBUG_CLIPROTO (comment out) +//#define OPENVPN_DEBUG_VERBOSE_ERRORS // verbosely log Error::Type errors (comment out) +#define OPENVPN_DEBUG_TUN 2 // debug level for tun object (2) +#define OPENVPN_DEBUG_UDPLINK 2 // debug level for UDP link object (2) +#define OPENVPN_DEBUG_TCPLINK 2 // debug level for TCP link object (2) +#define OPENVPN_DEBUG_COMPRESS 1 // debug level for compression objects (1) +#define OPENVPN_DEBUG_REMOTELIST 0 // debug level for RemoteList object (0) +#define OPENVPN_DEBUG_TUN_BUILDER 0 // debug level for tun/builder/client.hpp (0) +//#define OPENVPN_SHOW_SESSION_TOKEN // show server-pushed auth-token (comment out) +//#define OPENVPN_DEBUG_TAPWIN // shows Windows TAP driver debug logging (comment out) + +// enable assertion checks (can safely be disabled in production) +//#define OPENVPN_ENABLE_ASSERT + +// force null tun device (useful for testing) +//#define OPENVPN_FORCE_TUN_NULL + +// log cleartext tunnel packets to file for debugging/analysis +//#define OPENVPN_PACKET_LOG "pkt.log" + +#ifndef OPENVPN_LOG +// log thread settings +#define OPENVPN_LOG_CLASS openvpn::ClientAPI::LogReceiver +#define OPENVPN_LOG_INFO openvpn::ClientAPI::LogInfo +#include // should be included early +#endif + +// log SSL handshake messages +#define OPENVPN_LOG_SSL(x) OPENVPN_LOG(x) + +// on Android and iOS, use TunBuilderBase abstraction +#include +#if (defined(OPENVPN_PLATFORM_ANDROID) || defined(OPENVPN_PLATFORM_IPHONE)) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY) +#define USE_TUN_BUILDER +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// copyright +#include + +namespace openvpn { + namespace ClientAPI { + + OPENVPN_SIMPLE_EXCEPTION(app_expired); + + class MySessionStats : public SessionStats + { + public: + typedef RCPtr Ptr; + + MySessionStats(OpenVPNClient* parent_arg) + : parent(parent_arg) + { + std::memset(errors, 0, sizeof(errors)); +#ifdef OPENVPN_DEBUG_VERBOSE_ERRORS + session_stats_set_verbose(true); +#endif + } + + static size_t combined_n() + { + return N_STATS + Error::N_ERRORS; + } + + static std::string combined_name(const size_t index) + { + if (index < N_STATS + Error::N_ERRORS) + { + if (index < N_STATS) + return stat_name(index); + else + return Error::name(index - N_STATS); + } + else + return ""; + } + + count_t combined_value(const size_t index) const + { + if (index < N_STATS + Error::N_ERRORS) + { + if (index < N_STATS) + return get_stat(index); + else + return errors[index - N_STATS]; + } + else + return 0; + } + + count_t stat_count(const size_t index) const + { + return get_stat_fast(index); + } + + count_t error_count(const size_t index) const + { + return errors[index]; + } + + void detach_from_parent() + { + parent = nullptr; + } + + virtual void error(const size_t err, const std::string* text=nullptr) + { + if (err < Error::N_ERRORS) + { +#ifdef OPENVPN_DEBUG_VERBOSE_ERRORS + if (text) + OPENVPN_LOG("ERROR: " << Error::name(err) << " : " << *text); + else + OPENVPN_LOG("ERROR: " << Error::name(err)); +#endif + ++errors[err]; + } + } + + private: + OpenVPNClient* parent; + count_t errors[Error::N_ERRORS]; + }; + + class MyClientEvents : public ClientEvent::Queue + { + public: + typedef RCPtr Ptr; + + MyClientEvents(OpenVPNClient* parent_arg) : parent(parent_arg) {} + + virtual void add_event(ClientEvent::Base::Ptr event) override + { + if (parent) + { + Event ev; + ev.name = event->name(); + ev.info = event->render(); + ev.error = event->is_error(); + ev.fatal = event->is_fatal(); + + // save connected event + if (event->id() == ClientEvent::CONNECTED) + last_connected = std::move(event); + else if (event->id() == ClientEvent::DISCONNECTED) + parent->on_disconnect(); + parent->event(ev); + } + } + + void get_connection_info(ConnectionInfo& ci) + { + ClientEvent::Base::Ptr connected = last_connected; + if (connected) + { + const ClientEvent::Connected* c = connected->connected_cast(); + if (c) + { + ci.user = c->user; + ci.serverHost = c->server_host; + ci.serverPort = c->server_port; + ci.serverProto = c->server_proto; + ci.serverIp = c->server_ip; + ci.vpnIp4 = c->vpn_ip4; + ci.vpnIp6 = c->vpn_ip6; + ci.gw4 = c->vpn_gw4; + ci.gw6 = c->vpn_gw6; + ci.clientIp = c->client_ip; + ci.tunName = c->tun_name; + ci.defined = true; + return; + } + } + ci.defined = false; + } + + void detach_from_parent() + { + parent = nullptr; + } + + private: + OpenVPNClient* parent; + ClientEvent::Base::Ptr last_connected; + }; + + class MySocketProtect : public SocketProtect + { + public: + MySocketProtect() : parent(nullptr) {} + + void set_parent(OpenVPNClient* parent_arg) + { + parent = parent_arg; + } + + bool socket_protect(int socket, IP::Addr endpoint) override + { + if (parent) + { +#if defined(OPENVPN_COMMAND_AGENT) && defined(OPENVPN_PLATFORM_WIN) + return WinCommandAgent::add_bypass_route(endpoint); +#elif defined(OPENVPN_COMMAND_AGENT) && defined(OPENVPN_PLATFORM_MAC) + return UnixCommandAgent::add_bypass_route(endpoint); +#else + return parent->socket_protect(socket, endpoint.to_string(), endpoint.is_ipv6()); +#endif + } + else + return true; + } + + void detach_from_parent() + { + parent = nullptr; + } + + private: + OpenVPNClient* parent; + }; + + class MyReconnectNotify : public ReconnectNotify + { + public: + MyReconnectNotify() : parent(nullptr) {} + + void set_parent(OpenVPNClient* parent_arg) + { + parent = parent_arg; + } + + void detach_from_parent() + { + parent = nullptr; + } + + virtual bool pause_on_connection_timeout() + { + if (parent) + return parent->pause_on_connection_timeout(); + else + return false; + } + + private: + OpenVPNClient* parent; + }; + + class MyRemoteOverride : public RemoteList::RemoteOverride + { + public: + void set_parent(OpenVPNClient* parent_arg) + { + parent = parent_arg; + } + + void detach_from_parent() + { + parent = nullptr; + } + + virtual RemoteList::Item::Ptr get() override + { + if (parent) + { + const std::string title = "remote-override"; + ClientAPI::RemoteOverride ro; + try { + parent->remote_override(ro); + } + catch (const std::exception& e) + { + ro.error = e.what(); + } + RemoteList::Item::Ptr ri(new RemoteList::Item); + if (ro.error.empty()) + { + if (!ro.ip.empty()) + ri->set_ip_addr(IP::Addr(ro.ip, title)); + if (ro.host.empty()) + ro.host = ro.ip; + HostPort::validate_host(ro.host, title); + HostPort::validate_port(ro.port, title); + ri->server_host = std::move(ro.host); + ri->server_port = std::move(ro.port); + ri->transport_protocol = Protocol::parse(ro.proto, Protocol::CLIENT_SUFFIX, title.c_str()); + } + else + throw Exception("remote override exception: " + ro.error); + return ri; + } + else + return RemoteList::Item::Ptr(); + } + + private: + OpenVPNClient* parent = nullptr; + }; + + class MyClockTick + { + public: + MyClockTick(openvpn_io::io_context& io_context, + OpenVPNClient* parent_arg, + const unsigned int ms) + : timer(io_context), + parent(parent_arg), + period(Time::Duration::milliseconds(ms)) + { + } + + void cancel() + { + timer.cancel(); + } + + void detach_from_parent() + { + parent = nullptr; + } + + void schedule() + { + timer.expires_after(period); + timer.async_wait([this](const openvpn_io::error_code& error) + { + if (!parent || error) + return; + try { + parent->clock_tick(); + } + catch (...) + { + } + schedule(); + }); + } + + private: + AsioTimer timer; + OpenVPNClient* parent; + const Time::Duration period; + }; + + namespace Private { + class ClientState + { + public: + // state objects + OptionList options; + EvalConfig eval; + MySocketProtect socket_protect; + MyReconnectNotify reconnect_notify; + MyRemoteOverride remote_override; + ClientCreds::Ptr creds; + MySessionStats::Ptr stats; + MyClientEvents::Ptr events; + ClientConnect::Ptr session; + std::unique_ptr clock_tick; + + // extra settings submitted by API client + std::string server_override; + std::string port_override; + Protocol proto_override; + IPv6Setting ipv6; + int conn_timeout = 0; + bool tun_persist = false; + bool wintun = false; + bool google_dns_fallback = false; + bool synchronous_dns_lookup = false; + bool autologin_sessions = false; + bool retry_on_auth_failed = false; + std::string private_key_password; + std::string external_pki_alias; + bool disable_client_cert = false; + int ssl_debug_level = 0; + int default_key_direction = -1; + bool force_aes_cbc_ciphersuites = false; + std::string tls_version_min_override; + std::string tls_cert_profile_override; + std::string gui_version; + std::string sso_methods; + bool allow_local_lan_access; + std::string hw_addr_override; + std::string platform_version; + ProtoContextOptions::Ptr proto_context_options; + PeerInfo::Set::Ptr extra_peer_info; + HTTPProxyTransport::Options::Ptr http_proxy_options; + unsigned int clock_tick_ms = 0; +#ifdef OPENVPN_GREMLIN + Gremlin::Config::Ptr gremlin_config; +#endif + bool alt_proxy = false; + bool dco = false; + bool echo = false; + bool info = false; + + template + void attach(OpenVPNClient* parent, + openvpn_io::io_context* io_context, + Stop* async_stop_global) + { + // only one attachment per instantiation allowed + if (attach_called) + throw Exception("ClientState::attach() can only be called once per ClientState instantiation"); + attach_called = true; + + // async stop + async_stop_global_ = async_stop_global; + + // io_context + if (io_context) + io_context_ = io_context; + else + { + io_context_ = new openvpn_io::io_context(1); // concurrency hint=1 + io_context_owned = true; + } + + // client stats + stats.reset(new SESSION_STATS(parent)); + + // client events + events.reset(new CLIENT_EVENTS(parent)); + + // socket protect + socket_protect.set_parent(parent); + + // reconnect notifications + reconnect_notify.set_parent(parent); + + // remote override + remote_override.set_parent(parent); + } + + ClientState() {} + + ~ClientState() + { + stop_scope_local.reset(); + stop_scope_global.reset(); + socket_protect.detach_from_parent(); + reconnect_notify.detach_from_parent(); + remote_override.detach_from_parent(); + if (clock_tick) + clock_tick->detach_from_parent(); + if (stats) + stats->detach_from_parent(); + if (events) + events->detach_from_parent(); + session.reset(); + if (io_context_owned) + delete io_context_; + } + + // foreign thread access + + void enable_foreign_thread_access() + { + foreign_thread_ready.store(true, std::memory_order_release); + } + + bool is_foreign_thread_access() + { + return foreign_thread_ready.load(std::memory_order_acquire); + } + + // io_context + + openvpn_io::io_context* io_context() + { + return io_context_; + } + + // async stop + + Stop* async_stop_local() + { + return &async_stop_local_; + } + + Stop* async_stop_global() + { + return async_stop_global_; + } + + void trigger_async_stop_local() + { + async_stop_local_.stop(); + } + + // disconnect + void on_disconnect() + { + if (clock_tick) + clock_tick->cancel(); + } + + void setup_async_stop_scopes() + { + stop_scope_local.reset(new AsioStopScope(*io_context(), async_stop_local(), [this]() { + OPENVPN_ASYNC_HANDLER; + session->graceful_stop(); + })); + + stop_scope_global.reset(new AsioStopScope(*io_context(), async_stop_global(), [this]() { + OPENVPN_ASYNC_HANDLER; + trigger_async_stop_local(); + })); + } + + private: + ClientState(const ClientState&) = delete; + ClientState& operator=(const ClientState&) = delete; + + bool attach_called = false; + + Stop async_stop_local_; + Stop* async_stop_global_ = nullptr; + + std::unique_ptr stop_scope_local; + std::unique_ptr stop_scope_global; + + openvpn_io::io_context* io_context_ = nullptr; + bool io_context_owned = false; + + std::atomic foreign_thread_ready{false}; + }; + }; + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::init_process() + { + InitProcess::init(); + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::uninit_process() + { + InitProcess::uninit(); + } + + OPENVPN_CLIENT_EXPORT OpenVPNClient::OpenVPNClient() + { +#ifndef OPENVPN_NORESET_TIME + // We keep track of time as binary milliseconds since a time base, and + // this can wrap after ~48 days on 32 bit systems, so it's a good idea + // to periodically reinitialize the base. + Time::reset_base_conditional(); +#endif + + state = new Private::ClientState(); + state->proto_context_options.reset(new ProtoContextOptions()); + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::parse_config(const Config& config, EvalConfig& eval, OptionList& options) + { + try { + // validate proto_override + if (!config.protoOverride.empty()) + Protocol::parse(config.protoOverride, Protocol::NO_SUFFIX); + + // validate IPv6 setting + if (!config.ipv6.empty()) + IPv6Setting::parse(config.ipv6); + + // parse config + OptionList::KeyValueList kvl; + kvl.reserve(config.contentList.size()); + for (size_t i = 0; i < config.contentList.size(); ++i) + { + const KeyValue& kv = config.contentList[i]; + kvl.push_back(new OptionList::KeyValue(kv.key, kv.value)); + } + const ParseClientConfig cc = ParseClientConfig::parse(config.content, &kvl, options); +#ifdef OPENVPN_DUMP_CONFIG + std::cout << "---------- ARGS ----------" << std::endl; + std::cout << options.render(Option::RENDER_PASS_FMT|Option::RENDER_NUMBER|Option::RENDER_BRACKET) << std::endl; + std::cout << "---------- MAP ----------" << std::endl; + std::cout << options.render_map() << std::endl; +#endif + eval.error = cc.error(); + eval.message = cc.message(); + eval.userlockedUsername = cc.userlockedUsername(); + eval.profileName = cc.profileName(); + eval.friendlyName = cc.friendlyName(); + eval.autologin = cc.autologin(); + eval.externalPki = cc.externalPki(); + eval.staticChallenge = cc.staticChallenge(); + eval.staticChallengeEcho = cc.staticChallengeEcho(); + eval.privateKeyPasswordRequired = cc.privateKeyPasswordRequired(); + eval.allowPasswordSave = cc.allowPasswordSave(); + eval.remoteHost = config.serverOverride.empty() ? cc.firstRemoteListItem().host : config.serverOverride; + eval.remotePort = cc.firstRemoteListItem().port; + eval.remoteProto = cc.firstRemoteListItem().proto; + for (ParseClientConfig::ServerList::const_iterator i = cc.serverList().begin(); i != cc.serverList().end(); ++i) + { + ServerEntry se; + se.server = i->server; + se.friendlyName = i->friendlyName; + eval.serverList.push_back(se); + } + } + catch (const std::exception& e) + { + eval.error = true; + eval.message = Unicode::utf8_printable(std::string("ERR_PROFILE_GENERIC: ") + e.what(), 256); + } + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::parse_extras(const Config& config, EvalConfig& eval) + { + try { + state->server_override = config.serverOverride; + state->port_override = config.portOverride; + state->conn_timeout = config.connTimeout; + state->tun_persist = config.tunPersist; + state->wintun = config.wintun; + state->google_dns_fallback = config.googleDnsFallback; + state->synchronous_dns_lookup = config.synchronousDnsLookup; + state->autologin_sessions = config.autologinSessions; + state->retry_on_auth_failed = config.retryOnAuthFailed; + state->private_key_password = config.privateKeyPassword; + if (!config.protoOverride.empty()) + state->proto_override = Protocol::parse(config.protoOverride, Protocol::NO_SUFFIX); + if (!config.ipv6.empty()) + state->ipv6 = IPv6Setting::parse(config.ipv6); + if (!config.compressionMode.empty()) + state->proto_context_options->parse_compression_mode(config.compressionMode); + if (eval.externalPki) + state->external_pki_alias = config.externalPkiAlias; + state->disable_client_cert = config.disableClientCert; + state->ssl_debug_level = config.sslDebugLevel; + state->default_key_direction = config.defaultKeyDirection; + state->force_aes_cbc_ciphersuites = config.forceAesCbcCiphersuites; + state->tls_version_min_override = config.tlsVersionMinOverride; + state->tls_cert_profile_override = config.tlsCertProfileOverride; + state->allow_local_lan_access = config.allowLocalLanAccess; + state->gui_version = config.guiVersion; + state->sso_methods = config.ssoMethods; + state->platform_version = config.platformVersion; + state->hw_addr_override = config.hwAddrOverride; + state->alt_proxy = config.altProxy; + state->dco = config.dco; + state->echo = config.echo; + state->info = config.info; + state->clock_tick_ms = config.clockTickMS; + if (!config.gremlinConfig.empty()) + { +#ifdef OPENVPN_GREMLIN + state->gremlin_config.reset(new Gremlin::Config(config.gremlinConfig)); +#else + throw Exception("client not built with OPENVPN_GREMLIN"); +#endif + } + state->extra_peer_info = PeerInfo::Set::new_from_foreign_set(config.peerInfo); + if (!config.proxyHost.empty()) + { + HTTPProxyTransport::Options::Ptr ho(new HTTPProxyTransport::Options()); + ho->set_proxy_server(config.proxyHost, config.proxyPort); + ho->username = config.proxyUsername; + ho->password = config.proxyPassword; + ho->allow_cleartext_auth = config.proxyAllowCleartextAuth; + state->http_proxy_options = ho; + } + } + catch (const std::exception& e) + { + eval.error = true; + eval.message = Unicode::utf8_printable(e.what(), 256); + } + } + + OPENVPN_CLIENT_EXPORT long OpenVPNClient::max_profile_size() + { + return ProfileParseLimits::MAX_PROFILE_SIZE; + } + + OPENVPN_CLIENT_EXPORT MergeConfig OpenVPNClient::merge_config_static(const std::string& path, + bool follow_references) + { + ProfileMerge pm(path, "ovpn", "", follow_references ? ProfileMerge::FOLLOW_PARTIAL : ProfileMerge::FOLLOW_NONE, + ProfileParseLimits::MAX_LINE_SIZE, ProfileParseLimits::MAX_PROFILE_SIZE); + return build_merge_config(pm); + } + + OPENVPN_CLIENT_EXPORT MergeConfig OpenVPNClient::merge_config_string_static(const std::string& config_content) + { + ProfileMergeFromString pm(config_content, "", ProfileMerge::FOLLOW_NONE, + ProfileParseLimits::MAX_LINE_SIZE, ProfileParseLimits::MAX_PROFILE_SIZE); + return build_merge_config(pm); + } + + OPENVPN_CLIENT_EXPORT MergeConfig OpenVPNClient::build_merge_config(const ProfileMerge& pm) + { + MergeConfig ret; + ret.status = pm.status_string(); + ret.basename = pm.basename(); + if (pm.status() == ProfileMerge::MERGE_SUCCESS) + { + ret.refPathList = pm.ref_path_list(); + ret.profileContent = pm.profile_content(); + } + else + { + ret.errorText = pm.error(); + } + return ret; + } + + OPENVPN_CLIENT_EXPORT EvalConfig OpenVPNClient::eval_config_static(const Config& config) + { + EvalConfig eval; + OptionList options; + parse_config(config, eval, options); + return eval; + } + + // API client submits the configuration here before calling connect() + OPENVPN_CLIENT_EXPORT EvalConfig OpenVPNClient::eval_config(const Config& config) + { + // parse and validate configuration file + EvalConfig eval; + parse_config(config, eval, state->options); + if (eval.error) + return eval; + + // handle extra settings in config + parse_extras(config, eval); + state->eval = eval; + return eval; + } + + OPENVPN_CLIENT_EXPORT Status OpenVPNClient::provide_creds(const ProvideCreds& creds) + { + Status ret; + try { + ClientCreds::Ptr cc = new ClientCreds(); + cc->set_username(creds.username); + cc->set_password(creds.password); + cc->set_response(creds.response); + cc->set_dynamic_challenge_cookie(creds.dynamicChallengeCookie, creds.username); + cc->set_replace_password_with_session_id(creds.replacePasswordWithSessionID); + cc->enable_password_cache(creds.cachePassword); + state->creds = cc; + } + catch (const std::exception& e) + { + ret.error = true; + ret.message = Unicode::utf8_printable(e.what(), 256); + } + return ret; + } + + OPENVPN_CLIENT_EXPORT bool OpenVPNClient::socket_protect(int socket, std::string remote, bool ipv6) + { + return true; + } + + OPENVPN_CLIENT_EXPORT bool OpenVPNClient::parse_dynamic_challenge(const std::string& cookie, DynamicChallenge& dc) + { + try { + ChallengeResponse cr(cookie); + dc.challenge = cr.get_challenge_text(); + dc.echo = cr.get_echo(); + dc.responseRequired = cr.get_response_required(); + dc.stateID = cr.get_state_id(); + return true; + } + catch (const std::exception&) + { + return false; + } + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::process_epki_cert_chain(const ExternalPKICertRequest& req) + { + // Get cert and add to options list + if (!req.cert.empty()) + { + Option o; + o.push_back("cert"); + o.push_back(req.cert); + state->options.add_item(o); + } + + // Get the supporting chain, if it exists, and use + // it for ca (if ca isn't defined), or otherwise use + // it for extra-certs (if ca is defined but extra-certs + // is not). + if (!req.supportingChain.empty()) + { + if (!state->options.exists("ca")) + { + Option o; + o.push_back("ca"); + o.push_back(req.supportingChain); + state->options.add_item(o); + } + else if (!state->options.exists("extra-certs")) + { + Option o; + o.push_back("extra-certs"); + o.push_back(req.supportingChain); + state->options.add_item(o); + } + } + } + + OPENVPN_CLIENT_EXPORT Status OpenVPNClient::connect() + { +#if !defined(OPENVPN_OVPNCLI_SINGLE_THREAD) + openvpn_io::detail::signal_blocker signal_blocker; // signals should be handled by parent thread +#endif +#if defined(OPENVPN_LOG_LOGTHREAD_H) && !defined(OPENVPN_LOG_LOGBASE_H) +#ifdef OPENVPN_LOG_GLOBAL +#error ovpn3 core logging object only supports thread-local scope +#endif + Log::Context log_context(this); +#endif + + OPENVPN_LOG(ClientAPI::OpenVPNClient::platform()); + + return do_connect(); + } + + OPENVPN_CLIENT_EXPORT Status OpenVPNClient::do_connect() + { + Status status; + bool session_started = false; + try { + connect_attach(); +#if defined(OPENVPN_OVPNCLI_ASYNC_SETUP) + openvpn_io::post(*state->io_context(), [this]() { + do_connect_async(); + }); +#else + connect_setup(status, session_started); +#endif + connect_run(); + return status; + } + catch (const std::exception& e) + { + if (session_started) + connect_session_stop(); + return status_from_exception(e); + } + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::do_connect_async() + { + enum StopType { + NONE, + SESSION, + EXPLICIT, + }; + StopType stop_type = NONE; + Status status; + bool session_started = false; + try { + connect_setup(status, session_started); + } + catch (const std::exception& e) + { + stop_type = session_started ? SESSION : EXPLICIT; + status = status_from_exception(e); + } + if (status.error) + { + ClientEvent::Base::Ptr ev = new ClientEvent::ClientSetup(status.status, status.message); + state->events->add_event(std::move(ev)); + } + if (stop_type == SESSION) + connect_session_stop(); +#ifdef OPENVPN_IO_REQUIRES_STOP + if (stop_type == EXPLICIT) + state->io_context()->stop(); +#endif + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_setup(Status& status, bool& session_started) + { + // set global MbedTLS debug level +#if defined(USE_MBEDTLS) || defined(USE_MBEDTLS_APPLE_HYBRID) + mbedtls_debug_set_threshold(state->ssl_debug_level); // fixme -- using a global method for this seems wrong +#endif + + // load options + ClientOptions::Config cc; + cc.cli_stats = state->stats; + cc.cli_events = state->events; + cc.server_override = state->server_override; + cc.port_override = state->port_override; + cc.proto_override = state->proto_override; + cc.ipv6 = state->ipv6; + cc.conn_timeout = state->conn_timeout; + cc.tun_persist = state->tun_persist; + cc.wintun = state->wintun; + cc.google_dns_fallback = state->google_dns_fallback; + cc.synchronous_dns_lookup = state->synchronous_dns_lookup; + cc.autologin_sessions = state->autologin_sessions; + cc.retry_on_auth_failed = state->retry_on_auth_failed; + cc.proto_context_options = state->proto_context_options; + cc.http_proxy_options = state->http_proxy_options; + cc.alt_proxy = state->alt_proxy; + cc.dco = state->dco; + cc.echo = state->echo; + cc.info = state->info; + cc.reconnect_notify = &state->reconnect_notify; + if (remote_override_enabled()) + cc.remote_override = &state->remote_override; + cc.private_key_password = state->private_key_password; + cc.disable_client_cert = state->disable_client_cert; + cc.ssl_debug_level = state->ssl_debug_level; + cc.default_key_direction = state->default_key_direction; + cc.force_aes_cbc_ciphersuites = state->force_aes_cbc_ciphersuites; + cc.tls_version_min_override = state->tls_version_min_override; + cc.tls_cert_profile_override = state->tls_cert_profile_override; + cc.gui_version = state->gui_version; + cc.sso_methods = state->sso_methods; + cc.hw_addr_override = state->hw_addr_override; + cc.platform_version = state->platform_version; + cc.extra_peer_info = state->extra_peer_info; + cc.stop = state->async_stop_local(); + cc.allow_local_lan_access = state->allow_local_lan_access; +#ifdef OPENVPN_GREMLIN + cc.gremlin_config = state->gremlin_config; +#endif + cc.socket_protect = &state->socket_protect; +#if defined(USE_TUN_BUILDER) + cc.builder = this; +#endif +#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) + cc.extern_tun_factory = this; +#endif +#if defined(OPENVPN_EXTERNAL_TRANSPORT_FACTORY) + cc.extern_transport_factory = this; +#endif + // force Session ID use and disable password cache if static challenge is enabled + if (state->creds + && !state->creds->get_replace_password_with_session_id() + && !state->eval.autologin + && !state->eval.staticChallenge.empty()) + { + state->creds->set_replace_password_with_session_id(true); + state->creds->enable_password_cache(false); + } + + // external PKI +#if !defined(USE_APPLE_SSL) + if (state->eval.externalPki && !state->disable_client_cert) + { + if (!state->external_pki_alias.empty()) + { + ExternalPKICertRequest req; + req.alias = state->external_pki_alias; + external_pki_cert_request(req); + if (!req.error) + { + cc.external_pki = this; + process_epki_cert_chain(req); + } + else + { + external_pki_error(req, Error::EPKI_CERT_ERROR); + return; + } + } + else + { + status.error = true; + status.message = "Missing External PKI alias"; + return; + } + } +#endif + +#ifdef USE_OPENSSL + if (state->options.exists("allow-name-constraints")) + { + ClientEvent::Base::Ptr ev = new ClientEvent::UnsupportedFeature("allow-name-constraints", + "Always verified correctly with OpenSSL", false); + state->events->add_event(std::move(ev)); + } +#endif + + // build client options object + ClientOptions::Ptr client_options = new ClientOptions(state->options, cc); + + // configure creds in options + client_options->submit_creds(state->creds); + + // instantiate top-level client session + state->session.reset(new ClientConnect(*state->io_context(), client_options)); + + // convenience clock tick + if (state->clock_tick_ms) + { + state->clock_tick.reset(new MyClockTick(*state->io_context(), this, state->clock_tick_ms)); + state->clock_tick->schedule(); + } + + // raise an exception if app has expired + check_app_expired(); + + // start VPN + state->session->start(); // queue reads on socket/tun + session_started = true; + + // wire up async stop + state->setup_async_stop_scopes(); + + // prepare to start reactor + connect_pre_run(); + state->enable_foreign_thread_access(); + } + + OPENVPN_CLIENT_EXPORT Status OpenVPNClient::status_from_exception(const std::exception& e) + { + Status ret; + ret.error = true; + ret.message = Unicode::utf8_printable(e.what(), 256); + + // if exception is an ExceptionCode, translate the code + // to return status string + { + const ExceptionCode *ec = dynamic_cast(&e); + if (ec && ec->code_defined()) + ret.status = Error::name(ec->code()); + } + return ret; + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_attach() + { + state->attach(this, + nullptr, + get_async_stop()); + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_pre_run() + { + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_run() + { + state->io_context()->run(); + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_session_stop() + { + state->session->stop(); // On exception, stop client... + state->io_context()->poll(); // and execute completion handlers. + } + + OPENVPN_CLIENT_EXPORT ConnectionInfo OpenVPNClient::connection_info() + { + ConnectionInfo ci; + if (state->is_foreign_thread_access()) + { + MyClientEvents* events = state->events.get(); + if (events) + events->get_connection_info(ci); + } + return ci; + } + + OPENVPN_CLIENT_EXPORT bool OpenVPNClient::session_token(SessionToken& tok) + { + if (state->is_foreign_thread_access()) + { + ClientCreds* cc = state->creds.get(); + if (cc && cc->session_id_defined()) + { + tok.username = cc->get_username(); + tok.session_id = cc->get_password(); + return true; + } + } + return false; + } + + OPENVPN_CLIENT_EXPORT Stop* OpenVPNClient::get_async_stop() + { + return nullptr; + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::external_pki_error(const ExternalPKIRequestBase& req, const size_t err_type) + { + if (req.error) + { + if (req.invalidAlias) + { + ClientEvent::Base::Ptr ev = new ClientEvent::EpkiInvalidAlias(req.alias); + state->events->add_event(std::move(ev)); + } + + ClientEvent::Base::Ptr ev = new ClientEvent::EpkiError(req.errorText); + state->events->add_event(std::move(ev)); + + state->stats->error(err_type); + if (state->session) + state->session->dont_restart(); + } + } + + OPENVPN_CLIENT_EXPORT bool OpenVPNClient::sign(const std::string& data, std::string& sig, const std::string& algorithm) + { + ExternalPKISignRequest req; + req.data = data; + req.alias = state->external_pki_alias; + req.algorithm = algorithm; + external_pki_sign_request(req); // call out to derived class for RSA signature + if (!req.error) + { + sig = req.sig; + return true; + } + else + { + external_pki_error(req, Error::EPKI_SIGN_ERROR); + return false; + } + } + + OPENVPN_CLIENT_EXPORT bool OpenVPNClient::remote_override_enabled() + { + return false; + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::remote_override(RemoteOverride&) + { + } + + OPENVPN_CLIENT_EXPORT int OpenVPNClient::stats_n() + { + return (int)MySessionStats::combined_n(); + } + + OPENVPN_CLIENT_EXPORT std::string OpenVPNClient::stats_name(int index) + { + return MySessionStats::combined_name(index); + } + + OPENVPN_CLIENT_EXPORT long long OpenVPNClient::stats_value(int index) const + { + if (state->is_foreign_thread_access()) + { + MySessionStats* stats = state->stats.get(); + if (stats) + { + if (index == SessionStats::BYTES_IN || index == SessionStats::BYTES_OUT) + stats->dco_update(); + return stats->combined_value(index); + } + } + return 0; + } + + OPENVPN_CLIENT_EXPORT std::vector OpenVPNClient::stats_bundle() const + { + std::vector sv; + const size_t n = MySessionStats::combined_n(); + sv.reserve(n); + if (state->is_foreign_thread_access()) + { + MySessionStats* stats = state->stats.get(); + if (stats) + stats->dco_update(); + for (size_t i = 0; i < n; ++i) + sv.push_back(stats ? stats->combined_value(i) : 0); + } + else + { + for (size_t i = 0; i < n; ++i) + sv.push_back(0); + } + return sv; + } + + OPENVPN_CLIENT_EXPORT InterfaceStats OpenVPNClient::tun_stats() const + { + InterfaceStats ret; + if (state->is_foreign_thread_access()) + { + MySessionStats* stats = state->stats.get(); + + // The reason for the apparent inversion between in/out below is + // that TUN_*_OUT stats refer to data written to tun device, + // but from the perspective of tun interface, this is incoming + // data. Vice versa for TUN_*_IN. + if (stats) + { + ret.bytesOut = stats->stat_count(SessionStats::TUN_BYTES_IN); + ret.bytesIn = stats->stat_count(SessionStats::TUN_BYTES_OUT); + ret.packetsOut = stats->stat_count(SessionStats::TUN_PACKETS_IN); + ret.packetsIn = stats->stat_count(SessionStats::TUN_PACKETS_OUT); + ret.errorsOut = stats->error_count(Error::TUN_READ_ERROR); + ret.errorsIn = stats->error_count(Error::TUN_WRITE_ERROR); + return ret; + } + } + + ret.bytesOut = 0; + ret.bytesIn = 0; + ret.packetsOut = 0; + ret.packetsIn = 0; + ret.errorsOut = 0; + ret.errorsIn = 0; + return ret; + } + + OPENVPN_CLIENT_EXPORT TransportStats OpenVPNClient::transport_stats() const + { + TransportStats ret; + ret.lastPacketReceived = -1; // undefined + + if (state->is_foreign_thread_access()) + { + MySessionStats* stats = state->stats.get(); + if (stats) + { + stats->dco_update(); + ret.bytesOut = stats->stat_count(SessionStats::BYTES_OUT); + ret.bytesIn = stats->stat_count(SessionStats::BYTES_IN); + ret.packetsOut = stats->stat_count(SessionStats::PACKETS_OUT); + ret.packetsIn = stats->stat_count(SessionStats::PACKETS_IN); + + // calculate time since last packet received + { + const Time& lpr = stats->last_packet_received(); + if (lpr.defined()) + { + const Time::Duration dur = Time::now() - lpr; + const unsigned int delta = (unsigned int)dur.to_binary_ms(); + if (delta <= 60*60*24*1024) // only define for time periods <= 1 day + ret.lastPacketReceived = delta; + } + } + return ret; + } + } + + ret.bytesOut = 0; + ret.bytesIn = 0; + ret.packetsOut = 0; + ret.packetsIn = 0; + return ret; + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::stop() + { + if (state->is_foreign_thread_access()) + state->trigger_async_stop_local(); + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::pause(const std::string& reason) + { + if (state->is_foreign_thread_access()) + { + ClientConnect* session = state->session.get(); + if (session) + session->thread_safe_pause(reason); + } + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::resume() + { + if (state->is_foreign_thread_access()) + { + ClientConnect* session = state->session.get(); + if (session) + session->thread_safe_resume(); + } + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::reconnect(int seconds) + { + if (state->is_foreign_thread_access()) + { + ClientConnect* session = state->session.get(); + if (session) + session->thread_safe_reconnect(seconds); + } + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::post_cc_msg(const std::string& msg) + { + if (state->is_foreign_thread_access()) + { + ClientConnect* session = state->session.get(); + if (session) + session->thread_safe_post_cc_msg(msg); + } + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::clock_tick() + { + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::on_disconnect() + { + state->on_disconnect(); + } + + OPENVPN_CLIENT_EXPORT std::string OpenVPNClient::crypto_self_test() + { + return SelfTest::crypto_self_test(); + } + + OPENVPN_CLIENT_EXPORT int OpenVPNClient::app_expire() + { +#ifdef APP_EXPIRE_TIME + return APP_EXPIRE_TIME; +#else + return 0; +#endif + } + + OPENVPN_CLIENT_EXPORT void OpenVPNClient::check_app_expired() + { +#ifdef APP_EXPIRE_TIME + if (Time::now().seconds_since_epoch() >= APP_EXPIRE_TIME) + throw app_expired(); +#endif + } + + OPENVPN_CLIENT_EXPORT std::string OpenVPNClient::copyright() + { + return openvpn_copyright; + } + + OPENVPN_CLIENT_EXPORT std::string OpenVPNClient::platform() + { + std::string ret = platform_string(); +#ifdef PRIVATE_TUNNEL_PROXY + ret += " PT_PROXY"; +#endif +#ifdef ENABLE_DCO + ret += " DCO"; +#endif +#ifdef OPENVPN_GREMLIN + ret += " GREMLIN"; +#endif +#ifdef OPENVPN_DEBUG + ret += " built on " __DATE__ " " __TIME__; +#endif + return ret; + } + + OPENVPN_CLIENT_EXPORT OpenVPNClient::~OpenVPNClient() + { + delete state; + } + } +} diff --git a/client/ovpncli.hpp b/client/ovpncli.hpp new file mode 100644 index 0000000..9a1f5be --- /dev/null +++ b/client/ovpncli.hpp @@ -0,0 +1,633 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// API for OpenVPN Client, may be used standalone or wrapped by swig. +// Use ovpncli.i to wrap the API for swig. +// The crux of the API is defined in OpenVPNClient (below) +// and TunBuilderBase. + +#include +#include +#include + +#include +#include +#include +#include + +namespace openvpn { + class OptionList; + class ProfileMerge; + class Stop; + + namespace ClientAPI { + // Represents an OpenVPN server and its friendly name + // (client reads) + struct ServerEntry + { + std::string server; + std::string friendlyName; + }; + + // return properties of config + // (client reads) + struct EvalConfig + { + // true if error + bool error = false; + + // if error, message given here + std::string message; + + // this username must be used with profile + std::string userlockedUsername; + + // profile name of config + std::string profileName; + + // "friendly" name of config + std::string friendlyName; + + // true: no creds required, false: username/password required + bool autologin = false; + + // if true, this is an External PKI profile (no cert or key directives) + bool externalPki = false; + + // static challenge, may be empty, ignored if autologin + std::string staticChallenge; + + // true if static challenge response should be echoed to UI, ignored if autologin + bool staticChallengeEcho = false; + + // true if this profile requires a private key password + bool privateKeyPasswordRequired = false; + + // true if user is allowed to save authentication password in UI + bool allowPasswordSave = false; + + // information about the first remote item in config + std::string remoteHost; // will be overridden by Config::serverOverride if defined + std::string remotePort; + std::string remoteProto; + + // optional list of user-selectable VPN servers + std::vector serverList; + }; + + // used to pass credentials to VPN core + // (client writes) + struct ProvideCreds + { + std::string username; + std::string password; + + // response to challenge + std::string response; + + // Dynamic challenge/response cookie + std::string dynamicChallengeCookie; + + // If true, on successful connect, we will replace the password + // with the session ID we receive from the server (if provided). + // If false, the password will be cached for future reconnects + // and will not be replaced with a session ID, even if the + // server provides one. + bool replacePasswordWithSessionID = false; + + // If true, and if replacePasswordWithSessionID is true, and if + // we actually receive a session ID from the server, cache + // the user-provided password for future use before replacing + // the active password with the session ID. + bool cachePassword = false; + }; + + // used to get session token from VPN core + // (client reads) + struct SessionToken + { + std::string username; + std::string session_id; // an OpenVPN Session ID, used as a proxy for password + }; + + // used to query challenge/response from user + // (client reads) + struct DynamicChallenge + { + std::string challenge; + bool echo = false; + bool responseRequired = false; + + std::string stateID; + }; + + // a basic key/value pair, used in Config below when OpenVPN profile is + // passed as a dictionary + struct KeyValue + { + KeyValue() {} + + KeyValue(std::string key_arg, std::string value_arg) + : key(std::move(key_arg)), + value(std::move(value_arg)) {} + + std::string key; + std::string value; + }; + + // OpenVPN config-file/profile + // (client writes) + struct Config + { + // OpenVPN profile as a string + std::string content; + + // OpenVPN profile as series of key/value pairs (may be provided exclusively + // or in addition to content string above). + std::vector contentList; + + // Set to identity OpenVPN GUI version. + // Format should be "" + // Passed to server as IV_GUI_VER. + std::string guiVersion; + + // Set to a comma seperated list of supported SSO mechanisms that may + // be signalled via INFO_PRE to the client. + // "openurl" is to continue authentication by opening an url in a browser + // "crtext" gives a challenge response in text format that needs to + // responded via control channel. ( + // Passed to the server as IV_SSO + std::string ssoMethods; + + // Override the string that is passed as IV_HWADDR to the server + std::string hwAddrOverride; + + // Set the string that is passed to the server as IV_PLAT_VER + std::string platformVersion; + + // Use a different server than that specified in "remote" + // option of profile + std::string serverOverride; + + // Use a different port than that specified in "remote" + // option of profile + std::string portOverride; + + // Force a given transport protocol + // Should be tcp, udp, or adaptive. + std::string protoOverride; + + // IPv6 preference + // no -- disable IPv6, so tunnel will be IPv4-only + // yes -- request combined IPv4/IPv6 tunnel + // default (or empty string) -- leave decision to server + std::string ipv6; + + // Connection timeout in seconds, or 0 to retry indefinitely + int connTimeout = 0; + + // Keep tun interface active during pauses or reconnections + bool tunPersist = false; + + // If true and a redirect-gateway profile doesn't also define + // DNS servers, use the standard Google DNS servers. + bool googleDnsFallback = false; + + // if true, do synchronous DNS lookup. + bool synchronousDnsLookup = false; + + // Enable autologin sessions + bool autologinSessions = true; + + // If true, consider AUTH_FAILED to be a non-fatal error, + // and retry the connection after a pause. + bool retryOnAuthFailed = false; + + // An ID used for get-certificate and RSA signing callbacks + // for External PKI profiles. + std::string externalPkiAlias; + + // If true, don't send client cert/key to peer. + bool disableClientCert = false; + + // SSL library debug level + int sslDebugLevel = 0; + + // Compression mode, one of: + // yes -- allow compression on both uplink and downlink + // asym -- allow compression on downlink only (i.e. server -> client) + // no (default if empty) -- support compression stubs only + std::string compressionMode; + + // private key password (optional) + std::string privateKeyPassword; + + // Default key direction parameter for tls-auth (0, 1, or + // -1 (bidirectional -- default)) if no key-direction parameter + // defined in profile. Generally should be -1 (bidirectional) + // for compatibility with 2.x branch + int defaultKeyDirection = -1; + + // If true, force ciphersuite to be one of: + // 1. TLS_DHE_RSA_WITH_AES_256_CBC_SHA, or + // 2. TLS_DHE_RSA_WITH_AES_128_CBC_SHA + // and disable setting TLS minimum version. + // This is intended for compatibility with legacy systems. + bool forceAesCbcCiphersuites = false; + + // Override the minimum TLS version: + // disabled -- don't specify a minimum, and disable any minimum + // specified in profile + // default or "" -- use profile minimum + // tls_1_0 -- use TLS 1.0 minimum (overrides profile) + // tls_1_1 -- use TLS 1.1 minimum (overrides profile) + // tls_1_2 -- use TLS 1.2 minimum (overrides profile) + std::string tlsVersionMinOverride; + + // Override or default the tls-cert-profile setting: + // default or "" -- use profile default + // legacy -- allow 1024-bit RSA certs signed with SHA1 + // preferred -- require at least 2048-bit RSA certs signed + // with SHA256 or higher + // suiteb -- require NSA Suite-B + // legacy-default -- use legacy as the default if profile + // doesn't specify tls-cert-profile + // preferred-default -- use preferred as the default if profile + // doesn't specify tls-cert-profile + std::string tlsCertProfileOverride; + + // Pass custom key/value pairs to OpenVPN server. + std::vector peerInfo; + + // HTTP Proxy parameters (optional) + std::string proxyHost; // hostname or IP address of proxy + std::string proxyPort; // port number of proxy + std::string proxyUsername; // proxy credentials (optional) + std::string proxyPassword; // proxy credentials (optional) + bool proxyAllowCleartextAuth = false; // enables HTTP Basic auth + + // Custom proxy implementation + bool altProxy = false; + + // Custom Data Channel Offload implementation + bool dco = false; + + // pass through pushed "echo" directives via "ECHO" event + bool echo = false; + + // pass through control channel INFO notifications via "INFO" event + bool info = false; + + // Allow access to local LAN. This is for platforms like + // Android that disable local LAN access by default. + bool allowLocalLanAccess = false; + + // Periodic convenience clock tick in milliseconds. + // Will call clock_tick() at a frequency defined by this parameter. + // Set to 0 to disable. + unsigned int clockTickMS = 0; + + // Gremlin configuration (requires that the core is built with OPENVPN_GREMLIN) + std::string gremlinConfig; + + // Use wintun instead of tap-windows6 on Windows + bool wintun = false; + }; + + // used to communicate VPN events such as connect, disconnect, etc. + // (client reads) + struct Event + { + bool error = false; // true if error (fatal or nonfatal) + bool fatal = false; // true if fatal error (will disconnect) + std::string name; // event name + std::string info; // additional event info + }; + + // used to communicate extra details about successful connection + // (client reads) + struct ConnectionInfo + { + bool defined = false; + std::string user; + std::string serverHost; + std::string serverPort; + std::string serverProto; + std::string serverIp; + std::string vpnIp4; + std::string vpnIp6; + std::string gw4; + std::string gw6; + std::string clientIp; + std::string tunName; + }; + + // returned by some methods as a status/error indication + // (client reads) + struct Status + { + bool error = false; // true if error + std::string status; // an optional short error label that identifies the error + std::string message; // if error, message given here + }; + + // used to pass log lines + // (client reads) + struct LogInfo + { + LogInfo() {} + LogInfo(std::string str) + : text(std::move(str)) {} + std::string text; // log output (usually but not always one line) + }; + + // receives log messages + struct LogReceiver + { + virtual void log(const LogInfo&) = 0; + virtual ~LogReceiver() {} + }; + + // used to pass stats for an interface + struct InterfaceStats + { + long long bytesIn; + long long packetsIn; + long long errorsIn; + long long bytesOut; + long long packetsOut; + long long errorsOut; + }; + + // used to pass basic transport stats + struct TransportStats + { + long long bytesIn; + long long bytesOut; + long long packetsIn; + long long packetsOut; + + // number of binary milliseconds (1/1024th of a second) since + // last packet was received, or -1 if undefined + int lastPacketReceived; + }; + + // return value of merge_config methods + struct MergeConfig + { + std::string status; // ProfileMerge::Status codes rendered as string + std::string errorText; // error string (augments status) + std::string basename; // profile basename + std::string profileContent; // unified profile + std::vector refPathList; // list of all reference paths successfully read + }; + + // base class for External PKI queries + struct ExternalPKIRequestBase + { + bool error = false; // true if error occurred (client writes) + std::string errorText; // text describing error (client writes) + bool invalidAlias = false; // true if the error is caused by an invalid alias (client writes) + std::string alias; // the alias string, used to query cert/key (client reads) + }; + + // used to query for External PKI certificate + struct ExternalPKICertRequest : public ExternalPKIRequestBase + { + // leaf cert + std::string cert; // (client writes) + + // chain of intermediates and root (optional) + std::string supportingChain; // (client writes) + }; + + // Used to request an RSA signature. + // algorithm will determinate what signature is expected: + // RSA_PKCS1_PADDING means that + // data will be prefixed by an optional PKCS#1 digest prefix + // per RFC 3447. + // RSA_NO_PADDING mean so no padding should be done be the callee + struct ExternalPKISignRequest : public ExternalPKIRequestBase + { + std::string data; // data rendered as base64 (client reads) + std::string sig; // RSA signature, rendered as base64 (client writes) + std::string algorithm; + }; + + // used to override "remote" directives + struct RemoteOverride + { + // components of "remote" directive (client writes), + std::string host; // either one of host + std::string ip; // or ip must be defined (or both) + std::string port; + std::string proto; + std::string error; // if non-empty, indicates an error + }; + + namespace Private { + class ClientState; + }; + + // Top-level OpenVPN client class. + class OpenVPNClient : public TunBuilderBase, // expose tun builder virtual methods + public LogReceiver, // log message notification + public ExternalTun::Factory, // low-level tun override + public ExternalTransport::Factory,// low-level transport override + private ExternalPKIBase + { + public: + OpenVPNClient(); + virtual ~OpenVPNClient(); + + // Call me first, before calling any other method (static or instance methods) + // in this class. + static void init_process(); + + // Release any resources allocated by init_process. + static void uninit_process(); + + // Read an OpenVPN profile that might contain external + // file references, returning a unified profile. + static MergeConfig merge_config_static(const std::string& path, bool follow_references); + + // Read an OpenVPN profile that might contain external + // file references, returning a unified profile. + static MergeConfig merge_config_string_static(const std::string& config_content); + + // Parse profile and determine needed credentials statically. + static EvalConfig eval_config_static(const Config& config); + + // Maximum size of profile that should be allowed + static long max_profile_size(); + + // Parse a dynamic challenge cookie, placing the result in dc. + // Return true on success or false if parse error. + static bool parse_dynamic_challenge(const std::string& cookie, DynamicChallenge& dc); + + // Parse OpenVPN configuration file. + EvalConfig eval_config(const Config&); + + // Provide credentials and other options. Call before connect(). + Status provide_creds(const ProvideCreds&); + + // Callback to "protect" a socket from being routed through the tunnel. + // Will be called from the thread executing connect(). + // The remote and ipv6 are the remote host this socket will connect to + virtual bool socket_protect(int socket, std::string remote, bool ipv6); + + // Primary VPN client connect method, doesn't return until disconnect. + // Should be called by a worker thread. This method will make callbacks + // to event() and log() functions. Make sure to call eval_config() + // and possibly provide_creds() as well before this function. + Status connect(); + + // Return information about the most recent connection. Should be called + // after an event of type "CONNECTED". + ConnectionInfo connection_info(); + + // Writes current session token to tok and returns true. + // If session token is unavailable, false is returned and + // tok is unmodified. + bool session_token(SessionToken& tok); + + // Stop the client. Only meaningful when connect() is running. + // May be called asynchronously from a different thread + // when connect() is running. + void stop(); + + // Pause the client -- useful to avoid continuous reconnection attempts + // when network is down. May be called from a different thread + // when connect() is running. + void pause(const std::string& reason); + + // Resume the client after it has been paused. May be called from a + // different thread when connect() is running. + void resume(); + + // Do a disconnect/reconnect cycle n seconds from now. May be called + // from a different thread when connect() is running. + void reconnect(int seconds); + + // When a connection is close to timeout, the core will call this + // method. If it returns false, the core will disconnect with a + // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE + // state. + virtual bool pause_on_connection_timeout() = 0; + + // Get stats/error info. May be called from a different thread + // when connect() is running. + + // number of stats + static int stats_n(); + + // return a stats name, index should be >= 0 and < stats_n() + static std::string stats_name(int index); + + // return a stats value, index should be >= 0 and < stats_n() + long long stats_value(int index) const; + + // return all stats in a bundle + std::vector stats_bundle() const; + + // return tun stats only + InterfaceStats tun_stats() const; + + // return transport stats only + TransportStats transport_stats() const; + + // post control channel message + void post_cc_msg(const std::string& msg); + + // Callback for delivering events during connect() call. + // Will be called from the thread executing connect(). + virtual void event(const Event&) = 0; + + // Callback for logging. + // Will be called from the thread executing connect(). + virtual void log(const LogInfo&) = 0; + + // External PKI callbacks + // Will be called from the thread executing connect(). + virtual void external_pki_cert_request(ExternalPKICertRequest&) = 0; + virtual void external_pki_sign_request(ExternalPKISignRequest&) = 0; + + // Remote override callback (disabled by default). + virtual bool remote_override_enabled(); + virtual void remote_override(RemoteOverride&); + + // Periodic convenience clock tick, controlled by Config::clockTickMS + virtual void clock_tick(); + + // Do a crypto library self test + static std::string crypto_self_test(); + + // Returns date/time of app expiration as a unix time value + static int app_expire(); + + // Returns platform description string + static std::string platform(); + + // Returns core copyright + static std::string copyright(); + + // Hide protected methods/data from SWIG +#ifdef SWIGJAVA + private: +#else + protected: +#endif + + Status do_connect(); + + virtual void connect_attach(); + virtual void connect_pre_run(); + virtual void connect_run(); + virtual void connect_session_stop(); + + virtual Stop* get_async_stop(); + + Private::ClientState* state; + + private: + void connect_setup(Status&, bool&); + void do_connect_async(); + static Status status_from_exception(const std::exception&); + static void parse_config(const Config&, EvalConfig&, OptionList&); + void parse_extras(const Config&, EvalConfig&); + void external_pki_error(const ExternalPKIRequestBase&, const size_t); + void process_epki_cert_chain(const ExternalPKICertRequest&); + void check_app_expired(); + static MergeConfig build_merge_config(const ProfileMerge&); + + friend class MyClientEvents; + void on_disconnect(); + + // from ExternalPKIBase + virtual bool sign(const std::string& data, std::string& sig, const std::string& algorithm); + + // disable copy and assignment + OpenVPNClient(const OpenVPNClient&) = delete; + OpenVPNClient& operator=(const OpenVPNClient&) = delete; + }; + + } +} diff --git a/cmake/CMakeLists.txt.in b/cmake/CMakeLists.txt.in new file mode 100644 index 0000000..03bf3ff --- /dev/null +++ b/cmake/CMakeLists.txt.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.5) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG master + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" + ) diff --git a/cmake/FindLZ4.cmake b/cmake/FindLZ4.cmake new file mode 100644 index 0000000..761b275 --- /dev/null +++ b/cmake/FindLZ4.cmake @@ -0,0 +1,9 @@ +find_path(LZ4_INCLUDE_DIR NAMES lz4.h) +find_library(LZ4_LIBRARY NAMES lz4) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( + LZ4 DEFAULT_MSG + LZ4_LIBRARY LZ4_INCLUDE_DIR) + +mark_as_advanced(LZ4_INCLUDE_DIR LZ4_LIBRARY) \ No newline at end of file diff --git a/cmake/FindmbedTLS.cmake b/cmake/FindmbedTLS.cmake new file mode 100644 index 0000000..a262eaf --- /dev/null +++ b/cmake/FindmbedTLS.cmake @@ -0,0 +1,63 @@ +# - Try to find mbedTLS +# Once done this will define +# +# Read-Only variables +# MBEDTLS_FOUND - system has mbedTLS +# MBEDTLS_INCLUDE_DIR - the mbedTLS include directory +# MBEDTLS_LIBRARY_DIR - the mbedTLS library directory +# MBEDTLS_LIBRARIES - Link these to use mbedTLS +# MBEDTLS_LIBRARY - path to mbedTLS library +# MBEDX509_LIBRARY - path to mbedTLS X.509 library +# MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library + +FIND_PATH(MBEDTLS_INCLUDE_DIR mbedtls/version.h) + +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES) + # Already in cache, be silent + SET(MBEDTLS_FIND_QUIETLY TRUE) +ENDIF() + +FIND_LIBRARY(MBEDTLS_LIBRARY NAMES mbedtls libmbedtls libmbedx509) +FIND_LIBRARY(MBEDX509_LIBRARY NAMES mbedx509 libmbedx509) +FIND_LIBRARY(MBEDCRYPTO_LIBRARY NAMES mbedcrypto libmbedcrypto) + +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY) + SET(MBEDTLS_FOUND TRUE) +ELSEIF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND NOT MBEDX509_LIBRARY AND NOT MBEDCRYPTO_LIBRARY) + SET(MBEDTLS_FOUND TRUE) + SET(HACKY_OVPN_MBEDTLS TRUE) +ENDIF() + +IF(MBEDTLS_FOUND) + IF(HACKY_OVPN_MBEDTLS) + SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY}) + ELSE() + SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) + endif() + + IF(NOT MBEDTLS_FIND_QUIETLY) + MESSAGE(STATUS "Found mbedTLS:") + FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT) + STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT}) + IF (MBEDTLSMATCH) + STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH}) + MESSAGE(STATUS " version ${MBEDTLS_VERSION}") + ENDIF(MBEDTLSMATCH) + MESSAGE(STATUS " TLS: ${MBEDTLS_LIBRARY}") + MESSAGE(STATUS " X509: ${MBEDX509_LIBRARY}") + MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}") + ENDIF(NOT MBEDTLS_FIND_QUIETLY) +ELSE(MBEDTLS_FOUND) + IF(mbedTLS_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find mbedTLS") + ENDIF(mbedTLS_FIND_REQUIRED) +ENDIF(MBEDTLS_FOUND) + +MARK_AS_ADVANCED( + MBEDTLS_INCLUDE_DIR + MBEDTLS_LIBRARY_DIR + MBEDTLS_LIBRARIES + MBEDTLS_LIBRARY + MBEDX509_LIBRARY + MBEDCRYPTO_LIBRARY +) \ No newline at end of file diff --git a/cmake/dlgoogletest.cmake b/cmake/dlgoogletest.cmake new file mode 100644 index 0000000..ebd1a88 --- /dev/null +++ b/cmake/dlgoogletest.cmake @@ -0,0 +1,35 @@ + +# Google Test Unit testing +# Download and unpack googletest at configure time + +# Ensure that this only downloaded and added once +#include_guard(GLOBAL) +# Unfortunately include_guard requires cmake >= 3.10 +include(mypragmaonce) + +my_pragma_once() + + +configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in googletest-download/CMakeLists.txt) +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif() +execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) +if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") +endif() + +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Add googletest directly to our build. This defines +# the gtest and gtest_main targets. +add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src + ${CMAKE_CURRENT_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL) diff --git a/cmake/findcoredeps.cmake b/cmake/findcoredeps.cmake new file mode 100644 index 0000000..1961d76 --- /dev/null +++ b/cmake/findcoredeps.cmake @@ -0,0 +1,107 @@ +cmake_minimum_required(VERSION 3.5) + +set(CMAKE_CXX_STANDARD 14) + +#cmake_policy(SET CMP0079 NEW) + +set(CORE_DIR ${CMAKE_CURRENT_LIST_DIR}/..) + + +set(DEP_DIR ${CORE_DIR}/../deps CACHE PATH "Dependencies") +option(USE_MBEDTLS "Use mbed TLS instead of OpenSSL") + +if (DEFINED ENV{DEP_DIR}) + message(WARNING "Overriding DEP_DIR setting with environment variable") + set(DEP_DIR $ENV{DEP_DIR}) +endif () + +# Include our DEP_DIR in path used to find libraries + + +function(add_core_dependencies target) + if (APPLE) + set(PLAT osx) + elseif (WIN32) + set(PLAT amd64) + else () + set(PLAT linux) + endif () + + set(CORE_INCLUDES + ${CORE_DIR} + ${DEP_DIR}/asio/asio/include + ) + set(CORE_DEFINES + -DASIO_STANDALONE + -DUSE_ASIO + -DHAVE_LZ4 + -DLZ4_DISABLE_DEPRECATE_WARNINGS + -DMBEDTLS_DEPRECATED_REMOVED + ) + + if (WIN32) + list(APPEND CMAKE_PREFIX_PATH + ${DEP_DIR}/${PLAT}/mbedtls + ${DEP_DIR}/${PLAT}/lz4/lib + ) + list(APPEND CMAKE_LIBRARY_PATH + ${DEP_DIR}/${PLAT}/mbedtls/library + ) + list(APPEND CORE_INCLUDES + ${DEP_DIR}/${PLAT}/asio/asio/include + ${DEP_DIR}/${PLAT}/lz4/lz4/include + ${DEP_DIR}/${PLAT}/tap-windows/src + ) + list(APPEND CORE_DEFINES + -D_WIN32_WINNT=0x0600 + -DTAP_WIN_COMPONENT_ID=tap0901 + -D_CRT_SECURE_NO_WARNINGS + ) + set(EXTRA_LIBS fwpuclnt.lib Iphlpapi.lib) + target_compile_options(${target} PRIVATE "/bigobj") + else () + list(APPEND CMAKE_PREFIX_PATH + ${DEP_DIR}/mbedtls/mbedtls-${PLAT} + ${DEP_DIR}/lz4/lz4-${PLAT} + ) + list(APPEND CMAKE_LIBRARY_PATH + ${DEP_DIR}/mbedtls/mbedtls-${PLAT}/library + ) + endif () + + + if (${USE_MBEDTLS}) + find_package(mbedTLS REQUIRED) + + set(SSL_LIBRARY ${MBEDTLS_LIBRARIES}) + + list(APPEND CORE_DEFINES -DUSE_MBEDTLS) + + # The findmbedTLS does not set these automatically :( + list(APPEND CORE_INCLUDES ${MBEDTLS_INCLUDE_DIR}) + + else () + find_package(OpenSSL REQUIRED) + SET(SSL_LIBRARY OpenSSL::SSL) + list(APPEND CORE_DEFINES -DUSE_OPENSSL) + endif () + + if (APPLE) + find_library(coreFoundation CoreFoundation) + find_library(iokit IOKit) + find_library(coreServices CoreServices) + find_library(systemConfiguration SystemConfiguration) + target_link_libraries(${target} ${coreFoundation} ${iokit} ${coreServices} ${systemConfiguration} ${lz4} ${SSL_LIBRARY}) + endif() + + if(UNIX) + target_link_libraries(${target} pthread) + endif() + + find_package(LZ4 REQUIRED) + list(APPEND CORE_INCLUDES ${LZ4_INCLUDE_DIR}) + + target_include_directories(${target} PRIVATE ${CORE_INCLUDES}) + target_compile_definitions(${target} PRIVATE ${CORE_DEFINES}) + target_link_libraries(${target} ${SSL_LIBRARY} ${EXTRA_LIBS} ${LZ4_LIBRARY}) +endfunction() \ No newline at end of file diff --git a/cmake/mypragmaonce.cmake b/cmake/mypragmaonce.cmake new file mode 100644 index 0000000..bcc5469 --- /dev/null +++ b/cmake/mypragmaonce.cmake @@ -0,0 +1,8 @@ +macro(my_pragma_once) + set(__filename "${CMAKE_CURRENT_LIST_FILE}") + get_property(already_included GLOBAL PROPERTY "pr_${__filename}") + if(already_included) + return() + endif() + set_property(GLOBAL PROPERTY "pr_${__filename}" TRUE) +endmacro() diff --git a/deps/asio/build-asio b/deps/asio/build-asio new file mode 100755 index 0000000..91d96a8 --- /dev/null +++ b/deps/asio/build-asio @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$DEP_DIR" ]; then + echo DEP_DIR var must point to dependency build folder + exit 1 +fi +if [ -z "$DL" ]; then + echo DL var must point to the download folder + exit 1 +fi + +. $O3/core/deps/lib-versions + +# source helper functions +. $O3/core/deps/functions.sh + +PACKAGE=${ASIO_VERSION} +FNAME=${ASIO_VERSION}.tar.gz +URL=https://github.com/chriskohlhoff/asio/archive/${ASIO_VERSION}.tar.gz +CSUM=${ASIO_CSUM} +DIST=asio + +download + +if [ "$NO_WIPE" = "1" ]; then + echo RETAIN existing source +else + echo WIPE and reunzip source + cd $DEP_DIR + rm -rf $DIST asio-$ASIO_VERSION + tar xfz $DL/$FNAME + cd asio-$ASIO_VERSION + + apply_patches "asio" + + cd .. + + cp -a asio-$ASIO_VERSION $DIST +fi diff --git a/deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch b/deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch new file mode 100644 index 0000000..becea4e --- /dev/null +++ b/deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch @@ -0,0 +1,48 @@ +From 00c0b1b7076ebc24735071f587f9501c1595a02b Mon Sep 17 00:00:00 2001 +From: James Yonan +Date: Mon, 19 Mar 2018 11:24:10 +0800 +Subject: [PATCH] Added Apple NAT64 support when both ASIO_HAS_GETADDRINFO and + ASIO_APPLE_NAT64 ar defined + +* When calling getaddrinfo(), Apple recommends to set + AI_DEFAULT flags in hint. + +* iOS bug workaround: sometimes iOS getaddrinfo() returns a + non-zero scope ID for non-link-local addresses. + Workaround by forcing scope ID to 0 for non-link-local + addresses. +--- + asio/include/asio/detail/impl/socket_ops.ipp | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/asio/include/asio/detail/impl/socket_ops.ipp b/asio/include/asio/detail/impl/socket_ops.ipp +index ad203b74..b17a60ed 100644 +--- a/asio/include/asio/detail/impl/socket_ops.ipp ++++ b/asio/include/asio/detail/impl/socket_ops.ipp +@@ -3339,6 +3339,23 @@ asio::error_code getaddrinfo(const char* host, + # endif + #elif !defined(ASIO_HAS_GETADDRINFO) + int error = getaddrinfo_emulation(host, service, &hints, result); ++ return ec = translate_addrinfo_error(error); ++#elif defined(ASIO_HAS_GETADDRINFO) && defined(ASIO_APPLE_NAT64) ++ // For NAT64 compatibility, Apple recommends to set AI_DEFAULT flags ++ addrinfo_type new_hints = hints; ++ new_hints.ai_flags |= AI_DEFAULT; ++ int error = ::getaddrinfo(host, service, &new_hints, result); ++ ++ // iOS bug workaround: sometimes iOS getaddrinfo() returns a non-zero scope ID ++ // for non-link-local addresses. Workaround by forcing scope ID to 0 for ++ // non-link-local addresses. ++ if (!error && (*result)->ai_family == AF_INET6) ++ { ++ sockaddr_in6* a6 = (sockaddr_in6*)(*result)->ai_addr; ++ if (a6->sin6_scope_id && !(IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&a6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&a6->sin6_addr))) ++ a6->sin6_scope_id = 0; ++ } ++ + return ec = translate_addrinfo_error(error); + #else + int error = ::getaddrinfo(host, service, &hints, result); +-- +2.21.0 + diff --git a/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch b/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch new file mode 100644 index 0000000..18ae1f7 --- /dev/null +++ b/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch @@ -0,0 +1,38 @@ +From fe57c9127cfc95b4673c6530f86edab5e6538425 Mon Sep 17 00:00:00 2001 +From: James Yonan +Date: Wed, 2 Sep 2015 12:18:48 -0700 +Subject: [PATCH] Added randomize() method to + asio::ip::tcp::resolver::results_type. + +--- + asio/include/asio/ip/basic_resolver_results.hpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/asio/include/asio/ip/basic_resolver_results.hpp b/asio/include/asio/ip/basic_resolver_results.hpp +index 3b3fad49..c070f7da 100644 +--- a/asio/include/asio/ip/basic_resolver_results.hpp ++++ b/asio/include/asio/ip/basic_resolver_results.hpp +@@ -18,6 +18,7 @@ + #include "asio/detail/config.hpp" + #include + #include ++#include + #include "asio/detail/socket_ops.hpp" + #include "asio/detail/socket_types.hpp" + #include "asio/ip/basic_resolver_iterator.hpp" +@@ -299,6 +300,12 @@ public: + return !a.equal(b); + } + ++ template ++ void randomize(Random& r) ++ { ++ std::shuffle(this->values_->begin(), this->values_->end(), r); ++ } ++ + private: + typedef std::vector > values_type; + }; +-- +2.21.0 + diff --git a/deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch b/deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch new file mode 100644 index 0000000..de2a100 --- /dev/null +++ b/deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch @@ -0,0 +1,38 @@ +From 80485636d5140c4b45679a4664eb7fe9e09f574f Mon Sep 17 00:00:00 2001 +From: James Yonan +Date: Mon, 27 Feb 2017 13:01:26 -0700 +Subject: [PATCH] Added user code hook async_connect_post_open() to be called + immediately after socket open in async_connect. + +--- + asio/include/asio/basic_socket.hpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/asio/include/asio/basic_socket.hpp b/asio/include/asio/basic_socket.hpp +index 42efbda4..4da85eb6 100644 +--- a/asio/include/asio/basic_socket.hpp ++++ b/asio/include/asio/basic_socket.hpp +@@ -950,6 +950,8 @@ public: + { + const protocol_type protocol = peer_endpoint.protocol(); + impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); ++ if (!open_ec) ++ async_connect_post_open(protocol, open_ec); + } + + return async_initiate( +@@ -1800,6 +1802,11 @@ protected: + #endif + + private: ++ // optional user code hook immediately after socket open in async_connect ++ virtual void async_connect_post_open(const protocol_type& protocol, asio::error_code& ec) ++ { ++ } ++ + // Disallow copying and assignment. + basic_socket(const basic_socket&) ASIO_DELETED; + basic_socket& operator=(const basic_socket&) ASIO_DELETED; +-- +2.21.0 + diff --git a/deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch b/deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch new file mode 100644 index 0000000..81693de --- /dev/null +++ b/deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch @@ -0,0 +1,29 @@ +From af733fe9ce8345e06947dcf8b395d4736b1cb98c Mon Sep 17 00:00:00 2001 +From: Lev Stipakov +Date: Mon, 29 Apr 2019 10:26:13 +0300 +Subject: [PATCH] error_code.ipp: Use English for Windows error messages + +FormatMessageA doesn't work well with non-ASCII chars +so make it return error message in English. + +Signed-off-by: Lev Stipakov +--- + asio/include/asio/impl/error_code.ipp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/asio/include/asio/impl/error_code.ipp b/asio/include/asio/impl/error_code.ipp +index 55f5b361..3ef34fcd 100644 +--- a/asio/include/asio/impl/error_code.ipp ++++ b/asio/include/asio/impl/error_code.ipp +@@ -80,7 +80,7 @@ public: + DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value, +- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); ++ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (char*)&msg, 0, 0); + detail::local_free_on_block_exit local_free_obj(msg); + if (length && msg[length - 1] == '\n') + msg[--length] = '\0'; +-- +2.16.2.windows.1 + diff --git a/deps/asio/snapshot-asio b/deps/asio/snapshot-asio new file mode 100755 index 0000000..2bd3e69 --- /dev/null +++ b/deps/asio/snapshot-asio @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +export NAME=asio +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +$DIR/../../scripts/snapshot diff --git a/deps/boost/atomic-1.55.0.patch b/deps/boost/atomic-1.55.0.patch new file mode 100644 index 0000000..021ee81 --- /dev/null +++ b/deps/boost/atomic-1.55.0.patch @@ -0,0 +1,87 @@ +--- boost/atomic/detail/cas128strong.hpp ++++ boost/atomic/detail/cas128strong.hpp +@@ -196,15 +196,17 @@ class base_atomic + + public: + BOOST_DEFAULTED_FUNCTION(base_atomic(void), {}) +- explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0) ++ explicit base_atomic(value_type const& v) BOOST_NOEXCEPT + { ++ memset(&v_, 0, sizeof(v_)); + memcpy(&v_, &v, sizeof(value_type)); + } + + void + store(value_type const& value, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { +- storage_type value_s = 0; ++ storage_type value_s; ++ memset(&value_s, 0, sizeof(value_s)); + memcpy(&value_s, &value, sizeof(value_type)); + platform_fence_before_store(order); + platform_store128(value_s, &v_); +@@ -247,7 +249,9 @@ class base_atomic + memory_order success_order, + memory_order failure_order) volatile BOOST_NOEXCEPT + { +- storage_type expected_s = 0, desired_s = 0; ++ storage_type expected_s, desired_s; ++ memset(&expected_s, 0, sizeof(expected_s)); ++ memset(&desired_s, 0, sizeof(desired_s)); + memcpy(&expected_s, &expected, sizeof(value_type)); + memcpy(&desired_s, &desired, sizeof(value_type)); + +--- boost/atomic/detail/gcc-atomic.hpp ++++ boost/atomic/detail/gcc-atomic.hpp +@@ -958,14 +958,16 @@ class base_atomic + + public: + BOOST_DEFAULTED_FUNCTION(base_atomic(void), {}) +- explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0) ++ explicit base_atomic(value_type const& v) BOOST_NOEXCEPT + { ++ memset(&v_, 0, sizeof(v_)); + memcpy(&v_, &v, sizeof(value_type)); + } + + void store(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { +- storage_type tmp = 0; ++ storage_type tmp; ++ memset(&tmp, 0, sizeof(tmp)); + memcpy(&tmp, &v, sizeof(value_type)); + __atomic_store_n(&v_, tmp, atomics::detail::convert_memory_order_to_gcc(order)); + } +@@ -980,7 +982,8 @@ class base_atomic + + value_type exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { +- storage_type tmp = 0; ++ storage_type tmp; ++ memset(&tmp, 0, sizeof(tmp)); + memcpy(&tmp, &v, sizeof(value_type)); + tmp = __atomic_exchange_n(&v_, tmp, atomics::detail::convert_memory_order_to_gcc(order)); + value_type res; +@@ -994,7 +997,9 @@ class base_atomic + memory_order success_order, + memory_order failure_order) volatile BOOST_NOEXCEPT + { +- storage_type expected_s = 0, desired_s = 0; ++ storage_type expected_s, desired_s; ++ memset(&expected_s, 0, sizeof(expected_s)); ++ memset(&desired_s, 0, sizeof(desired_s)); + memcpy(&expected_s, &expected, sizeof(value_type)); + memcpy(&desired_s, &desired, sizeof(value_type)); + const bool success = __atomic_compare_exchange_n(&v_, &expected_s, desired_s, false, +@@ -1010,7 +1015,9 @@ class base_atomic + memory_order success_order, + memory_order failure_order) volatile BOOST_NOEXCEPT + { +- storage_type expected_s = 0, desired_s = 0; ++ storage_type expected_s, desired_s; ++ memset(&expected_s, 0, sizeof(expected_s)); ++ memset(&desired_s, 0, sizeof(desired_s)); + memcpy(&expected_s, &expected, sizeof(value_type)); + memcpy(&desired_s, &desired, sizeof(value_type)); + const bool success = __atomic_compare_exchange_n(&v_, &expected_s, desired_s, true, +-- diff --git a/deps/boost/build-boost b/deps/boost/build-boost new file mode 100755 index 0000000..fcd10e5 --- /dev/null +++ b/deps/boost/build-boost @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# +# Parameters: +# SDK_PATH_SCRIPT -- optional script to set SDK path + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$TARGETS" ]; then + echo TARGETS var must be defined + exit 1 +fi + +# NOTE: in Boost 1.55 and earlier, set BCONF=tools/build/v2 +BCONF=tools/build/src + +. $O3/core/deps/lib-versions +[ -z "$DL" ] && DL=~/Downloads +[ -z "$GPP_CMD" ] && export GPP_CMD=g++ +[ -z "$GCC_CMD" ] && export GCC_CMD=gcc +if [ "$NO_WIPE" != "1" ]; then + echo WIPE and reunzip source + rm -rf boost $BOOST_VERSION + mkdir boost + tar xfz $DL/$BOOST_VERSION.tar.gz + cd $BOOST_VERSION + #patch -p1 <$DL/asio-engine.patch + #patch -p0 <$O3/core/deps/boost/atomic-1.55.0.patch + patch -p1 <$O3/core/deps/boost/intrusive_ptr.patch + patch -p1 <$O3/core/deps/boost/page_size.patch + + ./bootstrap.sh + + for T in $TARGETS ; do + TS="${T//-/}" + . $O3/core/vars/vars-$T + cat >>$BCONF/user-config.jam <"-Wno-unused-function $PLATFORM_FLAGS $CXX_COMPILER_FLAGS $OTHER_COMPILER_FLAGS $LIB_FPIC $LIB_OPT_LEVEL" + ; +EOF + done + echo '********** BOOST CONFIG' + tail -30 $BCONF/user-config.jam + echo '********** END BOOST CONFIG' +else + echo RETAIN existing source + cd $BOOST_VERSION + for T in $TARGETS ; do + TS="${T//-/}" + . $O3/core/vars/vars-$T + done +fi +[ "$SDK_PATH_SCRIPT" ] && . $SDK_PATH_SCRIPT +for T in $TARGETS ; do + . $O3/core/vars/vars-$T + target="${T//-/}" + stage=stage-$T + if [ "${target:(-3)}" == "dbg" ]; then + variant=debug + else + variant=release + fi + [ -z "$LINK_MODE" ] && LINK_MODE=static + echo "************************ $target $variant $stage" + cmd="./bjam -d2 toolset=${GCC_CMD}-${target} --stagedir=$stage --with-system --with-thread --with-atomic variant=$variant link=$LINK_MODE threading=multi runtime-link=$LINK_MODE" + echo $cmd + $cmd +done +mv stage-* ../boost/ +cp -a boost ../boost/ +exit 0 diff --git a/deps/boost/intrusive_ptr.patch b/deps/boost/intrusive_ptr.patch new file mode 100644 index 0000000..19717d9 --- /dev/null +++ b/deps/boost/intrusive_ptr.patch @@ -0,0 +1,29 @@ +diff -ur boost_1_56_0.orig/boost/smart_ptr/intrusive_ptr.hpp boost_1_56_0/boost/smart_ptr/intrusive_ptr.hpp +--- boost_1_56_0.orig/boost/smart_ptr/intrusive_ptr.hpp 2014-07-26 00:44:34.000000000 -0600 ++++ boost_1_56_0/boost/smart_ptr/intrusive_ptr.hpp 2014-08-15 19:51:11.000000000 -0600 +@@ -63,7 +63,7 @@ + { + } + +- intrusive_ptr( T * p, bool add_ref = true ): px( p ) ++ intrusive_ptr( T * p, bool add_ref = true ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(intrusive_ptr_add_ref(static_cast(nullptr)))) : px( p ) + { + if( px != 0 && add_ref ) intrusive_ptr_add_ref( px ); + } +@@ -80,14 +80,14 @@ + intrusive_ptr( intrusive_ptr const & rhs ) + + #endif +- : px( rhs.get() ) ++ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(intrusive_ptr_add_ref(static_cast(nullptr)))) : px( rhs.get() ) + { + if( px != 0 ) intrusive_ptr_add_ref( px ); + } + + #endif + +- intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px ) ++ intrusive_ptr(intrusive_ptr const & rhs) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(intrusive_ptr_add_ref(static_cast(nullptr)))) : px( rhs.px ) + { + if( px != 0 ) intrusive_ptr_add_ref( px ); + } diff --git a/deps/boost/page_size.patch b/deps/boost/page_size.patch new file mode 100644 index 0000000..077015f --- /dev/null +++ b/deps/boost/page_size.patch @@ -0,0 +1,16 @@ +diff -ur boost_1_57_0/boost/thread/pthread/thread_data.hpp boost_1_57_0.new/boost/thread/pthread/thread_data.hpp +--- boost_1_57_0/boost/thread/pthread/thread_data.hpp 2014-10-24 10:43:26.000000000 -0600 ++++ boost_1_57_0.new/boost/thread/pthread/thread_data.hpp 2015-02-26 00:43:26.000000000 -0700 +@@ -24,8 +24,10 @@ + #include + #include + +-#if defined(__ANDROID__) +-#include // http://code.google.com/p/android/issues/detail?id=39983 ++// JY modified ++#if defined(__ANDROID__) && !defined(PAGE_SIZE) ++#define PAGE_SIZE 4096 ++//#include // http://code.google.com/p/android/issues/detail?id=39983 + #endif + + #include diff --git a/deps/cityhash/build-cityhash b/deps/cityhash/build-cityhash new file mode 100755 index 0000000..d5835f6 --- /dev/null +++ b/deps/cityhash/build-cityhash @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$DEP_DIR" ]; then + echo DEP_DIR var must point to dependency build folder + exit 1 +fi +if [ -z "$DL" ]; then + echo DL var must point to the download folder + exit 1 +fi + +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi + +# source vars +. $O3/core/vars/vars-${TARGET} +. $O3/core/deps/lib-versions + +# source helper functions +. $O3/core/deps/functions.sh + +FNAME=cityhash-${CITYHASH_VERSION}.tar.gz +PN=${CITYHASH_VERSION#*-} +URL=https://codeload.github.com/google/cityhash/tar.gz/${CITYHASH_VERSION} +CSUM=${CITYHASH_CSUM} + +download + +CC=cc +LD=ld +AR=ar +RANLIB=ranlib +[ "$GCC_CMD" ] && CC=$GCC_CMD +[ "$LD_CMD" ] && LD=$LD_CMD +[ "$AR_CMD" ] && AR=$AR_CMD +[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD + +if [ "$NO_WIPE" != "1" ]; then + rm -rf $CITYHASH_VERSION + tar xfz $DL/cityhash-$CITYHASH_VERSION.tar.gz +fi + +DIST=$(pwd)/cityhash/cityhash-$PLATFORM +rm -rf $DIST +mkdir -p $DIST/include +mkdir $DIST/lib +cd cityhash-$CITYHASH_VERSION +CMD=./configure +echo $CMD +$CMD +CMD="$CC $PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -I. -Isrc -c src/city.cc" +echo $CMD +$CMD +$AR rc $DIST/lib/libcityhash.a city.o +$RANLIB $DIST/lib/libcityhash.a +cp src/city.h $DIST/include/ +exit 0 diff --git a/deps/functions.sh b/deps/functions.sh new file mode 100644 index 0000000..a9e932b --- /dev/null +++ b/deps/functions.sh @@ -0,0 +1,47 @@ +function check_download() +{ + if [ -f $DL/$FNAME ]; then + CHECK=$(shasum -a 256 $DL/$FNAME |awk '{printf $1};') + if [ "$CHECK" == "$CSUM" ]; then + return 0 + else + echo "Checksum mismatch for $FNAME. Was $CHECK, expected $CSUM" + fi + else + echo "$FNAME not found." + fi + + return -1 +} + +function download() +{ + check_download && return 0 + + rm -f $DL/$FNAME + if [ -n "$URL" ]; then + wget $URL -O $DL/$FNAME + else + echo URL must be specified + exit 1 + fi + + check_download || return -1 +} + +function apply_patches() +{ + DEP_NAME=$1 + + # change directory since git apply got confused when + # applying patches to files which are not found in index + DIR=$(pwd) + pushd ${DIR} + cd /tmp + # apply pre-generated patches + for file in $O3/core/deps/${DEP_NAME}/patches/*.patch; do + echo Applying patch: $file + git apply --directory ${DIR} --unsafe-path $file + done + popd +} diff --git a/deps/lib-versions b/deps/lib-versions new file mode 100644 index 0000000..6e4efab --- /dev/null +++ b/deps/lib-versions @@ -0,0 +1,24 @@ +export ASIO_VERSION=asio-1-14-0 +export ASIO_CSUM=bdb01a649c24d73ca4a836662e7af442d935313ed6deef6b07f17f3bc5f78d7a + +export LZ4_VERSION=lz4-1.8.3 +export LZ4_CSUM=33af5936ac06536805f9745e0b6d61da606a1f8b4cc5c04dd3cbaca3b9b4fc43 + +export MBEDTLS_VERSION=mbedtls-2.7.12 +export MBEDTLS_CSUM=d3a36dbc9f607747daa6875c1ab2e41f49eff5fc99d3436b4f3ac90c89f3c143 + +export JSONCPP_VERSION=1.8.4 +export JSONCPP_CSUM=c49deac9e0933bcb7044f08516861a2d560988540b23de2ac1ad443b219afdb6 + +export TAP_VERSION=0e30f5c13b3c7b0bdd60da915350f653e4c14d92 +export TAP_CSUM=8ff65f9e741c5ecfe1af904eaa38713f05639ce9457ef92041fd8e6b2a170315 + +export CITYHASH_VERSION=8af9b8c2b889d80c22d6bc26ba0df1afb79a30db +export CITYHASH_CSUM=f70368facd15735dffc77fe2b27ab505bfdd05be5e9166d94149a8744c212f49 + +export LZO_VERSION=lzo-2.10 +export LZO_CSUM=c0f892943208266f9b6543b3ae308fab6284c5c90e627931446fb49b4221a072 + +export OPENSSL_VERSION=openssl-1.1.1d +export OPENSSL_CSUM=1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2 + diff --git a/deps/lz4/build-lz4 b/deps/lz4/build-lz4 new file mode 100755 index 0000000..53777d0 --- /dev/null +++ b/deps/lz4/build-lz4 @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$DEP_DIR" ]; then + echo DEP_DIR var must point to dependency build folder + exit 1 +fi +if [ -z "$DL" ]; then + echo DL var must point to the download folder + exit 1 +fi + +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi + +# source vars +. $O3/core/vars/vars-${TARGET} +. $O3/core/deps/lib-versions + +# source helper functions +. $O3/core/deps/functions.sh + +FNAME=${LZ4_VERSION}.tar.gz +PN=${LZ4_VERSION#*-} +URL=https://github.com/lz4/lz4/archive/v${PN}.tar.gz +CSUM=${LZ4_CSUM} + +download + +CC=cc +LD=ld +AR=ar +RANLIB=ranlib +[ "$GCC_CMD" ] && CC=$GCC_CMD +[ "$LD_CMD" ] && LD=$LD_CMD +[ "$AR_CMD" ] && AR=$AR_CMD +[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD + +if [ "$NO_WIPE" != "1" ]; then + rm -rf $LZ4_VERSION + tar xfz $DL/$LZ4_VERSION.tar.gz +fi + +if [ "x$NO_BUILD" == x1 ]; then + echo "Not building" + exit +fi + +DIST=$(pwd)/lz4/lz4-$PLATFORM +rm -rf $DIST +mkdir -p $DIST/include +mkdir $DIST/lib +cd $LZ4_VERSION/lib +CMD="$CC $PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -c lz4.c" +echo $CMD +$CMD +$AR rc $DIST/lib/liblz4.a lz4.o +$RANLIB $DIST/lib/liblz4.a +cp lz4.h $DIST/include/ +exit 0 diff --git a/deps/lz4/snapshot-lz4 b/deps/lz4/snapshot-lz4 new file mode 100755 index 0000000..1074081 --- /dev/null +++ b/deps/lz4/snapshot-lz4 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +export NAME=lz4 +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +$DIR/../../scripts/snapshot diff --git a/deps/lzo/build-lzo b/deps/lzo/build-lzo new file mode 100755 index 0000000..df96fb7 --- /dev/null +++ b/deps/lzo/build-lzo @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$DEP_DIR" ]; then + echo DEP_DIR var must point to dependency build folder + exit 1 +fi +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi + +[ -z "$DL" ] && DL=~/Downloads + +# source vars +. $O3/core/vars/vars-${TARGET} +. $O3/core/deps/lib-versions + +# source helper functions +. $O3/core/deps/functions.sh + +FNAME=${LZO_VERSION}.tar.gz +PN=${LZO_VERSION#*-} +URL=http://www.oberhumer.com/opensource/lzo/download/${LZO_VERSION}.tar.gz +CSUM=${LZO_CSUM} + +download + +CC=cc +LD=ld +AR=ar +RANLIB=ranlib +[ "$GCC_CMD" ] && CC=$GCC_CMD +[ "$LD_CMD" ] && LD=$LD_CMD +[ "$AR_CMD" ] && AR=$AR_CMD +[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD + +case $PLATFORM in +android*) + echo PLATFORM android + host=arm + target=arm + ;; +ios*) + echo PLATFORM ios + host="x86_64-apple-darwin" + target=arm + ;; +*) + host="" + target="" + ;; +esac + +if [ "$target" ]; then + targ_opt="--target=$target" +fi + +if [ "$host" ]; then + host_opt="--host=$host" +fi + +if [ "$NO_WIPE" != "1" ]; then + rm -rf $LZO_VERSION + tar xfz $DL/$LZO_VERSION.tar.gz +fi + +DIST=$(pwd)/lzo/lzo-$PLATFORM +rm -rf $DIST +mkdir -p $DIST +cd $LZO_VERSION +echo 'OPTIONS' $CC $LD $AR $RANLIB $host_opt $targ_opt +CFLAGS="$PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC" ./configure --prefix=$DIST $host_opt $targ_opt +make +make install +exit 0 diff --git a/deps/mbedtls/build-mbedtls b/deps/mbedtls/build-mbedtls new file mode 100755 index 0000000..a962ad9 --- /dev/null +++ b/deps/mbedtls/build-mbedtls @@ -0,0 +1,102 @@ +#!/bin/bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$DEP_DIR" ]; then + echo DEP_DIR var must point to dependency build folder + exit 1 +fi +if [ -z "$DL" ]; then + echo DL var must point to the download folder + exit 1 +fi + +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi + +# source vars +. $O3/core/vars/vars-${TARGET} +. $O3/core/deps/lib-versions + +# source helper functions +. $O3/core/deps/functions.sh + +FNAME=${MBEDTLS_VERSION}-apache.tgz +PN=${MBEDTLS_VERSION#*-} +URL=https://tls.mbed.org/download/$MBEDTLS_VERSION-apache.tgz +CSUM=${MBEDTLS_CSUM} + +download + +# put build targets here +DIST=$(pwd)/mbedtls/mbedtls-$PLATFORM +rm -rf $DIST +mkdir -p $DIST + +if [ "$NO_WIPE" = "1" ]; then + echo RETAIN existing source + cd $MBEDTLS_VERSION +else + echo WIPE and reunzip source + rm -rf $MBEDTLS_VERSION + [ -z "$DL" ] && DL=~/Downloads + tar xfz $DL/$MBEDTLS_VERSION-apache.tgz + cd $MBEDTLS_VERSION + + # enable MD4 (needed for NTLM auth) + perl -pi -e 's/^\/\/// if /#define MBEDTLS_MD4_C/' include/mbedtls/config.h + + apply_patches "mbedtls" +fi + +if [ "x$NO_BUILD" == x1 ]; then + echo "Not building" + exit 0 +fi + +if [[ "x$TARGET" == xlinux* || "x$TARGET" == xosx* ]]; then + # run unit tests and then clean + echo RUNNING CHECK + make check + echo CLEANING + make clean +fi + +echo BUILDING + +# compiler vars +CC=cc +LD=ld +AR=ar +RANLIB=ranlib +[ "$GCC_CMD" ] && CC=$GCC_CMD +[ "$LD_CMD" ] && LD=$LD_CMD +[ "$AR_CMD" ] && AR=$AR_CMD +[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD + +# build it +SRC=$(pwd) +cd library +rm -f *.o +for c in *.c ; do + CMD="$CC -I../include -DMBEDTLS_RELAXED_X509_DATE \ + $PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -c $c" + echo $CMD + $CMD +done + +# create archive +cd $DIST +mkdir library +$AR rc library/libmbedtls.a $SRC/library/*.o +$RANLIB library/libmbedtls.a 2>&1 | grep -v "has no symbols" || true + +# copy headers +mkdir -p include/mbedtls +cp $SRC/include/mbedtls/*.h include/mbedtls/ +exit 0 diff --git a/deps/mbedtls/patches/0001-relax-x509-date-format-check.patch b/deps/mbedtls/patches/0001-relax-x509-date-format-check.patch new file mode 100644 index 0000000..d5406e9 --- /dev/null +++ b/deps/mbedtls/patches/0001-relax-x509-date-format-check.patch @@ -0,0 +1,55 @@ +From 0554efae4e27b6a764def80f600394519ef1addb Mon Sep 17 00:00:00 2001 +From: Antonio Quartulli +Date: Tue, 20 Mar 2018 09:35:47 +0800 +Subject: [PATCH 1/2] relax x509 date format check + +Signed-off-by: Antonio Quartulli +--- + library/x509.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/library/x509.c b/library/x509.c +index 264c7fb0c..9372bcb92 100644 +--- a/library/x509.c ++++ b/library/x509.c +@@ -556,13 +556,20 @@ static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + /* + * Parse seconds if present + */ +- if ( len >= 2 ) ++ if ( len >= 2 && **p >= '0' && **p <= '9' ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else ++ { ++#if defined(MBEDTLS_RELAXED_X509_DATE) ++ /* if relaxed mode, allow seconds to be absent */ ++ tm->sec = 0; ++#else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); ++#endif ++ } + + /* + * Parse trailing 'Z' if present +@@ -572,6 +579,15 @@ static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + (*p)++; + len--; + } ++#if defined(MBEDTLS_RELAXED_X509_DATE) ++ else if ( len == 5 && **p == '+' ) ++ { ++ int tz; /* throwaway timezone */ ++ (*p)++; ++ CHECK( x509_parse_int( p, 4, &tz ) ); ++ return 0; ++ } ++#endif + + /* + * We should have parsed all characters at this point +-- +2.18.0 + diff --git a/deps/mbedtls/patches/0002-Enable-allowing-unsupported-critical-extensions-in-r.patch b/deps/mbedtls/patches/0002-Enable-allowing-unsupported-critical-extensions-in-r.patch new file mode 100644 index 0000000..f7f8f00 --- /dev/null +++ b/deps/mbedtls/patches/0002-Enable-allowing-unsupported-critical-extensions-in-r.patch @@ -0,0 +1,361 @@ +From 076f1437fe82de0b1f0ecf9a7ca031cd94c0c579 Mon Sep 17 00:00:00 2001 +From: Lev Stipakov +Date: Fri, 23 Feb 2018 17:12:49 +0200 +Subject: [PATCH] Enable allowing unsupported critical extensions in runtime + +When compile time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +is not set, certificate parsing fails if certificate contains unsupported critical extension. + +This patch allows to modify this behavior in runtime. + +Signed-off-by: Lev Stipakov +--- + include/mbedtls/oid.h | 13 +++- + include/mbedtls/ssl.h | 22 ++++++ + include/mbedtls/x509_crt.h | 2 + + library/oid.c | 81 ++++++++++++++++++---- + library/ssl_tls.c | 8 +++ + library/x509_crt.c | 10 ++- + tests/data_files/test-ca-nc.crt | 20 ++++++ + tests/suites/test_suite_x509parse.data | 6 ++ + tests/suites/test_suite_x509parse.function | 15 ++++ + 9 files changed, 162 insertions(+), 15 deletions(-) + create mode 100644 tests/data_files/test-ca-nc.crt + +diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h +index 408645ece..b116736f8 100644 +--- a/include/mbedtls/oid.h ++++ b/include/mbedtls/oid.h +@@ -410,7 +410,7 @@ int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_b + + #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + /** +- * \brief Translate an X.509 extension OID into local values ++ * \brief Translate supported X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type +@@ -418,6 +418,17 @@ int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_b + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ + int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); ++ ++/** ++ * \brief Translate supported and unsupported X.509 extension OID into local values ++ * ++ * \param oid OID to use ++ * \param ext_type place to store the extension type ++ * \param is_supported place to store flag if extension is supported (1 - supported, 0 otherwise) ++ * ++ * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND ++ */ ++int mbedtls_oid_get_x509_ext_type_supported( const mbedtls_asn1_buf *oid, int *ext_type, int *is_supported ); + #endif + + /** +diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h +index 5fd6969da..1087ea166 100644 +--- a/include/mbedtls/ssl.h ++++ b/include/mbedtls/ssl.h +@@ -696,6 +696,10 @@ struct mbedtls_ssl_config + retransmission timeout (ms) */ + #endif + ++ uint32_t allowed_unsupported_critical_exts; /*!< Bit flags which represent runtime-enabled ++ unsupported critical extensions, e.g. ++ MBEDTLS_X509_EXT_NAME_CONSTRAINTS */ ++ + #if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters +@@ -2298,6 +2302,24 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ); + #endif /* MBEDTLS_SSL_RENEGOTIATION */ + ++/** ++ * \brief Allows unsupported critical extensions ++ * ++ * Without compile-time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION ++ * mbedTLS fails certificate verification if certificate contains ++ * unsupported critical extensions. ++ * ++ * This method allows to modify behavior in runtime by providing ++ * bit flags which represent unsupported extensions (for example MBEDTLS_X509_EXT_NAME_CONSTRAINTS) ++ * which should be allowed despite missing above mentioned compile-time flag. ++ * ++ * \param conf SSL configuration ++ * \param exts Bit flags which represent runtime-enabled unsupported critical extensions, ++ * e.g. MBEDTLS_X509_EXT_NAME_CONSTRAINTS ++ * ++ */ ++void mbedtls_ssl_conf_allow_unsupported_critical_exts( mbedtls_ssl_config *conf, uint32_t exts ); ++ + /** + * \brief Return the number of data bytes available to read + * +diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h +index e72231ee8..9df19e52c 100644 +--- a/include/mbedtls/x509_crt.h ++++ b/include/mbedtls/x509_crt.h +@@ -90,6 +90,8 @@ typedef struct mbedtls_x509_crt + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + ++ uint32_t allowed_unsupported_critical_exts; /**< Optional Bit flags which represent runtime-enabled unsupported critical extensions, e.g. MBEDTLS_X509_EXT_NAME_CONSTRAINTS */ ++ + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ + } + mbedtls_x509_crt; +diff --git a/library/oid.c b/library/oid.c +index edea950f8..a756d2801 100644 +--- a/library/oid.c ++++ b/library/oid.c +@@ -254,38 +254,95 @@ FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, co + typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; ++ int is_supported; + } oid_x509_ext_t; + + static const oid_x509_ext_t oid_x509_ext[] = + { + { +- { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, +- MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, ++ { ADD_LEN( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), "id-ce-authorityKeyIdentifier", "Authority Key Identifier" }, ++ MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER, 0, + }, + { +- { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, +- MBEDTLS_X509_EXT_KEY_USAGE, ++ { ADD_LEN( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), "id-ce-subjectKeyIdentifier", "Subject Key Identifier" }, ++ MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER, 0, + }, + { +- { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, +- MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, ++ { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, ++ MBEDTLS_X509_EXT_KEY_USAGE, 1, + }, + { +- { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, +- MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, ++ { ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" }, ++ MBEDTLS_X509_EXT_CERTIFICATE_POLICIES, 0, + }, + { +- { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, +- MBEDTLS_X509_EXT_NS_CERT_TYPE, ++ { ADD_LEN( MBEDTLS_OID_POLICY_MAPPINGS ), "id-ce-policyMappings", "Policy Mapping" }, ++ MBEDTLS_X509_EXT_POLICY_MAPPINGS, 0, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_ISSUER_ALT_NAME ), "id-ce-issuerAltName", "Issuer Alt Name" }, ++ MBEDTLS_X509_EXT_ISSUER_ALT_NAME, 0, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS ), "id-ce-subjectDirectoryAttributes", "Subject Directory Attributes" }, ++ MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS, 0, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, ++ MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, 1, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_NAME_CONSTRAINTS ), "id-ce-nameConstraints", "Name Constraints" }, ++ MBEDTLS_X509_EXT_NAME_CONSTRAINTS, 0, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_POLICY_CONSTRAINTS ), "id-ce-policyConstraints", "Policy Constraints" }, ++ MBEDTLS_X509_EXT_POLICY_CONSTRAINTS, 0, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, ++ MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, 1 ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_CRL_DISTRIBUTION_POINTS ), "id-ce-cRLDistributionPoints", "CRL Distribution Points" }, ++ MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS, 0, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_INIHIBIT_ANYPOLICY ), "id-ce-inhibitAnyPolicy", "Inhibit Any Policy" }, ++ MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY, 0, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_FRESHEST_CRL ), "id-ce-freshestCRL", "Freshest CRL" }, ++ MBEDTLS_X509_EXT_FRESHEST_CRL, 0, ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, ++ MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, 1 ++ }, ++ { ++ { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, ++ MBEDTLS_X509_EXT_NS_CERT_TYPE, 1 + }, + { + { NULL, 0, NULL, NULL }, +- 0, ++ 0, 0 + }, + }; + + FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +-FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) ++FN_OID_GET_ATTR2(mbedtls_oid_get_x509_ext_type_supported, oid_x509_ext_t, x509_ext, int, ext_type, int, is_supported) ++ ++int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ) ++{ ++ int ret = 0; ++ int is_supported = 0; ++ ++ ret = mbedtls_oid_get_x509_ext_type_supported(oid, ext_type, &is_supported); ++ if( is_supported == 0 ) ++ ret = MBEDTLS_ERR_OID_NOT_FOUND; ++ ++ return( ret ); ++} + + static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = + { +diff --git a/library/ssl_tls.c b/library/ssl_tls.c +index 1270ee9b8..2ce3f9b7d 100644 +--- a/library/ssl_tls.c ++++ b/library/ssl_tls.c +@@ -4668,6 +4668,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) + + mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); + ++ ssl->session_negotiate->peer_cert->allowed_unsupported_critical_exts = ++ ssl->conf->allowed_unsupported_critical_exts; ++ + i += 3; + + while( i < ssl->in_hslen ) +@@ -6626,6 +6629,11 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + } + #endif /* MBEDTLS_SSL_RENEGOTIATION */ + ++void mbedtls_ssl_conf_allow_unsupported_critical_exts( mbedtls_ssl_config *conf, uint32_t exts ) ++{ ++ conf->allowed_unsupported_critical_exts = exts; ++} ++ + #if defined(MBEDTLS_SSL_SESSION_TICKETS) + #if defined(MBEDTLS_SSL_CLI_C) + void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) +diff --git a/library/x509_crt.c b/library/x509_crt.c +index 3ad53a715..130b3ad1b 100644 +--- a/library/x509_crt.c ++++ b/library/x509_crt.c +@@ -539,6 +539,7 @@ static int x509_get_crt_ext( unsigned char **p, + int ret; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; ++ int is_supported; + + if( *p == end ) + return( 0 ); +@@ -593,9 +594,9 @@ static int x509_get_crt_ext( unsigned char **p, + /* + * Detect supported extensions + */ +- ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); ++ ret = mbedtls_oid_get_x509_ext_type_supported( &extn_oid, &ext_type, &is_supported ); + +- if( ret != 0 ) ++ if( ( ret != 0 ) || ( is_supported == 0 ) ) + { + /* No parser found, skip extension */ + *p = end_ext_octet; +@@ -603,6 +604,10 @@ static int x509_get_crt_ext( unsigned char **p, + #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { ++ /* Do not fail if extension is found, but unsupported and allowed in runtime */ ++ if( ( ret == 0 ) && ( ext_type & crt->allowed_unsupported_critical_exts ) ) ++ continue; ++ + /* Data is marked as critical: fail */ + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); +@@ -956,6 +961,7 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu + + prev = crt; + mbedtls_x509_crt_init( crt->next ); ++ crt->next->allowed_unsupported_critical_exts = crt->allowed_unsupported_critical_exts; + crt = crt->next; + } + +diff --git a/tests/data_files/test-ca-nc.crt b/tests/data_files/test-ca-nc.crt +new file mode 100644 +index 000000000..7e0c56134 +--- /dev/null ++++ b/tests/data_files/test-ca-nc.crt +@@ -0,0 +1,20 @@ ++-----BEGIN CERTIFICATE----- ++MIIDSzCCAjOgAwIBAgIJAJx/NjT4C4viMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV ++BAMMCExlZXZpQ0E0MB4XDTE4MDEyNzE1MDczMloXDTI4MDEyNTE1MDczMlowEzER ++MA8GA1UEAwwITGVldmlDQTQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB ++AQDWN79RTlyFm5o0LVMSVjc68W0+gtl95xpaaD7IS6gDYjcbGnCwSefiq7y9rtck ++OM1A5Bzhj5+iWbmZStUmeJUhSGgxP/FxuUaAV0fsBGJ5jDrzmbhzDkHsNxDMB2ks ++XFyy4LfODcBs9TXxY43KUKuq/0meiT3WAaZWHMYle9vkQJM2l0RyH4IXHCHiIRwd ++2wntin6T9QOFJOc2ietNb7KsXVne81wb7h9BVMsjCIAsbPpHa+PZQs1xFuxmRxCs ++kpavnMy+SqevHhvqtvbHppcXYtZspTnkVoXWUdx3HHXgZMQKlAWlwyx57xpZBU2g ++qksO+KCLVYOQMN9usmuMOpHHAgMBAAGjgaEwgZ4wHQYDVR0eAQH/BBMwEaAPMA2C ++C2V4YW1wbGUuY29tMB0GA1UdDgQWBBR3T9IilPeRAFfLO8ocg216OBo+6DBDBgNV ++HSMEPDA6gBR3T9IilPeRAFfLO8ocg216OBo+6KEXpBUwEzERMA8GA1UEAwwITGVl ++dmlDQTSCCQCcfzY0+AuL4jAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkq ++hkiG9w0BAQsFAAOCAQEAR086ciNM3ujSQNhhguqFHYGfDRRuAgOk4l7GXIfFa9te ++B2KMLSwP367QaMwFxRrOoDvixIjzbpiiKB3cv+IXqGyfsRJw47XLwGK4FtSsXjst ++m2M8W5iXBQ94XoLj9OKb4ZJWKI930S/PF7uuxICtWttYSoylfyMkiR45+1SLj2eF ++X4EnXK3Q0H42v8LCDFqj9iNQ2WMLwA7kFPB+oOZxkFi2G0F3VuW+JZeBPQCpYdRO ++0kQQ/gIZE6KEdscKHi9y6OfGSeRlDBMADky9NiZy7I3AcspLcmMQh/191/DnooNe ++OwQ6w1HweApjB46bGyILpGUi9MZhvCnoLWg+cN3/wQ== ++-----END CERTIFICATE----- +diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data +index 0fe68cb06..e39f065e2 100644 +--- a/tests/suites/test_suite_x509parse.data ++++ b/tests/suites/test_suite_x509parse.data +@@ -1798,6 +1798,12 @@ X509 File parse (trailing spaces, OK) + depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C + x509parse_crt_file:"data_files/server7_trailing_space.crt":0 + ++X509 File parse (unsupported critical ext Name Constraints, fail) ++x509parse_crt_file:"data_files/test-ca-nc.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ++ ++X509 File parse (allowed unsupported critical ext Name Constraints, ok) ++x509parse_crt_file_allow_exts:"data_files/test-ca-nc.crt":MBEDTLS_X509_EXT_NAME_CONSTRAINTS:0 ++ + X509 Get time (UTC no issues) + depends_on:MBEDTLS_X509_USE_C + x509_get_time:MBEDTLS_ASN1_UTC_TIME:"500101000000Z":0:1950:1:1:0:0:0 +diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function +index 584ee822b..c12a0e0ef 100644 +--- a/tests/suites/test_suite_x509parse.function ++++ b/tests/suites/test_suite_x509parse.function +@@ -448,6 +448,21 @@ exit: + } + /* END_CASE */ + ++/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_FS_IO */ ++void x509parse_crt_file_allow_exts( char *crt_file, int exts, int result ) ++{ ++ mbedtls_x509_crt crt; ++ ++ mbedtls_x509_crt_init( &crt ); ++ crt.allowed_unsupported_critical_exts = exts; ++ ++ TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == result ); ++ ++exit: ++ mbedtls_x509_crt_free( &crt ); ++} ++/* END_CASE */ ++ + /* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */ + void x509parse_crt( char *crt_data, char *result_str, int result ) + { +-- +2.22.0.windows.1 + diff --git a/deps/mbedtls/patches/0003-fix-gcc-android-build.patch b/deps/mbedtls/patches/0003-fix-gcc-android-build.patch new file mode 100644 index 0000000..251de7b --- /dev/null +++ b/deps/mbedtls/patches/0003-fix-gcc-android-build.patch @@ -0,0 +1,13 @@ +Only in mbedtls-2.7.5/include/mbedtls: #bn_mul.h# +diff -ur mbedtls-2.7.5/include/mbedtls/bn_mul.h mbedtls-2.7.5.patch/include/mbedtls/bn_mul.h +--- mbedtls-2.7.5/include/mbedtls/bn_mul.h 2018-07-26 15:33:14.000000000 +0200 ++++ mbedtls-2.7.5.patch/include/mbedtls/bn_mul.h 2018-08-22 14:37:31.000000000 +0200 +@@ -56,7 +56,7 @@ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +-#if defined(__i386__) && defined(__OPTIMIZE__) ++#if defined(__i386__) && defined(__OPTIMIZE__) && (!defined(__ANDROID_API__) || defined(__clang__)) + + #define MULADDC_INIT \ + asm( \ diff --git a/deps/minicrypto/aes-armv4.pl.patch b/deps/minicrypto/aes-armv4.pl.patch new file mode 100644 index 0000000..8578ec9 --- /dev/null +++ b/deps/minicrypto/aes-armv4.pl.patch @@ -0,0 +1,32 @@ +--- aes-armv4.pl.orig 2012-09-03 00:16:20.000000000 -0600 ++++ aes-armv4.pl 2012-09-03 00:17:22.000000000 -0600 +@@ -171,7 +170,8 @@ + stmdb sp!,{r1,r4-r12,lr} + mov $rounds,r0 @ inp + mov $key,r2 +- sub $tbl,r3,#AES_encrypt-AES_Te @ Te ++ad1=AES_encrypt-AES_Te ++ sub $tbl,r3,#ad1 @ Te + #if __ARM_ARCH__<7 + ldrb $s0,[$rounds,#3] @ load input data in endian-neutral + ldrb $t1,[$rounds,#2] @ manner... +@@ -426,7 +426,8 @@ + bne .Labrt + + .Lok: stmdb sp!,{r4-r12,lr} +- sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 ++ad2=_armv4_AES_set_encrypt_key-AES_Te-1024 ++ sub $tbl,r3,#ad2 @ Te4 + + mov $rounds,r0 @ inp + mov lr,r1 @ bits +@@ -887,7 +888,8 @@ + stmdb sp!,{r1,r4-r12,lr} + mov $rounds,r0 @ inp + mov $key,r2 +- sub $tbl,r3,#AES_decrypt-AES_Td @ Td ++ad3=AES_decrypt-AES_Td ++ sub $tbl,r3,#ad3 @ Td + #if __ARM_ARCH__<7 + ldrb $s0,[$rounds,#3] @ load input data in endian-neutral + ldrb $t1,[$rounds,#2] @ manner... diff --git a/deps/minicrypto/arm-as-to-ios b/deps/minicrypto/arm-as-to-ios new file mode 100755 index 0000000..0fe6d06 --- /dev/null +++ b/deps/minicrypto/arm-as-to-ios @@ -0,0 +1,759 @@ +#!/usr/bin/env python +# +# arm-as-to-ios Modify ARM assembly code for the iOS assembler +# +# Copyright (c) 2012 Psellos http://psellos.com/ +# Licensed under the MIT License: +# http://www.opensource.org/licenses/mit-license.php +# +# Resources for running OCaml on iOS: http://psellos.com/ocaml/ +# +import sys +import re + +VERSION = '1.4.0' + +initial_glosyms = [] +initial_defsyms = [] + +# Character classes for expression lexing. +# +g_ccid0 = '[$.A-Z_a-z\x80-\xff]' # Beginning of id +g_ccid = '[$.0-9A-Z_a-z\x80-\xff]' # Later in id +def ccc(cc): # Complement the class + if cc[1] == '^': + return cc[0] + cc[2:] + return cc[0] + '^' + cc[1:] +def ccce(cc): # Complement the class, include EOL + return '(?:' + ccc(cc) + '|$)' + +# Prefixes for pooled symbol labels and jump table base labels. They're +# in the space of Linux assembler local symbols. Later rules will +# modify them to the Loc() form. +# +g_poolpfx = '.LP' +g_basepfx = '.LB' + + +def exists(p, l): + for l1 in l: + if p(l1): + return True + return False + + +def forall(p, l): + for l1 in l: + if not p(l1): + return False + return True + + +def add_prefix(instrs): + # Add compatibility macros for all systems, plus hardware + # definitions and compatibility macros for iOS. + # + # All systems: + # + # Glo() cpp macro for making global symbols (xxx vs _xxx) + # Loc() cpp macro for making local symbols (.Lxxx vs Lxxx) + # .funtype Expands to .thumb_func for iOS armv7 (null for armv6) + # Expands to .type %function for others + # + # iOS: + # + # .machine armv6/armv7 + # .thumb (for armv7) + # cbz Expands to cmp/beq for armv6 (Thumb-only instr) + # .type Not supported by Apple assembler + # .size Not supported by Apple assembler + # + defre = '#[ \t]*if.*def.*SYS' # Add new defs near first existing ones + skipre = '$|\.syntax[ \t]' # Skip comment lines (and .syntax) + + for i in range(len(instrs)): + if re.match(defre, instrs[i][1]): + break + else: + i = 0 + for i in range(i, len(instrs)): + if not re.match(skipre, instrs[i][1]): + break + instrs[i:0] = [ + ('', '', '\n'), + ('/* Apple compatibility macros */', '', '\n'), + ('', '#if defined(SYS_macosx)', '\n'), + ('', '#define Glo(s) _##s', '\n'), + ('', '#define Loc(s) L##s', '\n'), + ('', '#if defined(MODEL_armv6)', '\n'), + (' ', '.machine armv6', '\n'), + (' ', '.macro .funtype', '\n'), + (' ', '.endm', '\n'), + (' ', '.macro cbz', '\n'), + (' ', 'cmp $0, #0', '\n'), + (' ', 'beq $1', '\n'), + (' ', '.endm', '\n'), + ('', '#else', '\n'), + (' ', '.machine armv7', '\n'), + ('', '#if !defined(NO_THUMB)', '\n'), + (' ', '.thumb', '\n'), + ('', '#endif', '\n'), + (' ', '.macro .funtype', '\n'), + ('', '#if !defined(NO_THUMB)', '\n'), + (' ', '.thumb_func $0', '\n'), + ('', '#endif', '\n'), + (' ', '.endm', '\n'), + ('', '#endif', '\n'), + (' ', '.macro .type', '\n'), + (' ', '.endm', '\n'), + (' ', '.macro .size', '\n'), + (' ', '.endm', '\n'), + (' ', '.macro .skip', '\n'), + (' ', '.space $0', '\n'), + (' ', '.endm', '\n'), + (' ', '.macro .fpu', '\n'), + (' ', '.endm', '\n'), + (' ', '.macro .global', '\n'), + (' ', '.globl $0', '\n'), + (' ', '.endm', '\n'), + ('', '#else', '\n'), + ('', '#define Glo(s) s', '\n'), + ('', '#define Loc(s) .L##s', '\n'), + (' ', '.macro .funtype symbol', '\n'), + (' ', '.type \\symbol, %function', '\n'), + (' ', '.endm', '\n'), + ('', '#endif', '\n'), + ('/* End Apple compatibility macros */', '', '\n'), + ('', '', '\n') + ] + return instrs + + +# Regular expression for modified ldr lines +# +g_ldre = '(ldr[ \t][^,]*,[ \t]*)=(([^ \t\n@,/]|/(?!\*))*)(.*)' + + +def explicit_address_loads(instrs): + # Linux assemblers allow the following: + # + # ldr rM, =symbol + # + # which loads rM with [mov] (immediately) if possible, or creates an + # entry in memory for the symbol value and loads it PC-relatively + # with [ldr]. + # + # The Apple assembler doesn't seem to support this notation. If the + # value is a suitable constant, it emits a valid [mov]. Otherwise + # it seems to emit an invalid [ldr] that always generates an error. + # (At least I have not been able to make it work). So, change uses + # of =symbol to explicit PC-relative loads. + # + # This requires a pool containing the addresses to be loaded. For + # now, we just keep track of it ourselves and emit it into the text + # segment at the end of the file. + # + syms = {} + result = [] + + def repl1((syms, result), (a, b, c)): + global g_poolpfx + global g_ldre + (b1, b2, b3) = parse_iparts(b) + mo = re.match(g_ldre, b3, re.DOTALL) + if mo: + if mo.group(2) not in syms: + syms[mo.group(2)] = len(syms) + psym = mo.group(2) + if psym[0:2] == '.L': + psym = psym[2:] + newb3 = mo.group(1) + g_poolpfx + psym + mo.group(4) + result.append((a, b1 + b2 + newb3, c)) + else: + result.append((a, b, c)) + return (syms, result) + + def pool1(result, s): + global g_poolpfx + psym = s + if psym[0:2] == '.L': + psym = psym[2:] + result.append(('', g_poolpfx + psym + ':', '\n')) + result.append((' ', '.long ' + s, '\n')) + return result + + reduce(repl1, instrs, (syms, result)) + if len(syms) > 0: + result.append(('', '', '\n')) + result.append(('/* Pool of addresses loaded into registers */', + '', '\n')) + result.append(('', '', '\n')) + result.append((' ', '.text', '\n')) + result.append((' ', '.align 2', '\n')) + reduce(pool1, sorted(syms, key=syms.get), result) + return result + + +def global_symbols(instrs): + # The form of a global symbol differs between Linux assemblers and + # the Apple assember: + # + # Linux: xxx + # Apple: _xxx + # + # Change occurrences of global symbols to use the Glo() cpp macro + # defined in our prefix. + # + # We consider a symbol to be global if: + # + # a. It appears in a .globl declaration; or + # b. It is referenced, has global form, and is not defined + # + glosyms = set(initial_glosyms) + refsyms = set() + defsyms = set(initial_defsyms) + result = [] + + def findglo1 (glosyms, (a, b, c)): + if re.match('#', b): + # Preprocessor line; nothing to do + return glosyms + (b1, b2, b3) = parse_iparts(b) + mo = re.match('(\.globa?l)' + ccce(g_ccid), b3) + if mo: + tokens = parse_expr(b3[len(mo.group(1)):]) + if forall(lambda t: token_type(t) in ['space', 'id', ','], tokens): + for t in tokens: + if token_type(t) == 'id': + glosyms.add(t) + return glosyms + + def findref1 ((refsyms, skipct), (a, b, c)): + + def looksglobal(s): + if re.match('(r|a|v|p|c|cr|f|s|d|q|mvax|wcgr)[0-9]+$', s, re.I): + return False # numbered registers + if re.match('(wr|sb|sl|fp|ip|sp|lr|pc)$', s, re.I): + return False # named registers + if re.match('(fpsid|fpscr|fpexc|mvfr1|mvfr0)$', s, re.I): + return False # more named registers + if re.match('(mvf|mvd|mvfx|mvdx|dspsc)$', s, re.I): + return False # even more named registers + if re.match('(wcid|wcon|wcssf|wcasf|acc)$', s, re.I): + return False # even more named registers + if re.match('\.$|\.L|[0-9]|#', s): + return False # dot, local symbol, or number + if re.match('(asl|lsl|lsr|asr|ror|rrx)$', s, re.I): + return False # shift names + return True + + if re.match('#', b): + # Preprocessor line; nothing to do + return (refsyms, skipct) + + # Track nesting of .macro/.endm. For now, we don't look for + # global syms in macro defs. (Avoiding scoping probs etc.) + # + if skipct > 0 and re.match('\.(endm|endmacro)' + ccce(g_ccid), b): + return (refsyms, skipct - 1) + if re.match('\.macro' + ccce(g_ccid), b): + return (refsyms, skipct + 1) + if skipct > 0: + return (refsyms, skipct) + if re.match('\.(type|size|syntax|arch|fpu)' + ccce(g_ccid), b): + return (refsyms, skipct) + + (b1, b2, b3) = parse_iparts(b) + rtokens = parse_rexpr(b3) + if len(rtokens) > 1 and rtokens[1] == '.req': + # .req has atypical syntax; no symbol refs there anyway + return (refsyms, skipct) + for t in rtokens[1:]: + if token_type(t) == 'id' and looksglobal(t): + refsyms.add(t) + return (refsyms, skipct) + + def finddef1(defsyms, (a, b, c)): + if re.match('#', b): + # Preprocessor line + return defsyms + (b1, b2, b3) = parse_iparts(b) + rtokens = parse_rexpr(b3) + if b1 != '': + defsyms.add(b1) + if len(rtokens) > 1 and rtokens[1] == '.req': + defsyms.add(rtokens[0]) + return defsyms + + def repl1((glosyms, result), (a, b, c)): + if re.match('#', b): + # Preprocessor line + result.append((a, b, c)) + return (glosyms, result) + toglo = lambda s: 'Glo(' + s + ')' + (b1, b2, b3) = parse_iparts(b) + tokens = parse_expr(b3) + + if b1 in glosyms: + b1 = toglo(b1) + for i in range(len(tokens)): + if token_type(tokens[i]) == 'id' and tokens[i] in glosyms: + tokens[i] = toglo(tokens[i]) + result.append((a, b1 + b2 + ''.join(tokens), c)) + return (glosyms, result) + + reduce(findglo1, instrs, glosyms) + reduce(findref1, instrs, (refsyms, 0)) + reduce(finddef1, instrs, defsyms) + glosyms |= (refsyms - defsyms) + reduce(repl1, instrs, (glosyms, result)) + return result + + +def local_symbols(instrs): + # The form of a local symbol differs between Linux assemblers and + # the Apple assember: + # + # Linux: .Lxxx + # Apple: Lxxx + # + # Change occurrences of local symbols to use the Loc() cpp macro + # defined in our prefix. + # + lsyms = set() + result = [] + + def find1 (lsyms, (a, b, c)): + mo = re.match('(\.L[^ \t:]*)[ \t]*:', b) + if mo: + lsyms.add(mo.group(1)) + return lsyms + + def repl1((lsyms, result), (a, b, c)): + matches = list(re.finditer('\.L[^ \t@:,+*/\-()]+', b)) + if matches != []: + matches.reverse() + newb = b + for mo in matches: + if mo.group() in lsyms: + newb = newb[0:mo.start()] + \ + 'Loc(' + mo.group()[2:] + ')' + \ + newb[mo.end():] + result.append((a, newb, c)) + else: + result.append((a, b, c)) + return (lsyms, result) + + reduce(find1, instrs, lsyms) + reduce(repl1, instrs, (lsyms, result)) + return result + + +def funtypes(instrs): + # Linux assemblers accept declarations like this: + # + # .type symbol, %function + # + # For Thumb functions, the Apple assembler wants to see: + # + # .thumb_func symbol + # + # Handle this by converting declarations to this: + # + # .funtype symbol + # + # Our prefix defines an appropriate .funtype macro for each + # environment. + # + result = [] + + def repl1(result, (a, b, c)): + mo = re.match('.type[ \t]+([^ \t,]*),[ \t]*%function', b) + if mo: + result.append((a, '.funtype ' + mo.group(1), c)) + else: + result.append((a, b, c)) + return result + + reduce(repl1, instrs, result) + return result + + +def jump_tables(instrs): + # Jump tables for Linux assemblers often look like this: + # + # tbh [pc, rM, lsl #1] + # .short (.Labc-.)/2+0 + # .short (.Ldef-.)/2+1 + # .short (.Lghi-.)/2+2 + # + # The Apple assembler disagrees about the meaning of this code, + # producing jump tables that don't work. Convert to the following: + # + # tbh [pc, rM, lsl #1] + # .LBxxx: + # .short (.Labc-.LBxxx)/2 + # .short (.Ldef-.LBxxx)/2 + # .short (.Lghi-.LBxxx)/2 + # + # In fact we just convert sequences of .short pseudo-ops of the + # right form. There's no requirement that they follow a tbh + # instruction. + # + baselabs = [] + result = [] + + def short_match(seq, op): + # Determine whether the op is a .short of the form that needs to + # be converted: .short (symbol-.)/2+k. If so, return a pair + # containing the symbol and the value of k. If not, return + # None. The short can only be converted if there were at least + # k other .shorts in sequence before the current one. A summary + # of the previous .shorts is in seq. + # + # (A real parser would do a better job, but this was quick to + # get working.) + # + sp = '([ \t]|/\*.*?\*/)*' # space + sp1 = '([ \t]|/\*.*?\*/)+' # at least 1 space + spe = '([ \t]|/\*.*?\*/|@[^\n]*)*$' # end-of-instr space + expr_re0 = ( + '\.short' + sp + '\(' + sp + # .short ( + '([^ \t+\-*/@()]+)' + sp + # symbol + '-' + sp + '\.' + sp + '\)' + sp + # -.) + '/' + sp + '2' + spe # /2 END + ) + expr_re1 = ( + '\.short' + sp + '\(' + sp + # .short ( + '([^ \t+\-*/@()]+)' + sp + # symbol + '-' + sp + '\.' + sp + '\)' + sp + # -.) + '/' + sp + '2' + sp + # /2 + '\+' + sp + # + + '((0[xX])?[0-9]+)' + spe # k END + ) + expr_re2 = ( + '\.short' + sp1 + # .short + '((0[xX])?[0-9]+)' + sp + # k + '\+' + sp + '\(' + sp + # +( + '([^ \t+\-*/@()]+)' + sp + # symbol + '-' + sp + '\.' + sp + '\)' + sp + # -.) + '/' + sp + '2' + spe # /2 END + ) + mo = re.match(expr_re0, op) + if mo: + return(mo.group(3), 0) + mo = re.match(expr_re1, op) + if mo: + k = int(mo.group(11), 0) + if k > len(seq): + return None + return (mo.group(3), k) + mo = re.match(expr_re2, op) + if mo: + k = int(mo.group(2), 0) + if k > len(seq): + return None + return (mo.group(7), k) + return None + + def conv1 ((baselabs, shortseq, label, result), (a, b, c)): + # Convert current instr (a,b,c) if it's a .short of the right + # form that spans a previous sequence of .shorts. + # + (b1, b2, b3) = parse_iparts(b) + + if b3 == '': + # No operation: just note label if present. + result.append((a, b, c)) + if re.match('\.L.', b1): + return (baselabs, shortseq, b1, result) + return (baselabs, shortseq, label, result) + + if not re.match('.short[ \t]+[^ \t@]', b3): + # Not a .short: clear shortseq and label + result.append((a, b, c)) + return (baselabs, [], '', result) + + # We have a .short: figure out the label if any + if re.match('\.L', b1): + sl = b1 + else: + sl = label + + mpair = short_match(shortseq, b3) + if not mpair: + # A .short, but not of right form + shortseq.append((len(result), sl)) + result.append((a, b, c)) + return (baselabs, shortseq, '', result) + + # OK, we have a .short to convert! + (sym, k) = mpair + shortseq.append((len(result), sl)) + + # Figure out base label (create one if necessary). + bx = len(shortseq) - 1 - k + bl = shortseq[bx][1] + if bl == '': + bl = g_basepfx + str(shortseq[bx][0]) + shortseq[bx] = (shortseq[bx][0], bl) + baselabs.append(shortseq[bx]) + + op = '.short\t(' + sym + '-' + bl + ')/2' + + result.append ((a, b1 + b2 + op, c)) + return (baselabs, shortseq, '', result) + + # Convert, accumulate result and new labels. + reduce(conv1, instrs, (baselabs, [], '', result)) + + # Add labels created here to the instruction stream. + baselabs.reverse() + for (ix, lab) in baselabs: + result[ix:0] = [('', lab + ':', '\n')] + + # That does it + return result + + +def dot_relative(instrs): + # The Apple assembler (or possibly the linker) has trouble with code + # that looks like this: + # + # .word .Label - . + 0x80000000 + # .word 0x1966 + # .Label: + # .word 0x1967 + # + # One way to describe the problem is that the assembler marks the + # first .word for relocation when in fact it's an assembly-time + # constant. Translate to the following form, which doesn't generate + # a relocation marking: + # + # DR0 = .Label - . + 0x80000000 + # .word DR0 + # .word 0x1966 + # .Label: + # .word 0x1967 + # + prefix = 'DR' + pseudos = '(\.byte|\.short|\.word|\.long|\.quad)' + result = [] + + def tok_ok(t): + return t in ['.', '+', '-', '(', ')'] or \ + token_type(t) in ['space', 'locid', 'number'] + + def dotrel_match(expr): + # Determine whether the expression is one that needs to be + # translated. + tokens = parse_expr(expr) + return forall(tok_ok, tokens) and \ + exists(lambda t: token_type(t) == 'locid', tokens) and \ + exists(lambda t: token_type(t) == 'number', tokens) and \ + exists(lambda t: t == '-', tokens) and \ + exists(lambda t: t == '.', tokens) + + def conv1(result, (a, b, c)): + if re.match('#', b): + # Preprocessor line + result.append((a, b, c)) + else: + (b1, b2, b3) = parse_iparts(b) + mo = re.match(pseudos + ccce(g_ccid), b3) + if mo: + p = mo.group(1) + expr = b3[len(p):] + if dotrel_match(expr): + sym = prefix + str(len(result)) + instr = sym + ' =' + expr + result.append(('', instr, '\n')) + result.append((a, b1 + b2 + p + ' ' + sym, c)) + else: + result.append((a, b, c)) + else: + result.append((a, b, c)) + return result + + reduce(conv1, instrs, result) + return result + + +def read_input(): + # Concatenate all the input files into a string. + # + def fnl(s): + if s == '' or s[-1] == '\n': + return s + else: + return s + '\n' + + if len(sys.argv) < 2: + return fnl(sys.stdin.read()) + else: + input = "" + for f in sys.argv[1:]: + # allow global symbols to be enabled or disabled, eg: + # --global=foo,!bar + # foo is forced to be global + # bar is forced to be non-global + if f.startswith('--global='): + glist = f[9:].split(',') + for g in glist: + if g.startswith('!'): + initial_defsyms.append(g[1:]) + else: + initial_glosyms.append(g) + elif f.startswith('--stdin'): + input = input + fnl(sys.stdin.read()) + else: + try: + fd = open(f) + input = input + fnl(fd.read()) + fd.close() + except: + sys.stderr.write('arm-as-to-ios: cannot open ' + f + '\n') + return input + + +def parse_instrs(s): + # Parse the string into assembly instructions, also noting C + # preprocessor lines. Each instruction is represented as a triple: + # (space/comments, instruction, end). The end is either ';' or + # '\n'. + # + def goodmo(mo): + if mo == None: + # Should never happen + sys.stderr.write('arm-as-to-ios: internal parsing error\n') + sys.exit(1) + + cpp_re = '([ \t]*)(#([^\n]*\\\\\n)*[^\n]*[^\\\\\n])\n' + comment_re = '[ \t]*#[^\n]*' + instr_re = ( + '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments + '(([ \t]|/\*.*?\*/|[^;\n])*)' # "Instruction" + '([;\n])' # End + ) + instrs = [] + while s != '': + if re.match('[ \t]*#[ \t]*(if|ifdef|elif|else|endif|define)', s): + mo = re.match(cpp_re, s) + goodmo(mo) + instrs.append((mo.group(1), mo.group(2), '\n')) + elif re.match('[ \t]*#', s): + mo = re.match(comment_re, s) + goodmo(mo) + instrs.append((mo.group(0), '', '\n')) + else: + mo = re.match(instr_re, s, re.DOTALL) + goodmo(mo) + instrs.append((mo.group(1), mo.group(3), mo.group(5))) + s = s[len(mo.group(0)):] + return instrs + + +def parse_iparts(i): + # Parse an instruction into smaller parts, returning a triple of + # strings (label, colon, operation). The colon part also contains + # any surrounding spaces and comments (making the label and the + # operation cleaner to process). + # + # (Caller warrants that the given string doesn't start with space or + # a comment. This is true for strings returned by the instruction + # parser.) + # + lab_re = ( + '([^ \t:/@]+)' # Label + '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments + ':' # Colon + '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments + '([^\n]*)' # Operation + ) + + if len(i) > 0 and i[0] == '#': + # C preprocessor line; treat as operation. + return ('', '', i) + mo = re.match(lab_re, i) + if mo: + return (mo.group(1), mo.group(2) + ':' + mo.group(4), mo.group(6)) + # No label, just an operation + return ('', '', i) + + +def parse_expr(s): + # Parse a string into a sequence of tokens. A segment of white + # space (including comments) is treated as a token, so that the + # tokens can be reassembled into the string again. + # + result = [] + while s != '': + mo = re.match('([ \t]|/\*.*?\*/|@.*)+', s) + if not mo: + # Glo(...) and Loc(...) are single tokens + mo = re.match('(Glo|Loc)\([^()]*\)', s) + if not mo: + mo = re.match('"([^\\\\"]|\\\\.)*"', s) + if not mo: + mo = re.match(g_ccid0 + g_ccid + '*', s) + if not mo: + mo = re.match('[0-9]+[bf]', s) + if not mo: + mo = re.match('0[Xx][0-9a-fA-F]+|[0-9]+', s) + if not mo: + mo = re.match('.', s) + result.append(mo.group(0)) + s = s[len(mo.group(0)):] + return result + + +def parse_rexpr(s): + # Like parse_expr(), but return only "real" tokens, not the + # intervening space. + # + return filter(lambda t: token_type(t) != 'space', parse_expr(s)) + + +def token_type(t): + # Determine the type of a token. Caller warrants that it was + # returned by parse_expr() or parse_rexpr(). + # + if re.match('[ \t]|/\*|@', t): + return 'space' + if re.match('Glo\(', t): + return 'gloid' + if re.match('Loc\(', t): + return 'locid' + if re.match('"', t): + return 'string' + if re.match(g_ccid0, t): + return 'id' + if re.match('[0-9]+[bf]', t): + return 'label' + if re.match('[0-9]', t): + return 'number' + return t # Sui generis + + +def debug_parse(a, b, c): + # Show results of instuction stream parse. + # + (b1, b2, b3) = parse_iparts(b) + newb = '{' + b1 + '}' + '{' + b2 + '}' + '{' + b3 + '}' + sys.stdout.write('{' + a + '}' + newb + c) + + +def main(): + instrs = parse_instrs(read_input()) + instrs = explicit_address_loads(instrs) + instrs = funtypes(instrs) + instrs = jump_tables(instrs) + instrs = global_symbols(instrs) + instrs = local_symbols(instrs) + instrs = dot_relative(instrs) + instrs = add_prefix(instrs) + for (a, b, c) in instrs: + sys.stdout.write(a + b + c) + + +main() diff --git a/deps/minicrypto/arm-as-to-ios.orig b/deps/minicrypto/arm-as-to-ios.orig new file mode 100755 index 0000000..a049bca --- /dev/null +++ b/deps/minicrypto/arm-as-to-ios.orig @@ -0,0 +1,730 @@ +#!/usr/bin/env python +# +# arm-as-to-ios Modify ARM assembly code for the iOS assembler +# +# Copyright (c) 2012 Psellos http://psellos.com/ +# Licensed under the MIT License: +# http://www.opensource.org/licenses/mit-license.php +# +# Resources for running OCaml on iOS: http://psellos.com/ocaml/ +# +import sys +import re + +VERSION = '1.4.0' + +# Character classes for expression lexing. +# +g_ccid0 = '[$.A-Z_a-z\x80-\xff]' # Beginning of id +g_ccid = '[$.0-9A-Z_a-z\x80-\xff]' # Later in id +def ccc(cc): # Complement the class + if cc[1] == '^': + return cc[0] + cc[2:] + return cc[0] + '^' + cc[1:] +def ccce(cc): # Complement the class, include EOL + return '(?:' + ccc(cc) + '|$)' + +# Prefixes for pooled symbol labels and jump table base labels. They're +# in the space of Linux assembler local symbols. Later rules will +# modify them to the Loc() form. +# +g_poolpfx = '.LP' +g_basepfx = '.LB' + + +def exists(p, l): + for l1 in l: + if p(l1): + return True + return False + + +def forall(p, l): + for l1 in l: + if not p(l1): + return False + return True + + +def add_prefix(instrs): + # Add compatibility macros for all systems, plus hardware + # definitions and compatibility macros for iOS. + # + # All systems: + # + # Glo() cpp macro for making global symbols (xxx vs _xxx) + # Loc() cpp macro for making local symbols (.Lxxx vs Lxxx) + # .funtype Expands to .thumb_func for iOS armv7 (null for armv6) + # Expands to .type %function for others + # + # iOS: + # + # .machine armv6/armv7 + # .thumb (for armv7) + # cbz Expands to cmp/beq for armv6 (Thumb-only instr) + # .type Not supported by Apple assembler + # .size Not supported by Apple assembler + # + defre = '#[ \t]*if.*def.*SYS' # Add new defs near first existing ones + skipre = '$|\.syntax[ \t]' # Skip comment lines (and .syntax) + + for i in range(len(instrs)): + if re.match(defre, instrs[i][1]): + break + else: + i = 0 + for i in range(i, len(instrs)): + if not re.match(skipre, instrs[i][1]): + break + instrs[i:0] = [ + ('', '', '\n'), + ('/* Apple compatibility macros */', '', '\n'), + ('', '#if defined(SYS_macosx)', '\n'), + ('', '#define Glo(s) _##s', '\n'), + ('', '#define Loc(s) L##s', '\n'), + ('', '#if defined(MODEL_armv6)', '\n'), + (' ', '.machine armv6', '\n'), + (' ', '.macro .funtype', '\n'), + (' ', '.endm', '\n'), + (' ', '.macro cbz', '\n'), + (' ', 'cmp $0, #0', '\n'), + (' ', 'beq $1', '\n'), + (' ', '.endm', '\n'), + ('', '#else', '\n'), + (' ', '.machine armv7', '\n'), + (' ', '.thumb', '\n'), + (' ', '.macro .funtype', '\n'), + (' ', '.thumb_func $0', '\n'), + (' ', '.endm', '\n'), + ('', '#endif', '\n'), + (' ', '.macro .type', '\n'), + (' ', '.endm', '\n'), + (' ', '.macro .size', '\n'), + (' ', '.endm', '\n'), + ('', '#else', '\n'), + ('', '#define Glo(s) s', '\n'), + ('', '#define Loc(s) .L##s', '\n'), + (' ', '.macro .funtype symbol', '\n'), + (' ', '.type \\symbol, %function', '\n'), + (' ', '.endm', '\n'), + ('', '#endif', '\n'), + ('/* End Apple compatibility macros */', '', '\n'), + ('', '', '\n') + ] + return instrs + + +# Regular expression for modified ldr lines +# +g_ldre = '(ldr[ \t][^,]*,[ \t]*)=(([^ \t\n@,/]|/(?!\*))*)(.*)' + + +def explicit_address_loads(instrs): + # Linux assemblers allow the following: + # + # ldr rM, =symbol + # + # which loads rM with [mov] (immediately) if possible, or creates an + # entry in memory for the symbol value and loads it PC-relatively + # with [ldr]. + # + # The Apple assembler doesn't seem to support this notation. If the + # value is a suitable constant, it emits a valid [mov]. Otherwise + # it seems to emit an invalid [ldr] that always generates an error. + # (At least I have not been able to make it work). So, change uses + # of =symbol to explicit PC-relative loads. + # + # This requires a pool containing the addresses to be loaded. For + # now, we just keep track of it ourselves and emit it into the text + # segment at the end of the file. + # + syms = {} + result = [] + + def repl1((syms, result), (a, b, c)): + global g_poolpfx + global g_ldre + (b1, b2, b3) = parse_iparts(b) + mo = re.match(g_ldre, b3, re.DOTALL) + if mo: + if mo.group(2) not in syms: + syms[mo.group(2)] = len(syms) + psym = mo.group(2) + if psym[0:2] == '.L': + psym = psym[2:] + newb3 = mo.group(1) + g_poolpfx + psym + mo.group(4) + result.append((a, b1 + b2 + newb3, c)) + else: + result.append((a, b, c)) + return (syms, result) + + def pool1(result, s): + global g_poolpfx + psym = s + if psym[0:2] == '.L': + psym = psym[2:] + result.append(('', g_poolpfx + psym + ':', '\n')) + result.append((' ', '.long ' + s, '\n')) + return result + + reduce(repl1, instrs, (syms, result)) + if len(syms) > 0: + result.append(('', '', '\n')) + result.append(('/* Pool of addresses loaded into registers */', + '', '\n')) + result.append(('', '', '\n')) + result.append((' ', '.text', '\n')) + result.append((' ', '.align 2', '\n')) + reduce(pool1, sorted(syms, key=syms.get), result) + return result + + +def global_symbols(instrs): + # The form of a global symbol differs between Linux assemblers and + # the Apple assember: + # + # Linux: xxx + # Apple: _xxx + # + # Change occurrences of global symbols to use the Glo() cpp macro + # defined in our prefix. + # + # We consider a symbol to be global if: + # + # a. It appears in a .globl declaration; or + # b. It is referenced, has global form, and is not defined + # + glosyms = set() + refsyms = set() + defsyms = set() + result = [] + + def findglo1 (glosyms, (a, b, c)): + if re.match('#', b): + # Preprocessor line; nothing to do + return glosyms + (b1, b2, b3) = parse_iparts(b) + mo = re.match('(\.globl)' + ccce(g_ccid), b3) + if mo: + tokens = parse_expr(b3[len(mo.group(1)):]) + if forall(lambda t: token_type(t) in ['space', 'id', ','], tokens): + for t in tokens: + if token_type(t) == 'id': + glosyms.add(t) + return glosyms + + def findref1 ((refsyms, skipct), (a, b, c)): + + def looksglobal(s): + if re.match('(r|a|v|p|c|cr|f|s|d|q|mvax|wcgr)[0-9]+$', s, re.I): + return False # numbered registers + if re.match('(wr|sb|sl|fp|ip|sp|lr|pc)$', s, re.I): + return False # named registers + if re.match('(fpsid|fpscr|fpexc|mvfr1|mvfr0)$', s, re.I): + return False # more named registers + if re.match('(mvf|mvd|mvfx|mvdx|dspsc)$', s, re.I): + return False # even more named registers + if re.match('(wcid|wcon|wcssf|wcasf|acc)$', s, re.I): + return False # even more named registers + if re.match('\.$|\.L|[0-9]|#', s): + return False # dot, local symbol, or number + if re.match('(asl|lsl|lsr|asr|ror|rrx)$', s, re.I): + return False # shift names + return True + + if re.match('#', b): + # Preprocessor line; nothing to do + return (refsyms, skipct) + + # Track nesting of .macro/.endm. For now, we don't look for + # global syms in macro defs. (Avoiding scoping probs etc.) + # + if skipct > 0 and re.match('\.(endm|endmacro)' + ccce(g_ccid), b): + return (refsyms, skipct - 1) + if re.match('\.macro' + ccce(g_ccid), b): + return (refsyms, skipct + 1) + if skipct > 0: + return (refsyms, skipct) + if re.match('\.(type|size|syntax|arch|fpu)' + ccce(g_ccid), b): + return (refsyms, skipct) + + (b1, b2, b3) = parse_iparts(b) + rtokens = parse_rexpr(b3) + if len(rtokens) > 1 and rtokens[1] == '.req': + # .req has atypical syntax; no symbol refs there anyway + return (refsyms, skipct) + for t in rtokens[1:]: + if token_type(t) == 'id' and looksglobal(t): + refsyms.add(t) + return (refsyms, skipct) + + def finddef1(defsyms, (a, b, c)): + if re.match('#', b): + # Preprocessor line + return defsyms + (b1, b2, b3) = parse_iparts(b) + rtokens = parse_rexpr(b3) + if b1 != '': + defsyms.add(b1) + if len(rtokens) > 1 and rtokens[1] == '.req': + defsyms.add(rtokens[0]) + return defsyms + + def repl1((glosyms, result), (a, b, c)): + if re.match('#', b): + # Preprocessor line + result.append((a, b, c)) + return (glosyms, result) + toglo = lambda s: 'Glo(' + s + ')' + (b1, b2, b3) = parse_iparts(b) + tokens = parse_expr(b3) + + if b1 in glosyms: + b1 = toglo(b1) + for i in range(len(tokens)): + if token_type(tokens[i]) == 'id' and tokens[i] in glosyms: + tokens[i] = toglo(tokens[i]) + result.append((a, b1 + b2 + ''.join(tokens), c)) + return (glosyms, result) + + reduce(findglo1, instrs, glosyms) + reduce(findref1, instrs, (refsyms, 0)) + reduce(finddef1, instrs, defsyms) + glosyms |= (refsyms - defsyms) + reduce(repl1, instrs, (glosyms, result)) + return result + + +def local_symbols(instrs): + # The form of a local symbol differs between Linux assemblers and + # the Apple assember: + # + # Linux: .Lxxx + # Apple: Lxxx + # + # Change occurrences of local symbols to use the Loc() cpp macro + # defined in our prefix. + # + lsyms = set() + result = [] + + def find1 (lsyms, (a, b, c)): + mo = re.match('(\.L[^ \t:]*)[ \t]*:', b) + if mo: + lsyms.add(mo.group(1)) + return lsyms + + def repl1((lsyms, result), (a, b, c)): + matches = list(re.finditer('\.L[^ \t@:,+*/\-()]+', b)) + if matches != []: + matches.reverse() + newb = b + for mo in matches: + if mo.group() in lsyms: + newb = newb[0:mo.start()] + \ + 'Loc(' + mo.group()[2:] + ')' + \ + newb[mo.end():] + result.append((a, newb, c)) + else: + result.append((a, b, c)) + return (lsyms, result) + + reduce(find1, instrs, lsyms) + reduce(repl1, instrs, (lsyms, result)) + return result + + +def funtypes(instrs): + # Linux assemblers accept declarations like this: + # + # .type symbol, %function + # + # For Thumb functions, the Apple assembler wants to see: + # + # .thumb_func symbol + # + # Handle this by converting declarations to this: + # + # .funtype symbol + # + # Our prefix defines an appropriate .funtype macro for each + # environment. + # + result = [] + + def repl1(result, (a, b, c)): + mo = re.match('.type[ \t]+([^ \t,]*),[ \t]*%function', b) + if mo: + result.append((a, '.funtype ' + mo.group(1), c)) + else: + result.append((a, b, c)) + return result + + reduce(repl1, instrs, result) + return result + + +def jump_tables(instrs): + # Jump tables for Linux assemblers often look like this: + # + # tbh [pc, rM, lsl #1] + # .short (.Labc-.)/2+0 + # .short (.Ldef-.)/2+1 + # .short (.Lghi-.)/2+2 + # + # The Apple assembler disagrees about the meaning of this code, + # producing jump tables that don't work. Convert to the following: + # + # tbh [pc, rM, lsl #1] + # .LBxxx: + # .short (.Labc-.LBxxx)/2 + # .short (.Ldef-.LBxxx)/2 + # .short (.Lghi-.LBxxx)/2 + # + # In fact we just convert sequences of .short pseudo-ops of the + # right form. There's no requirement that they follow a tbh + # instruction. + # + baselabs = [] + result = [] + + def short_match(seq, op): + # Determine whether the op is a .short of the form that needs to + # be converted: .short (symbol-.)/2+k. If so, return a pair + # containing the symbol and the value of k. If not, return + # None. The short can only be converted if there were at least + # k other .shorts in sequence before the current one. A summary + # of the previous .shorts is in seq. + # + # (A real parser would do a better job, but this was quick to + # get working.) + # + sp = '([ \t]|/\*.*?\*/)*' # space + sp1 = '([ \t]|/\*.*?\*/)+' # at least 1 space + spe = '([ \t]|/\*.*?\*/|@[^\n]*)*$' # end-of-instr space + expr_re0 = ( + '\.short' + sp + '\(' + sp + # .short ( + '([^ \t+\-*/@()]+)' + sp + # symbol + '-' + sp + '\.' + sp + '\)' + sp + # -.) + '/' + sp + '2' + spe # /2 END + ) + expr_re1 = ( + '\.short' + sp + '\(' + sp + # .short ( + '([^ \t+\-*/@()]+)' + sp + # symbol + '-' + sp + '\.' + sp + '\)' + sp + # -.) + '/' + sp + '2' + sp + # /2 + '\+' + sp + # + + '((0[xX])?[0-9]+)' + spe # k END + ) + expr_re2 = ( + '\.short' + sp1 + # .short + '((0[xX])?[0-9]+)' + sp + # k + '\+' + sp + '\(' + sp + # +( + '([^ \t+\-*/@()]+)' + sp + # symbol + '-' + sp + '\.' + sp + '\)' + sp + # -.) + '/' + sp + '2' + spe # /2 END + ) + mo = re.match(expr_re0, op) + if mo: + return(mo.group(3), 0) + mo = re.match(expr_re1, op) + if mo: + k = int(mo.group(11), 0) + if k > len(seq): + return None + return (mo.group(3), k) + mo = re.match(expr_re2, op) + if mo: + k = int(mo.group(2), 0) + if k > len(seq): + return None + return (mo.group(7), k) + return None + + def conv1 ((baselabs, shortseq, label, result), (a, b, c)): + # Convert current instr (a,b,c) if it's a .short of the right + # form that spans a previous sequence of .shorts. + # + (b1, b2, b3) = parse_iparts(b) + + if b3 == '': + # No operation: just note label if present. + result.append((a, b, c)) + if re.match('\.L.', b1): + return (baselabs, shortseq, b1, result) + return (baselabs, shortseq, label, result) + + if not re.match('.short[ \t]+[^ \t@]', b3): + # Not a .short: clear shortseq and label + result.append((a, b, c)) + return (baselabs, [], '', result) + + # We have a .short: figure out the label if any + if re.match('\.L', b1): + sl = b1 + else: + sl = label + + mpair = short_match(shortseq, b3) + if not mpair: + # A .short, but not of right form + shortseq.append((len(result), sl)) + result.append((a, b, c)) + return (baselabs, shortseq, '', result) + + # OK, we have a .short to convert! + (sym, k) = mpair + shortseq.append((len(result), sl)) + + # Figure out base label (create one if necessary). + bx = len(shortseq) - 1 - k + bl = shortseq[bx][1] + if bl == '': + bl = g_basepfx + str(shortseq[bx][0]) + shortseq[bx] = (shortseq[bx][0], bl) + baselabs.append(shortseq[bx]) + + op = '.short\t(' + sym + '-' + bl + ')/2' + + result.append ((a, b1 + b2 + op, c)) + return (baselabs, shortseq, '', result) + + # Convert, accumulate result and new labels. + reduce(conv1, instrs, (baselabs, [], '', result)) + + # Add labels created here to the instruction stream. + baselabs.reverse() + for (ix, lab) in baselabs: + result[ix:0] = [('', lab + ':', '\n')] + + # That does it + return result + + +def dot_relative(instrs): + # The Apple assembler (or possibly the linker) has trouble with code + # that looks like this: + # + # .word .Label - . + 0x80000000 + # .word 0x1966 + # .Label: + # .word 0x1967 + # + # One way to describe the problem is that the assembler marks the + # first .word for relocation when in fact it's an assembly-time + # constant. Translate to the following form, which doesn't generate + # a relocation marking: + # + # DR0 = .Label - . + 0x80000000 + # .word DR0 + # .word 0x1966 + # .Label: + # .word 0x1967 + # + prefix = 'DR' + pseudos = '(\.byte|\.short|\.word|\.long|\.quad)' + result = [] + + def tok_ok(t): + return t in ['.', '+', '-', '(', ')'] or \ + token_type(t) in ['space', 'locid', 'number'] + + def dotrel_match(expr): + # Determine whether the expression is one that needs to be + # translated. + tokens = parse_expr(expr) + return forall(tok_ok, tokens) and \ + exists(lambda t: token_type(t) == 'locid', tokens) and \ + exists(lambda t: token_type(t) == 'number', tokens) and \ + exists(lambda t: t == '-', tokens) and \ + exists(lambda t: t == '.', tokens) + + def conv1(result, (a, b, c)): + if re.match('#', b): + # Preprocessor line + result.append((a, b, c)) + else: + (b1, b2, b3) = parse_iparts(b) + mo = re.match(pseudos + ccce(g_ccid), b3) + if mo: + p = mo.group(1) + expr = b3[len(p):] + if dotrel_match(expr): + sym = prefix + str(len(result)) + instr = sym + ' =' + expr + result.append(('', instr, '\n')) + result.append((a, b1 + b2 + p + ' ' + sym, c)) + else: + result.append((a, b, c)) + else: + result.append((a, b, c)) + return result + + reduce(conv1, instrs, result) + return result + + +def read_input(): + # Concatenate all the input files into a string. + # + def fnl(s): + if s == '' or s[-1] == '\n': + return s + else: + return s + '\n' + + if len(sys.argv) < 2: + return fnl(sys.stdin.read()) + else: + input = "" + for f in sys.argv[1:]: + try: + fd = open(f) + input = input + fnl(fd.read()) + fd.close() + except: + sys.stderr.write('arm-as-to-ios: cannot open ' + f + '\n') + return input + + +def parse_instrs(s): + # Parse the string into assembly instructions, also noting C + # preprocessor lines. Each instruction is represented as a triple: + # (space/comments, instruction, end). The end is either ';' or + # '\n'. + # + def goodmo(mo): + if mo == None: + # Should never happen + sys.stderr.write('arm-as-to-ios: internal parsing error\n') + sys.exit(1) + + cpp_re = '([ \t]*)(#([^\n]*\\\\\n)*[^\n]*[^\\\\\n])\n' + comment_re = '[ \t]*#[^\n]*' + instr_re = ( + '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments + '(([ \t]|/\*.*?\*/|[^;\n])*)' # "Instruction" + '([;\n])' # End + ) + instrs = [] + while s != '': + if re.match('[ \t]*#[ \t]*(if|ifdef|elif|else|endif|define)', s): + mo = re.match(cpp_re, s) + goodmo(mo) + instrs.append((mo.group(1), mo.group(2), '\n')) + elif re.match('[ \t]*#', s): + mo = re.match(comment_re, s) + goodmo(mo) + instrs.append((mo.group(0), '', '\n')) + else: + mo = re.match(instr_re, s, re.DOTALL) + goodmo(mo) + instrs.append((mo.group(1), mo.group(3), mo.group(5))) + s = s[len(mo.group(0)):] + return instrs + + +def parse_iparts(i): + # Parse an instruction into smaller parts, returning a triple of + # strings (label, colon, operation). The colon part also contains + # any surrounding spaces and comments (making the label and the + # operation cleaner to process). + # + # (Caller warrants that the given string doesn't start with space or + # a comment. This is true for strings returned by the instruction + # parser.) + # + lab_re = ( + '([^ \t:/@]+)' # Label + '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments + ':' # Colon + '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments + '([^\n]*)' # Operation + ) + + if len(i) > 0 and i[0] == '#': + # C preprocessor line; treat as operation. + return ('', '', i) + mo = re.match(lab_re, i) + if mo: + return (mo.group(1), mo.group(2) + ':' + mo.group(4), mo.group(6)) + # No label, just an operation + return ('', '', i) + + +def parse_expr(s): + # Parse a string into a sequence of tokens. A segment of white + # space (including comments) is treated as a token, so that the + # tokens can be reassembled into the string again. + # + result = [] + while s != '': + mo = re.match('([ \t]|/\*.*?\*/|@.*)+', s) + if not mo: + # Glo(...) and Loc(...) are single tokens + mo = re.match('(Glo|Loc)\([^()]*\)', s) + if not mo: + mo = re.match('"([^\\\\"]|\\\\.)*"', s) + if not mo: + mo = re.match(g_ccid0 + g_ccid + '*', s) + if not mo: + mo = re.match('[0-9]+[bf]', s) + if not mo: + mo = re.match('0[Xx][0-9a-fA-F]+|[0-9]+', s) + if not mo: + mo = re.match('.', s) + result.append(mo.group(0)) + s = s[len(mo.group(0)):] + return result + + +def parse_rexpr(s): + # Like parse_expr(), but return only "real" tokens, not the + # intervening space. + # + return filter(lambda t: token_type(t) != 'space', parse_expr(s)) + + +def token_type(t): + # Determine the type of a token. Caller warrants that it was + # returned by parse_expr() or parse_rexpr(). + # + if re.match('[ \t]|/\*|@', t): + return 'space' + if re.match('Glo\(', t): + return 'gloid' + if re.match('Loc\(', t): + return 'locid' + if re.match('"', t): + return 'string' + if re.match(g_ccid0, t): + return 'id' + if re.match('[0-9]+[bf]', t): + return 'label' + if re.match('[0-9]', t): + return 'number' + return t # Sui generis + + +def debug_parse(a, b, c): + # Show results of instuction stream parse. + # + (b1, b2, b3) = parse_iparts(b) + newb = '{' + b1 + '}' + '{' + b2 + '}' + '{' + b3 + '}' + sys.stdout.write('{' + a + '}' + newb + c) + + +def main(): + instrs = parse_instrs(read_input()) + instrs = explicit_address_loads(instrs) + instrs = funtypes(instrs) + instrs = jump_tables(instrs) + instrs = global_symbols(instrs) + instrs = local_symbols(instrs) + instrs = dot_relative(instrs) + instrs = add_prefix(instrs) + for (a, b, c) in instrs: + sys.stdout.write(a + b + c) + + +main() diff --git a/deps/minicrypto/build-minicrypto b/deps/minicrypto/build-minicrypto new file mode 100755 index 0000000..f229b5d --- /dev/null +++ b/deps/minicrypto/build-minicrypto @@ -0,0 +1,137 @@ +#!/usr/bin/env bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi + +[ -z "$DL" ] && DL=~/Downloads + +. $O3/core/vars/vars-$TARGET +. $O3/core/deps/lib-versions + +# Build ASM files with clang 3.0 +if [ "$APPLE_FAMILY" = "1" ]; then + GCC_AS_CMD=$HOME/clang3/clang + if ! [ -f "$GCC_AS_CMD" ]; then + echo "clang 3.0 binary must be present in $GCC_AS_CMD to assemble ARM crypto algorithms" + exit 1 + fi +fi + +DEST=minicrypto/minicrypto-$PLATFORM + +GLOBAL_COMPILE_FLAGS="$PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -DSHA1_ASM -DBF_PTR -DOPENSSL_VERSION_PTEXT= -D__LP32__" + +[ -z "$GCC_CMD" ] && GCC_CMD=gcc +[ -z "$GCC_AS_CMD" ] && GCC_AS_CMD="$GCC_CMD" +[ -z "$AR_CMD" ] && AR_CMD=ar +# the directory where this script lives +H=$O3/core/deps/minicrypto + +if [ "$NO_WIPE" != "1" ]; then + # unzip OpenSSL + rm -rf $OPENSSL_VERSION + tar xfz $DL/$OPENSSL_VERSION.tar.gz +fi + +OPENSSL_DIR=$(pwd)/$OPENSSL_VERSION + +# make build directory +mkdir -p minicrypto +rm -rf minicrypto/minicrypto-$PLATFORM +mkdir -p minicrypto/minicrypto-$PLATFORM/build.tmp +cd minicrypto/minicrypto-$PLATFORM/build.tmp +mkdir openssl + +# copy files from OpenSSL tree + +# ARM +cp $OPENSSL_DIR/crypto/arm_arch.h . + +# SHA general +cp $OPENSSL_DIR/crypto/md32_common.h . +cp $OPENSSL_DIR/crypto/sha/sha.h openssl + +# AES +cp $OPENSSL_DIR/crypto/aes/asm/aes-armv4.pl . + +# SHA1 +cp $OPENSSL_DIR/crypto/sha/asm/sha1-armv4-large.pl . +cp $OPENSSL_DIR/crypto/sha/sha_locl.h . +cp $OPENSSL_DIR/crypto/sha/sha1dgst.c . + +# SHA2 +cp $OPENSSL_DIR/crypto/sha/sha256.c . +cp $OPENSSL_DIR/crypto/sha/asm/sha256-armv4.pl . + +# SHA4 +cp $OPENSSL_DIR/crypto/sha/sha512.c . +cp $OPENSSL_DIR/crypto/sha/asm/sha512-armv4.pl . + +# note that OPENSSL_cleanse is not used by any +# of the functions we are interested in +cat >openssl/crypto.h <armv4cpuid.S +#CMD="$GCC_AS_CMD $GLOBAL_COMPILE_FLAGS -DSYS_macosx -DNO_THUMB -c armv4cpuid.S" +#echo $CMD +#$CMD + +# build the ASM files given as perl source +for f in *.pl ; do + bn=${f%%.pl} + S=$bn.S + COMPILE_FLAGS="" + CVT_FLAGS="" + if [ "$APPLE_FAMILY" = "1" ]; then + COMPILE_FLAGS="$COMPILE_FLAGS -DNO_THUMB" + [ "$bn" = "aes-armv4" ] && CVT_FLAGS="$CVT_FLAGS --global=!ad1,!ad2,!ad3" + [ "$bn" = "sha512-armv4" ] && CVT_FLAGS="$CVT_FLAGS --global=!HI,!LO" + perl $f | $O3/core/deps/minicrypto/arm-as-to-ios --stdin $CVT_FLAGS >$S + else + perl $f >$S + fi + CMD="$GCC_AS_CMD $GLOBAL_COMPILE_FLAGS $COMPILE_FLAGS -DSYS_macosx -c $S" + echo $CMD + $CMD +done + +CMD="$AR_CMD crs ../libminicrypto.a *.o" +echo $CMD +$CMD +exit 0 diff --git a/deps/minicrypto/build-minicrypto-osx b/deps/minicrypto/build-minicrypto-osx new file mode 100755 index 0000000..5773833 --- /dev/null +++ b/deps/minicrypto/build-minicrypto-osx @@ -0,0 +1,139 @@ +#!/usr/bin/env bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi +if [ -z "$ARCH" ]; then + echo "ARCH var must be defined (x86_64|i386)" + exit 1 +fi + +[ -z "$DL" ] && DL=~/Downloads + +. $O3/core/vars-$TARGET +. $O3/core/deps/lib-versions + +DEST=minicrypto/minicrypto-$PLATFORM + +GLOBAL_COMPILE_FLAGS="$MIN_DEPLOY_TARGET $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC" + +[ -z "$GCC_CMD" ] && GCC_CMD=gcc +[ -z "$GCC_AS_CMD" ] && GCC_AS_CMD="$GCC_CMD" +[ -z "$AR_CMD" ] && AR_CMD=ar + +# the directory where this script lives +H=$O3/core/deps/minicrypto + +if [ "$NO_WIPE" != "1" ]; then + # unzip OpenSSL + rm -rf $OPENSSL_VERSION + tar xfz $DL/$OPENSSL_VERSION.tar.gz +fi + +OPENSSL_DIR=$(pwd)/$OPENSSL_VERSION + +# make build directory +mkdir -p minicrypto +rm -rf minicrypto/minicrypto-$PLATFORM/$ARCH +mkdir -p minicrypto/minicrypto-$PLATFORM/$ARCH/build.tmp +cd minicrypto/minicrypto-$PLATFORM/$ARCH/build.tmp +mkdir openssl + +# copy files from OpenSSL tree + +# AES (not necessary now that PolarSSL has AES optimizations) +#cp $OPENSSL_DIR/crypto/aes/asm/aesni-x86_64.pl . + +if [ "$ARCH" = "x86_64" ]; then + # General + cp $O3/core/deps/polarssl/intel_cpu.c . + cp $OPENSSL_DIR/crypto/perlasm/x86_64-xlate.pl . + cp $OPENSSL_DIR/crypto/x86_64cpuid.pl . + + # SHA general + cp $OPENSSL_DIR/crypto/md32_common.h . + cp $OPENSSL_DIR/crypto/sha/sha.h openssl + + # SHA1 + cp $OPENSSL_DIR/crypto/sha/sha_locl.h . + cp $OPENSSL_DIR/crypto/sha/sha1dgst.c . + cp $OPENSSL_DIR/crypto/sha/asm/sha1-x86_64.pl . + + # SHA256 + cp $OPENSSL_DIR/crypto/sha/sha256.c . + + # SHA512 + cp $OPENSSL_DIR/crypto/sha/sha512.c . + cp $OPENSSL_DIR/crypto/sha/asm/sha512-x86_64.pl . + + # convert perl ASM to .s + for f in x86_64cpuid sha1-x86_64 ; do + perl $f.pl macosx >$f.s + done + perl sha512-x86_64.pl macosx sha512-x86_64.s + perl sha512-x86_64.pl macosx sha256-x86_64.s +elif [ "$ARCH" = "i386" ]; then + # General + cp $O3/core/deps/polarssl/intel_cpu.c . + cp $OPENSSL_DIR/crypto/perlasm/x86asm.pl . + cp $OPENSSL_DIR/crypto/perlasm/x86gas.pl . + cp $OPENSSL_DIR/crypto/x86cpuid.pl . + + # SHA general + cp $OPENSSL_DIR/crypto/md32_common.h . + cp $OPENSSL_DIR/crypto/sha/sha.h openssl + + # SHA1 + cp $OPENSSL_DIR/crypto/sha/sha_locl.h . + cp $OPENSSL_DIR/crypto/sha/sha1dgst.c . + cp $OPENSSL_DIR/crypto/sha/asm/sha1-586.pl . + + # SHA256 + cp $OPENSSL_DIR/crypto/sha/sha256.c . + cp $OPENSSL_DIR/crypto/sha/asm/sha256-586.pl . + + # SHA512 + cp $OPENSSL_DIR/crypto/sha/sha512.c . + cp $OPENSSL_DIR/crypto/sha/asm/sha512-586.pl . + + # convert perl ASM to .s + for f in x86cpuid sha1-586 sha256-586 sha512-586 ; do + perl $f.pl macosx >$f.s + done +fi + +cat >openssl/crypto.h <=7 +- ldr r12,.LOPENSSL_armcap +- ldr r12,[r3,r12] @ OPENSSL_armcap_P +- tst r12,#1 +- bne .LNEON ++ b .LNEON @ JY -- assume ARM v7 always supports NEON + #endif + stmdb sp!,{r4-r12,lr} + sub $Ktbl,r3,#672 @ K512 +@@ -573,7 +567,6 @@ + .size sha512_block_data_order,.-sha512_block_data_order + .asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by " + .align 2 +-.comm OPENSSL_armcap_P,4,4 + ___ + + $code =~ s/\`([^\`]*)\`/eval $1/gem; diff --git a/deps/openssl/build-openssl b/deps/openssl/build-openssl new file mode 100755 index 0000000..200dc6e --- /dev/null +++ b/deps/openssl/build-openssl @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi +if [ -z "$OPENSSL_TARGET" ]; then + echo "OPENSSL_TARGET var must be defined" + exit 1 +fi + +# GNU sed differs from BSD sed +if sed --version 2>&1 | grep -q GNU ; then + mysed='sed -i' +else + mysed='sed -i ""' +fi + +[ -z "$GCC_CMD" ] && GCC_CMD=gcc + +[ -z "$LINK_MODE" ] && LINK_MODE=static +[ "$LINK_MODE" = "static" ] && LINK_MODE=no-shared + +[ -z "$DL" ] && DL=~/Downloads + +. $O3/core/vars/vars-$TARGET +. $O3/core/deps/lib-versions + + +# source vars +. $O3/core/vars/vars-${TARGET} +. $O3/core/deps/lib-versions + +# source helper functions +. $O3/core/deps/functions.sh + +FNAME=openssl-${OPNESSL_VERSION}.tar.gz +URL=https://www.openssl.org/source/${OPENSSL_VERSION}.tar.gz +CSUM=${OPENSSL_CSUM} + +download + +AR=ar +RANLIB=ranlib +[ "$AR_CMD" ] && AR=$AR_CMD +[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD + +# special hack because OpenSSL build system doesn't use rc options for ar +[ "$AR" = "gcc-ar" ] && AR="gcc-ar rc" +[ "$AR" = "gcc-ar-5" ] && AR="gcc-ar-5 rc" + +OPENSSL=$OPENSSL_VERSION +DIST=$(pwd)/openssl/openssl-$PLATFORM +[ "$ARCH" ] && DIST=$DIST/$ARCH +rm -rf $OPENSSL $DIST +mkdir -p $DIST +tar xfz $DL/$FNAME +pushd $OPENSSL +CMD="./Configure $OPENSSL_TARGET $LINK_MODE threads no-idea no-mdc2 no-rc5 --prefix=$DIST" +echo $CMD +$CMD +$mysed -e "s|-O3|$LIB_OPT_LEVEL $MIN_DEPLOY_TARGET $OTHER_COMPILER_FLAGS $LIB_FPIC|" Makefile +#$mysed -e "s|ERR_load_COMP_strings()|//ERR_load_COMP_strings()|" crypto/err/err_all.c +make depend +make CC="$GCC_CMD" AR="$AR" RANLIB="$RANLIB" -j ${MAKE_JOBS:-1} build_libs +touch apps/openssl +touch openssl.pc +touch libcrypto.pc +touch libssl.pc +make install_sw +popd + +exit 0 diff --git a/deps/polarssl/.gitignore b/deps/polarssl/.gitignore new file mode 100644 index 0000000..75ea0b2 --- /dev/null +++ b/deps/polarssl/.gitignore @@ -0,0 +1 @@ +polartmp diff --git a/deps/polarssl/CMakeLists.txt b/deps/polarssl/CMakeLists.txt new file mode 100644 index 0000000..d98aca5 --- /dev/null +++ b/deps/polarssl/CMakeLists.txt @@ -0,0 +1,86 @@ +cmake_minimum_required(VERSION 2.6) +project(POLARSSL C) + +enable_testing() + +if(CMAKE_COMPILER_IS_GNUCC) + # JY Added + set(CMAKE_OSX_ARCHITECTURES "") + set(CMAKE_OSX_DEPLOYMENT_TARGET "") + set(CMAKE_OSX_SYSROOT "") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} $ENV{LIB_FPIC} $ENV{LIB_OPT_LEVEL} $ENV{PLATFORM_FLAGS} $ENV{OTHER_COMPILER_FLAGS} -Wall -W -Wdeclaration-after-statement") + if (NOT "$ENV{GCC_CMD}" STREQUAL "") + set(CMAKE_C_COMPILER "$ENV{GCC_CMD}") + endif() + if (NOT "$ENV{GPP_CMD}" STREQUAL "") + set(CMAKE_CXX_COMPILER "$ENV{GPP_CMD}") + endif() + if (NOT "$ENV{AR_CMD}" STREQUAL "") + set(CMAKE_AR "$ENV{AR_CMD}") + endif() + if (NOT "$ENV{RANLIB_CMD}" STREQUAL "") + set(CMAKE_RANLIB "$ENV{RANLIB_CMD}") + endif() + + # JY Commented out + #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -Wall -Wextra -W -Wdeclaration-after-statement") + #set(CMAKE_C_FLAGS_DEBUG "-g3 -O0") + #set(CMAKE_C_FLAGS_COVERAGE "-g3 -O0 -fprofile-arcs -ftest-coverage -lgcov") +endif(CMAKE_COMPILER_IS_GNUCC) + +if(CMAKE_BUILD_TYPE STREQUAL "Coverage") + if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_SHARED_LINKER_FLAGS "-fprofile-arcs -ftest-coverage") + endif(CMAKE_COMPILER_IS_GNUCC) +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) + +# JY added +if(MINICRYPTO) + if(MINICRYPTO_DIR) + add_library(minicrypto STATIC IMPORTED) + set_property(TARGET minicrypto PROPERTY IMPORTED_LOCATION "${MINICRYPTO_DIR}/libminicrypto.a") + endif() + if(OSSLCRYPTO_DIR) + add_library(crypto STATIC IMPORTED) + set_property(TARGET crypto PROPERTY IMPORTED_LOCATION "${OSSLCRYPTO_DIR}/libcrypto.a") + endif() +endif() + +# include full testing infrastructure (JY added) +if(ENABLE_TESTING) + enable_testing() +endif() + +if(LIB_INSTALL_DIR) +else() +set(LIB_INSTALL_DIR lib) +endif() + +include_directories(include/) + +if(ENABLE_ZLIB_SUPPORT) + find_package(ZLIB) + + if(ZLIB_FOUND) + include_directories(ZLIB_INCLUDE_DIR) + endif(ZLIB_FOUND) +endif(ENABLE_ZLIB_SUPPORT) + +add_subdirectory(library) +add_subdirectory(include) + +# include full testing infrastructure (JY modified) +if(ENABLE_TESTING) + if(CMAKE_COMPILER_IS_GNUCC) + add_subdirectory(tests) + endif(CMAKE_COMPILER_IS_GNUCC) + add_subdirectory(programs) +endif() + +ADD_CUSTOM_TARGET(apidoc + COMMAND doxygen doxygen/polarssl.doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/deps/polarssl/README.txt b/deps/polarssl/README.txt new file mode 100644 index 0000000..2c58a3d --- /dev/null +++ b/deps/polarssl/README.txt @@ -0,0 +1,12 @@ +Building PolarSSL for android. + +First, build static OpenSSL for PolarSSL/OpenSSL bridge +(the build-openssl-small script may be used). + +Next build libminicrypto.a from libcrypto.a : + + $O3/polarssl/build-mini-openssl ref + +Finally, build PolarSSL: + + TARGET=android $O3/polarssl/build-polarssl diff --git a/deps/polarssl/android.cmake b/deps/polarssl/android.cmake new file mode 100644 index 0000000..0f1d04f --- /dev/null +++ b/deps/polarssl/android.cmake @@ -0,0 +1,17 @@ +# this one is important +SET(CMAKE_SYSTEM_NAME Linux) +#this one not so much +SET(CMAKE_SYSTEM_VERSION 1) + +# specify the cross compiler (assumes that PATH already points to android toolchain) +SET(CMAKE_C_COMPILER gcc) +SET(CMAKE_CXX_COMPILER g++) + +# where is the target environment +#SET(CMAKE_FIND_ROOT_PATH /opt/eldk-2007-01-19/ppc_74xx /home/alex/eldk-ppc74xx-inst) + +# search for programs in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/deps/polarssl/apple.cmake b/deps/polarssl/apple.cmake new file mode 100644 index 0000000..2b58f24 --- /dev/null +++ b/deps/polarssl/apple.cmake @@ -0,0 +1,4 @@ +# specify the cross compiler +SET(CMAKE_C_COMPILER clang) +SET(CMAKE_CXX_COMPILER clang++) +SET(CMAKE_COMPILER_IS_GNUCC 1) diff --git a/deps/polarssl/bignum-arm.patch b/deps/polarssl/bignum-arm.patch new file mode 100644 index 0000000..12178ae --- /dev/null +++ b/deps/polarssl/bignum-arm.patch @@ -0,0 +1,32 @@ +diff -uNr polarssl-1.2.7/include/polarssl/bn_mul.h polarssl-1.2.7.new/include/polarssl/bn_mul.h +--- polarssl-1.2.7/include/polarssl/bn_mul.h 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl-1.2.7.new/include/polarssl/bn_mul.h 2013-06-13 16:30:35.000000000 -0600 +@@ -548,7 +548,7 @@ + + #if defined(__arm__) + +-#if defined(__thumb__) ++#if defined(__thumb__) && !defined(__thumb2__) + + #define MULADDC_INIT \ + asm( \ +diff -uNr polarssl-1.2.7/library/bignum.c polarssl-1.2.7.new/library/bignum.c +--- polarssl-1.2.7/library/bignum.c 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl-1.2.7.new/library/bignum.c 2013-06-13 16:30:35.000000000 -0600 +@@ -935,7 +935,15 @@ + /* + * Helper for mpi multiplication + */ +-static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) ++static ++#if defined(__APPLE__) && defined(__arm__) ++/* ++ * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) ++ * appears to need this to prevent bad ARM code generation at -O3. ++ */ ++__attribute__ ((noinline)) ++#endif ++void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) + { + t_uint c = 0, t = 0; + diff --git a/deps/polarssl/build-detail-patch b/deps/polarssl/build-detail-patch new file mode 100755 index 0000000..a71e342 --- /dev/null +++ b/deps/polarssl/build-detail-patch @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -e +. $O3/core/deps/lib-versions +POLARSSL_SRC=$HOME/src/mac/$POLARSSL_VERSION +PD=$O3/core/deps/polarssl +PB=$(basename $POLARSSL_SRC) + +rm -rf polartmp +mkdir polartmp +cd polartmp +cp -a $POLARSSL_SRC polarssl.new + +# extract the PolarSSL source +tar xfz $DL/$PB-gpl.tgz + +cd $PB +rm $(find . -type f | grep -E 'Makefile|\.orig$|\.rej$') +rm -f CMakeLists.txt include/polarssl/config.h include/polarssl/openvpn-polarssl.h + +cd ../polarssl.new +rm -f CMakeLists.txt include/polarssl/config.h include/polarssl/openvpn-polarssl.h +cd .. + +diff -ur $PB polarssl.new | grep -v '^Only in' diff --git a/deps/polarssl/build-mini-openssl b/deps/polarssl/build-mini-openssl new file mode 100755 index 0000000..6ecf736 --- /dev/null +++ b/deps/polarssl/build-mini-openssl @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Examples: +# $O3/core/deps/polarssl/build-mini-openssl ref +# $O3/core/deps/polarssl/build-mini-openssl ref-aesni + +set -e +if [ -z "$1" ]; then + echo "usage: build-mini-openssl " + exit 1 +fi +if [ -z "$OPENSSL_DIR" ]; then + echo OPENSSL_DIR must be defined + exit 1 +fi + +if [ "$APPLE_FAMILY" = "1" ] && [ -z "$GCC_CMD" ]; then + GCC_CMD=clang +fi + +if [ "$APPLE_FAMILY" = "1" ]; then + NM_FLAGS=-P + BSD_SYMBOLS="1" + VISIBILITY="-fvisibility=hidden" +else + NM_FLAGS="-f posix" + BSD_SYMBOLS="0" + VISIBILITY="" +fi + +[ -z "$NM_CMD" ] && NM_CMD=nm +[ -z "$AR_CMD" ] && AR_CMD=ar +[ -z "$GCC_CMD" ] && GCC_CMD=gcc +PD=$O3/core/deps/polarssl +cd $OPENSSL_DIR +cd lib +rm -rf tmp +mkdir tmp +$NM_CMD $NM_FLAGS libcrypto.a >tmp/nm-file +echo "NOTE: on BSD systems, don't worry about any 'no name list' errors above" +cd tmp +python $O3/common/scripts/sym.py $PD/$1 nm-file $AR_CMD ../libcrypto.a libminicrypto.a buildmini ../mini-undef.sh $BSD_SYMBOLS +. buildmini + +# need any special initialization? +. ../mini-undef.sh +if [ "$SYM_UNDEF_OPENSSL_ia32cap_P" ] && [ "$SYM_UNDEF_OPENSSL_cpuid_setup" ]; then + echo BUILDING STUB intel_cpu.c + $GCC_CMD $VISIBILITY $LIB_OPT_LEVEL $LIB_FPIC -c $PD/intel_cpu.c + $AR_CMD rs libminicrypto.a intel_cpu.o +fi + +mv libminicrypto.a .. diff --git a/deps/polarssl/build-polarssl b/deps/polarssl/build-polarssl new file mode 100755 index 0000000..dad7a23 --- /dev/null +++ b/deps/polarssl/build-polarssl @@ -0,0 +1,167 @@ +#!/usr/bin/env bash +# +# Parameters: +# CMAKE_TARGET -- use $CMAKE_TARGET.cmake as toolchain file +# AES_NI=1 -- enable AES_NI processor optimization +# EXTERNAL_RNG=1 -- disable all internal RNG implementations (caller must provide) +# ENABLE_TESTING=1 -- run PolarSSL test scripts after build +# DEBUG_BUILD=1 or SELF_TEST=1 -- enable minimal testing on target +# ENABLE_SERVER=1 -- enable SSL/TLS server code +# ENABLE_FS_IO=1 -- enable PolarSSL file I/O +# VERBOSE=1 -- see build commands +# USE_MINICRYPTO=1 -- use minicrypto library +# NO_WIPE=1 -- don't wipe source tree and reunzip tarball +# STOCK_CONFIG=1 -- use stock PolarSSL config.h + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi + +# source vars +. $O3/core/vars/vars-${TARGET} +. $O3/core/deps/lib-versions + +# extract the PolarSSL source +PD=$O3/core/deps/polarssl +DIST=polarssl-$PLATFORM + +rm -rf $DIST +mkdir $DIST + +if [ "$NO_WIPE" = "1" ]; then + echo RETAIN existing source + cd $POLARSSL_VERSION +elif [ "$NO_WIPE" = "partial" ]; then + echo RETAIN existing source but copy config.h and CMakeLists.txt + cd $POLARSSL_VERSION + + # define configs + if [ "$STOCK_CONFIG" != "1" ]; then + cp $PD/config.h include/polarssl/ + fi + cp $PD/CMakeLists.txt . +else + echo WIPE and reunzip source + rm -rf $POLARSSL_VERSION $POLARSSL_VERSION-prerelease + [ -z "$DL" ] && DL=~/Downloads + tar xfz $DL/$POLARSSL_VERSION-gpl.tgz + + [ -d $POLARSSL_VERSION-prerelease ] && mv $POLARSSL_VERSION-prerelease $POLARSSL_VERSION + cd $POLARSSL_VERSION + + # delete makefiles (apparently not needed) + rm $(find . -type f | grep Makefile) + + patch -p1 <$PD/relaxed-x509-date.patch + #patch -p1 <$PD/dhm.patch + #patch -p1 <$PD/entropy-printf.patch + + if [ "$USE_MINICRYPTO" = "1" ]; then + # do the big polar-openssl patch + echo MERGING polarssl-minicrypto.patch + patch -p1 <$PD/polarssl-minicrypto.patch + fi + + # define configs + cp include/polarssl/config.h include/polarssl/config.h.orig + cp CMakeLists.txt CMakeLists.txt.orig + cp $PD/config.h include/polarssl/ + cp $PD/CMakeLists.txt . +fi + +# dynamically generated header file with options, +# included by config.h +OPC=include/polarssl/openvpn-polarssl.h +echo '/* Automatically generated by ovpn3/core/deps/polarssl/build-polarssl, do not edit */' >$OPC + +# set options +OPT="" + +# relaxed cert checking +echo "#define POLARSSL_RELAXED_X509_DATE" >>$OPC + +# RNG +if [ "$EXTERNAL_RNG" = "1" ]; then + echo "#define EXTERNAL_RNG" >>$OPC +fi + +# enable full testing infrastructure +if [ "$ENABLE_TESTING" = "1" ]; then + OPT="$OPT -DENABLE_TESTING=1" + echo "#define ENABLE_TESTING" >>$OPC +fi + +# enable minimal testing on target +if [ "$DEBUG_BUILD" = "1" ] || [ "$SELF_TEST" = "1" ]; then + echo "#define POLARSSL_SELF_TEST" >>$OPC +fi + +# configure target +if [ "$CMAKE_TARGET" ]; then + OPT="$OPT -DCMAKE_TOOLCHAIN_FILE=$PD/$CMAKE_TARGET.cmake" +elif [ "$APPLE_FAMILY" = "1" ]; then + OPT="$OPT -DCMAKE_TOOLCHAIN_FILE=$PD/apple.cmake" +fi + +# Minicrypto +if [ "$USE_MINICRYPTO" = "1" ]; then + OPT="$OPT -DMINICRYPTO=1" + if [ "$MINICRYPTO_DIR" ]; then + OPT="$OPT -DMINICRYPTO_DIR=$MINICRYPTO_DIR" + fi + if [ "$OSSLCRYPTO_DIR" ]; then + OPT="$OPT -DOSSLCRYPTO_DIR=$OSSLCRYPTO_DIR" + fi + if [ "$MINICRYPTO_NO_AES" != "1" ]; then + echo "#define POLARSSL_AES_ALT" >>$OPC + fi + echo "#define POLARSSL_SHA1_ALT" >>$OPC + echo "#define POLARSSL_SHA256_ALT" >>$OPC + echo "#define POLARSSL_SHA512_ALT" >>$OPC + if [ "$AES_NI" = "1" ] && [ "$MINICRYPTO_NO_AES" != "1" ]; then + echo "#define POLARSSL_USE_OPENSSL_AES_NI" >>$OPC + fi +fi + +# Enable SSL/TLS server +if [ "$ENABLE_SERVER" = "1" ]; then + echo "#define POLARSSL_SSL_SRV_C" >>$OPC +fi + +# enable PolarSSL file I/O +if [ "$ENABLE_FS_IO" = "1" ]; then + echo "#define POLARSSL_FS_IO" >>$OPC +fi + +# Build shared library +if [ "$SHARED" = "1" ]; then + OPT="$OPT -DUSE_SHARED_POLARSSL_LIBRARY=1" +fi + +# echo options +echo OPTIONS $OPT + +# build it +pwd +cd ../$DIST +cmake $OPT ../$POLARSSL_VERSION +if [ "$VERBOSE" = "1" ]; then + make VERBOSE=1 +else + make +fi + +# test it +if [ "$ENABLE_TESTING" = "1" ]; then + make test +fi + +# copy headers +cp -a ../$POLARSSL_VERSION/include/polarssl include/ +exit 0 diff --git a/deps/polarssl/build-polarssl-patch b/deps/polarssl/build-polarssl-patch new file mode 100755 index 0000000..1562ac2 --- /dev/null +++ b/deps/polarssl/build-polarssl-patch @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -e +. $O3/core/deps/lib-versions +POLARSSL_SRC=$HOME/src/mac/$POLARSSL_VERSION +PD=$O3/core/deps/polarssl +PB=$(basename $POLARSSL_SRC) + +rm -rf polartmp +mkdir polartmp +cd polartmp +cp -a $POLARSSL_SRC polarssl.new + +# extract the PolarSSL source +tar xfz $DL/$PB-gpl.tgz + +cd $PB +rm $(find . -type f | grep -E 'Makefile|\.orig$|\.rej$') +rm -f CMakeLists.txt include/polarssl/config.h include/polarssl/openvpn-polarssl.h + +cd ../polarssl.new +rm -f CMakeLists.txt include/polarssl/config.h include/polarssl/openvpn-polarssl.h +cd .. + +if [ "$CRYPTO_ALT_PATCH" = "1" ]; then + diff -uNr $PB polarssl.new >$PD/polar-openssl.patch + cp $PD/crypto-alt.txt $PD/polarssl-crypto-alt.patch + diff -ur $PB polarssl.new | grep -v '^Only in' >>$PD/polarssl-crypto-alt.patch +else + diff -ur $PB polarssl.new | grep -v '^Only in' +fi diff --git a/deps/polarssl/config.h b/deps/polarssl/config.h new file mode 100644 index 0000000..482b3ed --- /dev/null +++ b/deps/polarssl/config.h @@ -0,0 +1,2227 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#include + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * Uncomment if native integers are 8-bit wide. + */ +//#define POLARSSL_HAVE_INT8 + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * Uncomment if native integers are 16-bit wide. + */ +//#define POLARSSL_HAVE_INT16 + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define POLARSSL_HAVE_SSE2 + +/** + * \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 + * + * System supports the basic socket interface for IPv6 (RFC 3493), + * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. + * + * Note: on Windows/MingW, XP or higher is required. + * + * Comment if your system does not support the IPv6 socket interface + */ +#define POLARSSL_HAVE_IPV6 + +/** + * \def POLARSSL_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * 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_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 */ + +/** + * \name SECTION: PolarSSL feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_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 + * + * Uncomment a macro to let PolarSSL use your alternate core implementation of + * a symmetric or hash algorithm (e.g. platform specific assembly optimized + * implementations). Keep in mind that the function prototypes should remain + * the same. + * + * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer + * provide the "struct aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation for core algorithm + * functions + */ +//#define POLARSSL_AES_ALT +//#define POLARSSL_ARC4_ALT +//#define POLARSSL_BLOWFISH_ALT +//#define POLARSSL_CAMELLIA_ALT +//#define POLARSSL_DES_ALT +//#define POLARSSL_XTEA_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 + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + * + */ +//#define POLARSSL_AES_ROM_TABLES + +/** + * \def POLARSSL_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CBC + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +// JY removed +//#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * 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_ECDHE_PSK_WITH_NULL_SHA256 + * TLS_ECDHE_PSK_WITH_NULL_SHA + * TLS_DHE_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_NULL_SHA256 + * TLS_DHE_PSK_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_PSK_WITH_NULL_SHA384 + * TLS_RSA_PSK_WITH_NULL_SHA256 + * TLS_RSA_PSK_WITH_NULL_SHA + * TLS_PSK_WITH_NULL_SHA384 + * TLS_PSK_WITH_NULL_SHA256 + * TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define POLARSSL_CIPHER_NULL_CIPHER + +/** + * \def POLARSSL_CIPHER_PADDING_XXX + * + * Uncomment or comment macros to add support for specific padding modes + * in the cipher layer with cipher modes that support padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define POLARSSL_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to 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. + */ +// JY added -- crypto +#define POLARSSL_REMOVE_ARC4_CIPHERSUITES + +/** + * \def POLARSSL_ECP_XXXX_ENABLED + * + * Enables specific curves within the Elliptic Curve module. + * By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define POLARSSL_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_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 + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#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 + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * 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_128_GCM_SHA256 + * 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_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +// JY removed -- PSK +//#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + */ +// JY removed -- PSK +//#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +// JY removed -- PSK +//#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_RC4_128_SHA + */ +// JY removed -- PSK +//#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + */ +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#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() + */ +// JY removed +//#define POLARSSL_ERROR_STRERROR_BC + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of polarssl_strerror() in + * 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() + */ +#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: POLARSSL_BIGNUM_C + */ +#define POLARSSL_GENPRIME + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. + */ +// JY removed +//#define POLARSSL_FS_IO + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define POLARSSL_NO_PLATFORM_ENTROPY + +// JY added +#ifdef EXTERNAL_RNG +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES +#define POLARSSL_NO_PLATFORM_ENTROPY +#endif + +/** + * \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 + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define POLARSSL_MEMORY_DEBUG + +/** + * \def POLARSSL_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define POLARSSL_MEMORY_BACKTRACE + +/** + * \def POLARSSL_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: POLARSSL_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define POLARSSL_PKCS1_V15 + +/** + * \def POLARSSL_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define POLARSSL_PKCS1_V21 + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define POLARSSL_RSA_NO_CRT + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +// JY changed +#if defined(ENABLE_TESTING) && !defined(POLARSSL_SELF_TEST) +#define POLARSSL_SELF_TEST +#endif + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, PolarSSL can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define POLARSSL_SSL_DEBUG_ALL + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define POLARSSL_SSL_HW_RECORD_ACCEL + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C). + * + * Comment this macro to disable support for SSLv2 Client Hello messages. + */ +// JY removed +//#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 + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def POLARSSL_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +#define POLARSSL_SSL_PROTO_SSL3 + +/** + * \def POLARSSL_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define POLARSSL_SSL_PROTO_TLS1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 + */ +#define POLARSSL_SSL_PROTO_TLS1_1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2. + * + * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 + */ +#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 + * + * Enable support for RFC 5077 session tickets in SSL. + * + * Requires: POLARSSL_AES_C + * POLARSSL_SHA256_C + * POLARSSL_CIPHER_MODE_CBC + * + * Comment this macro to disable support for SSL session tickets + */ +// JY removed +//#define POLARSSL_SSL_SESSION_TICKETS + +/** + * \def POLARSSL_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Comment this macro to disable support for server name indication in SSL + */ +#define POLARSSL_SSL_SERVER_NAME_INDICATION + +/** + * \def POLARSSL_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define POLARSSL_SSL_TRUNCATED_HMAC + +/** + * \def POLARSSL_SSL_SET_CURVES + * + * Enable ssl_set_curves(). + * + * 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 to make ssl_set_curves() available. + */ +//#define POLARSSL_SSL_SET_CURVES + +/** + * \def POLARSSL_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define POLARSSL_THREADING_ALT + +/** + * \def POLARSSL_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#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 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +// JY Added +#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + */ +// JY Added +#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 + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define POLARSSL_ZLIB_SUPPORT +/* \} name SECTION: PolarSSL feature support */ + +/** + * \name SECTION: PolarSSL modules + * + * This section enables or disables entire modules in PolarSSL + * \{ + */ + +/** + * \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 + */ +// JY added +#ifndef POLARSSL_AES_ALT +#define POLARSSL_AESNI_C +#endif + +/** + * \def POLARSSL_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (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 + * 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_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_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_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define POLARSSL_AES_C + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (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 + * TLS_DHE_PSK_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_PSK_WITH_RC4_128_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +// JY removed -- crypto +//#define POLARSSL_ARC4_C + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * 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, DHM and ECC (ECDH, ECDSA) support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.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 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * 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_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +// JY removed -- crypto +//#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 + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * Requires: POLARSSL_PEM_PARSE_C + * + * This module is used for testing (ssl_client/server). + */ +// JY changed +#ifdef ENABLE_TESTING +#define POLARSSL_CERTS_C +#endif + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +// JY added +#ifndef EXTERNAL_RNG +#define POLARSSL_CTR_DRBG_C +#endif + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.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 + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: POLARSSL_ECP_C + */ +#define POLARSSL_ECDH_C + +/** + * \def POLARSSL_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C + */ +#define POLARSSL_ECDSA_C + +/** + * \def POLARSSL_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * + * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED + */ +#define POLARSSL_ECP_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C + * + * This module provides a generic entropy pool + */ +#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables polarssl_strerror(). + */ +#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#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 + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define POLARSSL_MD2_C + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +// JY Added for NTLM proxy auth +#define POLARSSL_MD4_C + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define POLARSSL_MD5_C + +/** + * \def POLARSSL_MEMORY_C + * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead. + */ +//#define POLARSSL_MEMORY_C + +/** + * \def POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: POLARSSL_PLATFORM_C + * POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define POLARSSL_MEMORY_BUFFER_ALLOC_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * + * This module provides TCP/IP networking routines. + */ +// JY removed +//#define POLARSSL_NET_C + +/** + * \def POLARSSL_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define POLARSSL_OID_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: POLARSSL_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +// JY removed +//#define POLARSSL_PADLOCK_C + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function. + * DEPRECATED: Use POLARSSL_PKCS5_C instead + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_PKCS5_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. + */ +#define POLARSSL_PBKDF2_C + +/** + * \def POLARSSL_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define POLARSSL_PEM_PARSE_C + +/** + * \def POLARSSL_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define POLARSSL_PEM_WRITE_C + +/** + * \def POLARSSL_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define POLARSSL_PK_C + +/** + * \def POLARSSL_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define POLARSSL_PK_PARSE_C + +/** + * \def POLARSSL_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key write functions. + */ +// JY removed -- PKI +//#define POLARSSL_PK_WRITE_C + +/** + * \def POLARSSL_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define POLARSSL_PKCS5_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: POLARSSL_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define POLARSSL_PKCS11_C + +/** + * \def POLARSSL_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C + * Can use: POLARSSL_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#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 + * + */ +// JY removed +//#define POLARSSL_RIPEMD160_C + +/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C + */ +#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/** + * \def POLARSSL_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA2_C) + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA256_C + +/** + * \def POLARSSL_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA4_C) + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA512_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +// JY removed +//#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +// JY removed -- server +//#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C + * and at least one of the POLARSSL_SSL_PROTO_* defines + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_THREADING_C + * + * Enable the threading abstraction layer. + * By default PolarSSL assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either POLARSSL_THREADING_ALT or + * POLARSSL_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within PolarSSL + */ +//#define POLARSSL_THREADING_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +// JY removed +//#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, + * POLARSSL_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define POLARSSL_X509_USE_C + +/** + * \def POLARSSL_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define POLARSSL_X509_CRT_PARSE_C + +/** + * \def POLARSSL_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define POLARSSL_X509_CRL_PARSE_C + +/** + * \def POLARSSL_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +// JY removed -- PKI +//#define POLARSSL_X509_CSR_PARSE_C + +/** + * \def POLARSSL_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +// JY removed -- PKI +//#define POLARSSL_X509_CREATE_C + +/** + * \def POLARSSL_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +// JY removed -- PKI +//#define POLARSSL_X509_CRT_WRITE_C + +/** + * \def POLARSSL_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +// JY removed -- PKI +//#define POLARSSL_X509_CSR_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +// JY removed -- crypto +//#define POLARSSL_XTEA_C + +/* \} name SECTION: PolarSSL modules */ + +/** + * \name SECTION: Module configuration options + * + * 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 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). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define POLARSSL_MPI_MAX_SIZE 1024 /**< 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 */ + +/* 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 */ + +/* 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 */ + +/* Entropy options */ +//#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +/* Memory buffer allocator options */ +//#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define POLARSSL_PLATFORM_STD_MEM_HDR /**< 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 */ + +/* SSL Cache options */ +//#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* 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) */ + +/** + * 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. + */ +//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* Debug options */ +//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ + +/* \} name SECTION: Module configuration options */ + +#include "check_config.h" + +#endif /* POLARSSL_CONFIG_H */ diff --git a/deps/polarssl/config.h.orig b/deps/polarssl/config.h.orig new file mode 100644 index 0000000..50b4e33 --- /dev/null +++ b/deps/polarssl/config.h.orig @@ -0,0 +1,2180 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * Uncomment if native integers are 8-bit wide. + */ +//#define POLARSSL_HAVE_INT8 + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * Uncomment if native integers are 16-bit wide. + */ +//#define POLARSSL_HAVE_INT16 + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + * Comment to disable the use of assembly code. + */ +#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define POLARSSL_HAVE_SSE2 + +/** + * \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 + * + * System supports the basic socket interface for IPv6 (RFC 3493), + * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. + * + * Note: on Windows/MingW, XP or higher is required. + * + * Comment if your system does not support the IPv6 socket interface + */ +#define POLARSSL_HAVE_IPV6 + +/** + * \def POLARSSL_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * 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_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 */ + +/** + * \name SECTION: PolarSSL feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_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 + * + * Uncomment a macro to let PolarSSL use your alternate core implementation of + * a symmetric or hash algorithm (e.g. platform specific assembly optimized + * implementations). Keep in mind that the function prototypes should remain + * the same. + * + * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer + * provide the "struct aes_context" definition and omit the base function + * declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation for core algorithm + * functions + */ +//#define POLARSSL_AES_ALT +//#define POLARSSL_ARC4_ALT +//#define POLARSSL_BLOWFISH_ALT +//#define POLARSSL_CAMELLIA_ALT +//#define POLARSSL_DES_ALT +//#define POLARSSL_XTEA_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 + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + * + */ +//#define POLARSSL_AES_ROM_TABLES + +/** + * \def POLARSSL_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CBC + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * 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_ECDHE_PSK_WITH_NULL_SHA256 + * TLS_ECDHE_PSK_WITH_NULL_SHA + * TLS_DHE_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_NULL_SHA256 + * TLS_DHE_PSK_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_PSK_WITH_NULL_SHA384 + * TLS_RSA_PSK_WITH_NULL_SHA256 + * TLS_RSA_PSK_WITH_NULL_SHA + * TLS_PSK_WITH_NULL_SHA384 + * TLS_PSK_WITH_NULL_SHA256 + * TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define POLARSSL_CIPHER_NULL_CIPHER + +/** + * \def POLARSSL_CIPHER_PADDING_XXX + * + * Uncomment or comment macros to add support for specific padding modes + * in the cipher layer with cipher modes that support padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define POLARSSL_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to 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 + * + * Enables specific curves within the Elliptic Curve module. + * By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define POLARSSL_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_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 + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#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 + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * 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_128_GCM_SHA256 + * 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_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + */ +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, + * POLARSSL_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#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() + */ +#define POLARSSL_ERROR_STRERROR_BC + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of polarssl_strerror() in + * 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() + */ +#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: POLARSSL_BIGNUM_C + */ +#define POLARSSL_GENPRIME + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. + */ +#define POLARSSL_FS_IO + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define POLARSSL_NO_PLATFORM_ENTROPY + +/** + * \def POLARSSL_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 + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define POLARSSL_MEMORY_DEBUG + +/** + * \def POLARSSL_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define POLARSSL_MEMORY_BACKTRACE + +/** + * \def POLARSSL_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: POLARSSL_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define POLARSSL_PKCS1_V15 + +/** + * \def POLARSSL_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define POLARSSL_PKCS1_V21 + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define POLARSSL_RSA_NO_CRT + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define POLARSSL_SELF_TEST + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, PolarSSL can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define POLARSSL_SSL_DEBUG_ALL + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define POLARSSL_SSL_HW_RECORD_ACCEL + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C). + * + * Comment this macro to disable support for SSLv2 Client Hello 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 + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def POLARSSL_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +#define POLARSSL_SSL_PROTO_SSL3 + +/** + * \def POLARSSL_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define POLARSSL_SSL_PROTO_TLS1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1. + * + * Requires: POLARSSL_MD5_C + * POLARSSL_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 + */ +#define POLARSSL_SSL_PROTO_TLS1_1 + +/** + * \def POLARSSL_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2. + * + * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 + */ +#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 + * + * Enable support for RFC 5077 session tickets in SSL. + * + * Requires: POLARSSL_AES_C + * POLARSSL_SHA256_C + * POLARSSL_CIPHER_MODE_CBC + * + * Comment this macro to disable support for SSL session tickets + */ +#define POLARSSL_SSL_SESSION_TICKETS + +/** + * \def POLARSSL_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Comment this macro to disable support for server name indication in SSL + */ +#define POLARSSL_SSL_SERVER_NAME_INDICATION + +/** + * \def POLARSSL_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define POLARSSL_SSL_TRUNCATED_HMAC + +/** + * \def POLARSSL_SSL_SET_CURVES + * + * Enable ssl_set_curves(). + * + * 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 to make ssl_set_curves() available. + */ +//#define POLARSSL_SSL_SET_CURVES + +/** + * \def POLARSSL_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define POLARSSL_THREADING_ALT + +/** + * \def POLARSSL_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: POLARSSL_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#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 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + */ +//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \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 + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define POLARSSL_ZLIB_SUPPORT +/* \} name SECTION: PolarSSL feature support */ + +/** + * \name SECTION: PolarSSL modules + * + * This section enables or disables entire modules in PolarSSL + * \{ + */ + +/** + * \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 + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (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 + * 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_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_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_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA256 + * TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define POLARSSL_AES_C + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (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 + * TLS_DHE_PSK_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_SHA + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_PSK_WITH_RC4_128_SHA + * TLS_PSK_WITH_RC4_128_SHA + */ +#define POLARSSL_ARC4_C + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * 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, DHM and ECC (ECDH, ECDSA) support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.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 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * 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_CAMELLIA_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#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 + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * Requires: POLARSSL_PEM_PARSE_C + * + * This module is used for testing (ssl_client/server). + */ +#define POLARSSL_CERTS_C + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define POLARSSL_CTR_DRBG_C + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.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 + * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ +#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: POLARSSL_ECP_C + */ +#define POLARSSL_ECDH_C + +/** + * \def POLARSSL_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C + */ +#define POLARSSL_ECDSA_C + +/** + * \def POLARSSL_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * + * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED + */ +#define POLARSSL_ECP_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C + * + * This module provides a generic entropy pool + */ +#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables polarssl_strerror(). + */ +#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#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 + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define POLARSSL_MD2_C + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define POLARSSL_MD4_C + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ +#define POLARSSL_MD5_C + +/** + * \def POLARSSL_MEMORY_C + * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead. + */ +//#define POLARSSL_MEMORY_C + +/** + * \def POLARSSL_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: POLARSSL_PLATFORM_C + * POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define POLARSSL_MEMORY_BUFFER_ALLOC_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * + * This module provides TCP/IP networking routines. + */ +#define POLARSSL_NET_C + +/** + * \def POLARSSL_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define POLARSSL_OID_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * 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 + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function. + * DEPRECATED: Use POLARSSL_PKCS5_C instead + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_PKCS5_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. + */ +#define POLARSSL_PBKDF2_C + +/** + * \def POLARSSL_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define POLARSSL_PEM_PARSE_C + +/** + * \def POLARSSL_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define POLARSSL_PEM_WRITE_C + +/** + * \def POLARSSL_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define POLARSSL_PK_C + +/** + * \def POLARSSL_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define POLARSSL_PK_PARSE_C + +/** + * \def POLARSSL_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: POLARSSL_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define POLARSSL_PK_WRITE_C + +/** + * \def POLARSSL_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define POLARSSL_PKCS5_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: POLARSSL_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define POLARSSL_PKCS11_C + +/** + * \def POLARSSL_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C + * Can use: POLARSSL_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#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 + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C + */ +#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/** + * \def POLARSSL_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA2_C) + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA256_C + +/** + * \def POLARSSL_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * (Used to be POLARSSL_SHA4_C) + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA512_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C + * and at least one of the POLARSSL_SSL_PROTO_* defines + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_THREADING_C + * + * Enable the threading abstraction layer. + * By default PolarSSL assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either POLARSSL_THREADING_ALT or + * POLARSSL_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within PolarSSL + */ +//#define POLARSSL_THREADING_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, + * POLARSSL_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define POLARSSL_X509_USE_C + +/** + * \def POLARSSL_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define POLARSSL_X509_CRT_PARSE_C + +/** + * \def POLARSSL_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define POLARSSL_X509_CRL_PARSE_C + +/** + * \def POLARSSL_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: POLARSSL_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define POLARSSL_X509_CSR_PARSE_C + +/** + * \def POLARSSL_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define POLARSSL_X509_CREATE_C + +/** + * \def POLARSSL_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define POLARSSL_X509_CRT_WRITE_C + +/** + * \def POLARSSL_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: POLARSSL_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define POLARSSL_X509_CSR_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#define POLARSSL_XTEA_C + +/* \} name SECTION: PolarSSL modules */ + +/** + * \name SECTION: Module configuration options + * + * 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 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). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define POLARSSL_MPI_MAX_SIZE 1024 /**< 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 */ + +/* 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 */ + +/* 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 */ + +/* Entropy options */ +//#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + +/* Memory buffer allocator options */ +//#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define POLARSSL_PLATFORM_STD_MEM_HDR /**< 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 */ + +/* SSL Cache options */ +//#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* 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) */ + +/** + * 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. + */ +//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* Debug options */ +//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ + +/* \} name SECTION: Module configuration options */ + +#include "check_config.h" + +#endif /* POLARSSL_CONFIG_H */ diff --git a/deps/polarssl/config12.h b/deps/polarssl/config12.h new file mode 100644 index 0000000..26fdf8b --- /dev/null +++ b/deps/polarssl/config12.h @@ -0,0 +1,959 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * Copyright (C) 2006-2012, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +#ifndef POLARSSL_CONFIG_H +#define POLARSSL_CONFIG_H + +#include + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def POLARSSL_HAVE_INT8 + * + * The system uses 8-bit wide native integers. + * + * Uncomment if native integers are 8-bit wide. +#define POLARSSL_HAVE_INT8 + */ + +/** + * \def POLARSSL_HAVE_INT16 + * + * The system uses 16-bit wide native integers. + * + * Uncomment if native integers are 16-bit wide. +#define POLARSSL_HAVE_INT16 + */ + +/** + * \def POLARSSL_HAVE_LONGLONG + * + * The compiler supports the 'long long' type. + * (Only used on 32-bit platforms) + */ +#define POLARSSL_HAVE_LONGLONG + +/** + * \def POLARSSL_HAVE_ASM + * + * The compiler has support for asm() + * + * Uncomment to enable the use of assembly code. + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/polarssl/bn_mul.h + * + */ +#define POLARSSL_HAVE_ASM + +/** + * \def POLARSSL_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + * +#define POLARSSL_HAVE_SSE2 + */ +/* \} name */ + +/** + * \name SECTION: PolarSSL feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def POLARSSL_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + * +#define POLARSSL_AES_ROM_TABLES + */ + +/** + * \def POLARSSL_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +// JY removed +//#define POLARSSL_CIPHER_MODE_CFB + +/** + * \def POLARSSL_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +// JY removed +//#define POLARSSL_CIPHER_MODE_CTR + +/** + * \def POLARSSL_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * TLS_RSA_WITH_NULL_MD5 + * TLS_RSA_WITH_NULL_SHA + * TLS_RSA_WITH_NULL_SHA256 + * + * Uncomment this macro to enable the NULL cipher and ciphersuites +#define POLARSSL_CIPHER_NULL_CIPHER + */ + +/** + * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * TLS_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES + */ + +/** + * \def POLARSSL_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of error_strerror() in + * third party libraries easier. + * + * Disable if you run into name conflicts and want to really remove the + * error_strerror() + */ +#define POLARSSL_ERROR_STRERROR_DUMMY + +/** + * \def POLARSSL_GENPRIME + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * Enable the RSA prime-number generation code. + */ +#define POLARSSL_GENPRIME + +/** + * \def POLARSSL_FS_IO + * + * Enable functions that use the filesystem. + */ +// JY removed +//#define POLARSSL_FS_IO + +/** + * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES + */ + +/** + * \def POLARSSL_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. +#define POLARSSL_NO_PLATFORM_ENTROPY + */ + +// JY added +#ifdef EXTERNAL_RNG +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES +#define POLARSSL_NO_PLATFORM_ENTROPY +#endif + +/** + * \def POLARSSL_PKCS1_V21 + * + * Requires: POLARSSL_MD_C, POLARSSL_RSA_C + * + * Enable support for PKCS#1 v2.1 encoding. + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define POLARSSL_PKCS1_V21 + +/** + * \def POLARSSL_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * +#define POLARSSL_RSA_NO_CRT + */ + +/** + * \def POLARSSL_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +// JY changed +#if defined(ENABLE_TESTING) && !defined(POLARSSL_SELF_TEST) +#define POLARSSL_SELF_TEST +#endif + +/** + * \def POLARSSL_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, PolarSSL can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define POLARSSL_SSL_ALERT_MESSAGES + +/** + * \def POLARSSL_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * +#define POLARSSL_SSL_DEBUG_ALL + */ + +/** + * \def POLARSSL_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. +#define POLARSSL_SSL_HW_RECORD_ACCEL + */ + +/** + * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (POLARSSL_SSL_SRV_C) + * + * Comment this macro to disable support for SSLv2 Client Hello messages. + */ +// JY removed +//#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * Uncomment to prevent an error. + * +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + */ + +/** + * \def POLARSSL_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB +#define POLARSSL_ZLIB_SUPPORT + */ +/* \} name */ + +/** + * \name SECTION: PolarSSL modules + * + * This section enables or disables entire modules in PolarSSL + * \{ + */ + +/** + * \def POLARSSL_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_128_CBC_SHA + * TLS_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_RSA_WITH_AES_128_CBC_SHA256 + * TLS_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_256_GCM_SHA384 + * + * PEM uses AES for decrypting encrypted keys. + */ +#define POLARSSL_AES_C + +/** + * \def POLARSSL_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites: + * TLS_RSA_WITH_RC4_128_MD5 + * TLS_RSA_WITH_RC4_128_SHA + */ +// JY removed +//#define POLARSSL_ARC4_C + +/** + * \def POLARSSL_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509parse.c + */ +#define POLARSSL_ASN1_PARSE_C + +/** + * \def POLARSSL_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + */ +// JY removed +//#define POLARSSL_ASN1_WRITE_C + +/** + * \def POLARSSL_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define POLARSSL_BASE64_C + +/** + * \def POLARSSL_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/rsa.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for RSA and DHM support. + */ +#define POLARSSL_BIGNUM_C + +/** + * \def POLARSSL_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define POLARSSL_BLOWFISH_C + +/** + * \def POLARSSL_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + */ +// JY removed +//#define POLARSSL_CAMELLIA_C + +/** + * \def POLARSSL_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +// JY changed +#ifdef ENABLE_TESTING +#define POLARSSL_CERTS_C +#endif + +/** + * \def POLARSSL_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: + * + * Uncomment to enable generic cipher wrappers. + */ +#define POLARSSL_CIPHER_C + +/** + * \def POLARSSL_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: POLARSSL_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +// JY added +#ifndef EXTERNAL_RNG +#define POLARSSL_CTR_DRBG_C +#endif + +/** + * \def POLARSSL_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define POLARSSL_DEBUG_C + +/** + * \def POLARSSL_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * PEM uses DES/3DES for decrypting encrypted keys. + */ +#define POLARSSL_DES_C + +/** + * \def POLARSSL_DHM_C + * + * Enable the Diffie-Hellman-Merkle key exchange. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_DHE_RSA_WITH_DES_CBC_SHA + * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + */ +#define POLARSSL_DHM_C + +/** + * \def POLARSSL_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: POLARSSL_SHA4_C + * + * This module provides a generic entropy pool + */ +#define POLARSSL_ENTROPY_C + +/** + * \def POLARSSL_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables err_strerror(). + */ +#define POLARSSL_ERROR_C + +/** + * \def POLARSSL_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES + * + * Module: library/gcm.c + * + * Requires: POLARSSL_AES_C + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * TLS_RSA_WITH_AES_128_GCM_SHA256 + * TLS_RSA_WITH_AES_256_GCM_SHA384 + */ +#define POLARSSL_GCM_C + +/** + * \def POLARSSL_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Module: library/havege.c + * Caller: + * + * Requires: POLARSSL_TIMING_C + * + * This module enables the HAVEGE random number generator. + */ +// JY removed +//#define POLARSSL_HAVEGE_C + +/** + * \def POLARSSL_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define POLARSSL_MD_C + +/** + * \def POLARSSL_MD2_C + * + * Enable the MD2 hash algorithm + * + * Module: library/md2.c + * Caller: library/x509parse.c + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * +#define POLARSSL_MD2_C + */ + +/** + * \def POLARSSL_MD4_C + * + * Enable the MD4 hash algorithm + * + * Module: library/md4.c + * Caller: library/x509parse.c + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + */ +// JY Added for NTLM proxy auth +#define POLARSSL_MD4_C + +/** + * \def POLARSSL_MD5_C + * + * Enable the MD5 hash algorithm + * + * Module: library/md5.c + * Caller: library/pem.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for SSL/TLS and X.509. + * PEM uses MD5 for decrypting encrypted keys. + */ +#define POLARSSL_MD5_C + +/** + * \def POLARSSL_NET_C + * + * Enable the TCP/IP networking routines. + * + * Module: library/net.c + * Caller: + * + * This module provides TCP/IP networking routines. + */ +// JY removed +//#define POLARSSL_NET_C + +/** + * \def POLARSSL_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * This modules adds support for the VIA PadLock on x86. + */ +// JY removed +//#define POLARSSL_PADLOCK_C + +/** + * \def POLARSSL_PBKDF2_C + * + * Enable PKCS#5 PBKDF2 key derivation function + * DEPRECATED: Use POLARSSL_PKCS5_C instead + * + * Module: library/pbkdf2.c + * + * Requires: POLARSSL_PKCS5_C + * + * This module adds support for the PKCS#5 PBKDF2 key derivation function. +#define POLARSSL_PBKDF2_C + */ + +/** + * \def POLARSSL_PEM_C + * + * Enable PEM decoding + * + * Module: library/pem.c + * Caller: library/x509parse.c + * + * Requires: POLARSSL_BASE64_C + * + * This modules adds support for decoding PEM files. + */ +#define POLARSSL_PEM_C + +/** + * \def POLARSSL_PKCS5_C + * + * Enable PKCS#5 functions + * + * Module: library/pkcs5.c + * + * Requires: POLARSSL_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define POLARSSL_PKCS5_C + +/** + * \def POLARSSL_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/ssl_srv.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) +#define POLARSSL_PKCS11_C + */ + +/** + * \def POLARSSL_PKCS12_C + * + * Enable PKCS#12 PBE functions + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/x509parse.c + * + * Requires: POLARSSL_ASN1_PARSE_C + * Can use: POLARSSL_SHA1_C, POLARSSL_DES_C, POLARSSL_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define POLARSSL_PKCS12_C + +/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * Requires: POLARSSL_BIGNUM_C + * + * This module is required for SSL/TLS and MD5-signed certificates. + */ +#define POLARSSL_RSA_C + +/** + * \def POLARSSL_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509parse.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define POLARSSL_SHA1_C + +/** + * \def POLARSSL_SHA2_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha2.c + * Caller: library/md_wrap.c + * library/x509parse.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define POLARSSL_SHA2_C + +/** + * \def POLARSSL_SHA4_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha4.c + * Caller: library/md_wrap.c + * library/x509parse.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define POLARSSL_SHA4_C + +/** + * \def POLARSSL_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: POLARSSL_SSL_CACHE_C + */ +// JY removed +//#define POLARSSL_SSL_CACHE_C + +/** + * \def POLARSSL_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define POLARSSL_SSL_CLI_C + +/** + * \def POLARSSL_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: POLARSSL_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +// JY removed +//#define POLARSSL_SSL_SRV_C + +/** + * \def POLARSSL_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C + * + * This module is required for SSL/TLS. + */ +#define POLARSSL_SSL_TLS_C + +/** + * \def POLARSSL_TIMING_C + * + * Enable the portable timing interface. + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +// JY removed +//#define POLARSSL_TIMING_C + +/** + * \def POLARSSL_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define POLARSSL_VERSION_C + +/** + * \def POLARSSL_X509_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509parse.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * This module is required for X.509 certificate parsing. + */ +#define POLARSSL_X509_PARSE_C + +/** + * \def POLARSSL_X509_WRITE_C + * + * Enable X.509 buffer writing. + * + * Module: library/x509write.c + * + * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C + * + * This module is required for X.509 certificate request writing. + */ +// JY removed +//#define POLARSSL_X509_WRITE_C + +/** + * \def POLARSSL_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +// JY removed +//#define POLARSSL_XTEA_C +/* \} name */ + +// JY added +#define POLARSSL_BLOWFISH_NAME "BF" +#define POLARSSL_BLOWFISH_DEFAULT_KEY_LEN 128 + +#endif /* config.h */ diff --git a/deps/polarssl/crypto-alt.txt b/deps/polarssl/crypto-alt.txt new file mode 100644 index 0000000..32fb2e6 --- /dev/null +++ b/deps/polarssl/crypto-alt.txt @@ -0,0 +1,16 @@ +This patch (against PolarSSL 1.2.7) allows alternative crypto +implementations to be compiled, without actually defining +such implementations. + +* define POLARSSL_AES_ALT to include alternative AES implementation + from polarssl/aes_alt.h + +* define POLARSSL_SHA1_ALT to include alternative SHA1 implementation + from polarssl/sha1_alt.h + +* define POLARSSL_SHA2_ALT to include alternative SHA2 implementation + from polarssl/sha2_alt.h + +* define POLARSSL_SHA4_ALT to include alternative SHA4 implementation + from polarssl/sha4_alt.h + diff --git a/deps/polarssl/dhm.patch b/deps/polarssl/dhm.patch new file mode 100644 index 0000000..43732f2 --- /dev/null +++ b/deps/polarssl/dhm.patch @@ -0,0 +1,12 @@ +diff -ur polarssl-1.3.4/library/dhm.c polarssl.new/library/dhm.c +--- polarssl-1.3.4/library/dhm.c 2014-01-27 05:36:23.000000000 -0700 ++++ polarssl.new/library/dhm.c 2014-03-02 14:47:02.000000000 -0700 +@@ -32,6 +32,8 @@ + + #if defined(POLARSSL_DHM_C) + ++#include "polarssl/x509.h" // for POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ++ + #include "polarssl/dhm.h" + + #if defined(POLARSSL_PEM_PARSE_C) diff --git a/deps/polarssl/entropy-printf.patch b/deps/polarssl/entropy-printf.patch new file mode 100644 index 0000000..9a5b288 --- /dev/null +++ b/deps/polarssl/entropy-printf.patch @@ -0,0 +1,12 @@ +diff -ur polarssl-1.3.8.orig/library/entropy.c polarssl-1.3.8/library/entropy.c +--- polarssl-1.3.8.orig/library/entropy.c 2014-07-09 03:34:48.000000000 -0600 ++++ polarssl-1.3.8/library/entropy.c 2014-07-09 16:27:06.000000000 -0600 +@@ -34,7 +34,7 @@ + #include "polarssl/entropy.h" + #include "polarssl/entropy_poll.h" + +-#if defined(POLARSSL_FS_IO) ++#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) + #include + #endif + diff --git a/deps/polarssl/gitar b/deps/polarssl/gitar new file mode 100755 index 0000000..d340407 --- /dev/null +++ b/deps/polarssl/gitar @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +. $O3/core/deps/lib-versions +rm -rf gitar.tmp +mkdir gitar.tmp +cd gitar.tmp +git clone https://github.com/polarssl/polarssl.git -b $POLARSSL_VERSION $POLARSSL_VERSION +tar cfz $DL/$POLARSSL_VERSION-gpl.tgz $POLARSSL_VERSION +cd .. +rm -rf gitar.tmp diff --git a/deps/polarssl/intel_cpu.c b/deps/polarssl/intel_cpu.c new file mode 100644 index 0000000..fea1eda --- /dev/null +++ b/deps/polarssl/intel_cpu.c @@ -0,0 +1,22 @@ +#if defined(_WIN32) +typedef unsigned __int64 IA32CAP; +#else +typedef unsigned long long IA32CAP; +#endif + +IA32CAP OPENSSL_ia32_cpuid(void); + +unsigned int OPENSSL_ia32cap_P[2]; // GLOBAL + +void OPENSSL_cpuid_setup(void) +{ + const IA32CAP vec = OPENSSL_ia32_cpuid(); + + /* + * |(1<<10) sets a reserved bit to signal that variable + * was initialized already... This is to avoid interference + * with cpuid snippets in ELF .init segment. + */ + OPENSSL_ia32cap_P[0] = (unsigned int)vec|(1<<10); + OPENSSL_ia32cap_P[1] = (unsigned int)(vec>>32); +} diff --git a/deps/polarssl/linux-arm.cmake b/deps/polarssl/linux-arm.cmake new file mode 100644 index 0000000..a356912 --- /dev/null +++ b/deps/polarssl/linux-arm.cmake @@ -0,0 +1,17 @@ +# this one is important +SET(CMAKE_SYSTEM_NAME Linux) +#this one not so much +SET(CMAKE_SYSTEM_VERSION 1) + +# specify the cross compiler +SET(CMAKE_C_COMPILER arm-linux-gnueabi-gcc-4.6) +SET(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++-4.6) + +# where is the target environment +#SET(CMAKE_FIND_ROOT_PATH /opt/eldk-2007-01-19/ppc_74xx /home/alex/eldk-ppc74xx-inst) + +# search for programs in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/deps/polarssl/polar-openssl.patch b/deps/polarssl/polar-openssl.patch new file mode 100644 index 0000000..9601b14 --- /dev/null +++ b/deps/polarssl/polar-openssl.patch @@ -0,0 +1,782 @@ +diff -uNr polarssl-1.2.7/include/polarssl/aes.h polarssl.new/include/polarssl/aes.h +--- polarssl-1.2.7/include/polarssl/aes.h 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/include/polarssl/aes.h 2013-06-07 17:43:56.000000000 -0600 +@@ -29,6 +29,8 @@ + + #include + ++#include "config.h" ++ + #ifdef _MSC_VER + #include + typedef UINT32 uint32_t; +@@ -42,6 +44,12 @@ + #define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ + #define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + ++#ifdef POLARSSL_AES_ALT ++ ++#include "polarssl/aes_alt.h" ++ ++#else ++ + /** + * \brief AES context structure + */ +@@ -169,6 +177,17 @@ + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* POLARSSL_AES_ALT */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ + /** + * \brief Checkup routine + * +diff -uNr polarssl-1.2.7/include/polarssl/aes_alt.h polarssl.new/include/polarssl/aes_alt.h +--- polarssl-1.2.7/include/polarssl/aes_alt.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/aes_alt.h 2013-06-07 18:18:37.000000000 -0600 +@@ -0,0 +1,183 @@ ++/* ++ * Use OpenSSL implementation of AES methods to get asm and hardware acceleration. ++ * Don't include this file directly, it is included by aes.h when ++ * POLARSSL_AES_ALT is defined. ++ */ ++ ++#ifdef _MSC_VER ++#include ++typedef UINT32 uint32_t; ++#else ++#include ++#endif ++ ++#define OPENSSL_AES_BLOCK_SIZE 16 ++#define OPENSSL_AES_MAXNR 14 ++ ++/** ++ * \brief AES context structure ++ */ ++typedef struct ++{ ++ uint32_t rd_key[4 * (OPENSSL_AES_MAXNR + 1)]; ++ int rounds; ++} ++aes_context; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#if defined(POLARSSL_USE_OPENSSL_AES_NI) ++ ++int aesni_set_encrypt_key(const unsigned char *userKey, const int bits, ++ aes_context *key); ++int aesni_set_decrypt_key(const unsigned char *userKey, const int bits, ++ aes_context *key); ++void aesni_ecb_encrypt(const unsigned char *in, unsigned char *out, ++ size_t length, const aes_context *key, const int enc); ++void aesni_cbc_encrypt(const unsigned char *in, unsigned char *out, ++ size_t length, const aes_context *key, ++ unsigned char *ivec, const int enc); ++ ++#define OPENSSL_AES_SET_ENCRYPT_KEY(k,b,c) aesni_set_encrypt_key(k,b,c) ++#define OPENSSL_AES_SET_DECRYPT_KEY(k,b,c) aesni_set_decrypt_key(k,b,c) ++#define OPENSSL_AES_ECB_ENCRYPT(i,o,k) aesni_ecb_encrypt(i,o,16,k,AES_ENCRYPT) ++#define OPENSSL_AES_ECB_DECRYPT(i,o,k) aesni_ecb_encrypt(i,o,16,k,AES_DECRYPT) ++#define OPENSSL_AES_CBC_ENCRYPT(i,o,l,k,iv,e) aesni_cbc_encrypt(i,o,l,k,iv,e) ++ ++#else ++ ++int AES_set_encrypt_key(const unsigned char *userKey, const int bits, ++ aes_context *key); ++int AES_set_decrypt_key(const unsigned char *userKey, const int bits, ++ aes_context *key); ++ ++void AES_encrypt(const unsigned char *in, unsigned char *out, const aes_context *key); ++void AES_decrypt(const unsigned char *in, unsigned char *out, const aes_context *key); ++ ++ ++#define OPENSSL_AES_SET_ENCRYPT_KEY(k,b,c) AES_set_encrypt_key(k,b,c) ++#define OPENSSL_AES_SET_DECRYPT_KEY(k,b,c) AES_set_decrypt_key(k,b,c) ++#define OPENSSL_AES_ECB_ENCRYPT(i,o,k) AES_encrypt(i,o,k) ++#define OPENSSL_AES_ECB_DECRYPT(i,o,k) AES_decrypt(i,o,k) ++ ++#endif ++ ++/** ++ * \brief AES key schedule (encryption) ++ * ++ * \param ctx AES context to be initialized ++ * \param key encryption key ++ * \param keysize must be 128, 192 or 256 ++ * ++ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH ++ */ ++static inline int aes_setkey_enc( aes_context *ctx, const unsigned char *key, const unsigned int keysize ) ++{ ++ const int status = OPENSSL_AES_SET_ENCRYPT_KEY(key, keysize, ctx); ++ return status ? POLARSSL_ERR_AES_INVALID_KEY_LENGTH : 0; ++} ++ ++/** ++ * \brief AES key schedule (decryption) ++ * ++ * \param ctx AES context to be initialized ++ * \param key decryption key ++ * \param keysize must be 128, 192 or 256 ++ * ++ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH ++ */ ++static inline int aes_setkey_dec( aes_context *ctx, const unsigned char *key, const unsigned int keysize ) ++{ ++ const int status = OPENSSL_AES_SET_DECRYPT_KEY(key, keysize, ctx); ++ return status ? POLARSSL_ERR_AES_INVALID_KEY_LENGTH : 0; ++} ++ ++/** ++ * \brief AES-ECB block encryption/decryption ++ * ++ * \param ctx AES context ++ * \param mode AES_ENCRYPT or AES_DECRYPT ++ * \param input 16-byte input block ++ * \param output 16-byte output block ++ * ++ * \return 0 if successful ++ */ ++static inline int aes_crypt_ecb( aes_context *ctx, ++ const int mode, ++ const unsigned char input[16], ++ unsigned char output[16] ) ++{ ++ if (mode == AES_DECRYPT) ++ OPENSSL_AES_ECB_DECRYPT(input, output, ctx); ++ else ++ OPENSSL_AES_ECB_ENCRYPT(input, output, ctx); ++ return 0; ++} ++ ++/** ++ * \brief AES-CBC buffer encryption/decryption ++ * Length should be a multiple of the block ++ * size (16 bytes) ++ * ++ * \param ctx AES context ++ * \param mode AES_ENCRYPT or AES_DECRYPT ++ * \param length length of the input data ++ * \param iv initialization vector (updated after use) ++ * \param input buffer holding the input data ++ * \param output buffer holding the output data ++ * ++ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ++ */ ++static inline int aes_crypt_cbc( aes_context *ctx, ++ const int mode, ++ size_t length, ++ unsigned char iv[16], ++ const unsigned char *input, ++ unsigned char *output ) ++{ ++#ifdef OPENSSL_AES_CBC_ENCRYPT ++ if (length & (OPENSSL_AES_BLOCK_SIZE-1)) ++ return POLARSSL_ERR_AES_INVALID_INPUT_LENGTH; ++ OPENSSL_AES_CBC_ENCRYPT(input, output, length, ctx, iv, mode); ++ return 0; ++#else ++ int i; ++ unsigned char temp[16]; ++ if (length & (OPENSSL_AES_BLOCK_SIZE-1)) ++ return POLARSSL_ERR_AES_INVALID_INPUT_LENGTH; ++ if( mode == AES_DECRYPT ) ++ { ++ while( length > 0 ) ++ { ++ memcpy( temp, input, 16 ); ++ OPENSSL_AES_ECB_DECRYPT(input, output, ctx); ++ for( i = 0; i < 16; i++ ) ++ output[i] = (unsigned char)( output[i] ^ iv[i] ); ++ memcpy( iv, temp, 16 ); ++ input += 16; ++ output += 16; ++ length -= 16; ++ } ++ } ++ else ++ { ++ while( length > 0 ) ++ { ++ for( i = 0; i < 16; i++ ) ++ output[i] = (unsigned char)( input[i] ^ iv[i] ); ++ OPENSSL_AES_ECB_ENCRYPT(output, output, ctx); ++ memcpy( iv, output, 16 ); ++ input += 16; ++ output += 16; ++ length -= 16; ++ } ++ } ++ return( 0 ); ++#endif ++} ++ ++#ifdef __cplusplus ++} ++#endif +diff -uNr polarssl-1.2.7/include/polarssl/sha1.h polarssl.new/include/polarssl/sha1.h +--- polarssl-1.2.7/include/polarssl/sha1.h 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/include/polarssl/sha1.h 2013-06-07 17:43:56.000000000 -0600 +@@ -29,6 +29,8 @@ + + #include + ++#include "config.h" ++ + #ifdef _MSC_VER + #include + typedef UINT32 uint32_t; +@@ -38,6 +40,12 @@ + + #define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */ + ++#ifdef POLARSSL_SHA1_ALT ++ ++#include "polarssl/sha1_alt.h" ++ ++#else ++ + /** + * \brief SHA-1 context structure + */ +@@ -80,6 +88,19 @@ + */ + void sha1_finish( sha1_context *ctx, unsigned char output[20] ); + ++/* Internal use */ ++void sha1_process( sha1_context *ctx, const unsigned char data[64] ); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* POLARSSL_SHA1_ALT */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ + /** + * \brief Output = SHA-1( input buffer ) + * +@@ -152,9 +173,6 @@ + */ + int sha1_self_test( int verbose ); + +-/* Internal use */ +-void sha1_process( sha1_context *ctx, const unsigned char data[64] ); +- + #ifdef __cplusplus + } + #endif +diff -uNr polarssl-1.2.7/include/polarssl/sha1_alt.h polarssl.new/include/polarssl/sha1_alt.h +--- polarssl-1.2.7/include/polarssl/sha1_alt.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/sha1_alt.h 2013-06-07 17:43:56.000000000 -0600 +@@ -0,0 +1,56 @@ ++/* ++ * Use OpenSSL implementation of SHA1 methods to get asm and hardware acceleration. ++ * Don't include this file directly, it is included by sha1.h when ++ * POLARSSL_SHA1_ALT is defined. ++ */ ++ ++#include "polarssl/sha_openssl.h" ++ ++struct openssl_sha_context { ++ SHA_LONG h0,h1,h2,h3,h4; ++ SHA_LONG Nl,Nh; ++ SHA_LONG data[SHA_LBLOCK]; ++ unsigned int num; ++}; ++ ++typedef struct ++{ ++ struct openssl_sha_context octx; ++ ++ unsigned char ipad[64]; /*!< HMAC: inner padding */ ++ unsigned char opad[64]; /*!< HMAC: outer padding */ ++} ++sha1_context; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int SHA1_Init(struct openssl_sha_context *c); ++int SHA1_Update(struct openssl_sha_context *c, const void *data, size_t len); ++int SHA1_Final(unsigned char *md, struct openssl_sha_context *c); ++void sha1_block_data_order(struct openssl_sha_context *c, const void *p, size_t num); ++ ++static inline void sha1_starts( sha1_context *ctx ) ++{ ++ SHA1_Init(&ctx->octx); ++} ++ ++static inline void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) ++{ ++ SHA1_Update(&ctx->octx, input, ilen); ++} ++ ++static inline void sha1_finish( sha1_context *ctx, unsigned char output[20] ) ++{ ++ SHA1_Final(output, &ctx->octx); ++} ++ ++static inline void sha1_process( sha1_context *ctx, const unsigned char data[64] ) ++{ ++ sha1_block_data_order(&ctx->octx, data, 1); ++} ++ ++#ifdef __cplusplus ++} ++#endif +diff -uNr polarssl-1.2.7/include/polarssl/sha2.h polarssl.new/include/polarssl/sha2.h +--- polarssl-1.2.7/include/polarssl/sha2.h 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/include/polarssl/sha2.h 2013-06-07 17:43:56.000000000 -0600 +@@ -29,6 +29,8 @@ + + #include + ++#include "config.h" ++ + #ifdef _MSC_VER + #include + typedef UINT32 uint32_t; +@@ -38,6 +40,12 @@ + + #define POLARSSL_ERR_SHA2_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */ + ++#ifdef POLARSSL_SHA2_ALT ++ ++#include "polarssl/sha2_alt.h" ++ ++#else ++ + /** + * \brief SHA-256 context structure + */ +@@ -82,6 +90,19 @@ + */ + void sha2_finish( sha2_context *ctx, unsigned char output[32] ); + ++/* Internal use */ ++void sha2_process( sha2_context *ctx, const unsigned char data[64] ); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* POLARSSL_SHA2_ALT */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ + /** + * \brief Output = SHA-256( input buffer ) + * +@@ -160,9 +181,6 @@ + */ + int sha2_self_test( int verbose ); + +-/* Internal use */ +-void sha2_process( sha2_context *ctx, const unsigned char data[64] ); +- + #ifdef __cplusplus + } + #endif +diff -uNr polarssl-1.2.7/include/polarssl/sha2_alt.h polarssl.new/include/polarssl/sha2_alt.h +--- polarssl-1.2.7/include/polarssl/sha2_alt.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/sha2_alt.h 2013-06-07 17:43:56.000000000 -0600 +@@ -0,0 +1,71 @@ ++/* ++ * Use OpenSSL implementation of SHA2 methods to get asm and hardware acceleration. ++ * Don't include this file directly, it is included by sha2.h when ++ * POLARSSL_SHA2_ALT is defined. ++ */ ++ ++#include "polarssl/sha_openssl.h" ++ ++struct openssl_sha2_context { ++ SHA_LONG h[8]; ++ SHA_LONG Nl,Nh; ++ SHA_LONG data[SHA_LBLOCK]; ++ unsigned int num,md_len; ++}; ++ ++typedef struct ++{ ++ struct openssl_sha2_context octx; ++ ++ unsigned char ipad[64]; /*!< HMAC: inner padding */ ++ unsigned char opad[64]; /*!< HMAC: outer padding */ ++ int is224; /*!< 0 => SHA-256, else SHA-224 */ ++} ++sha2_context; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int SHA224_Init(struct openssl_sha2_context *c); ++int SHA224_Update(struct openssl_sha2_context *c, const void *data, size_t len); ++int SHA224_Final(unsigned char *md, struct openssl_sha2_context *c); ++ ++int SHA256_Init(struct openssl_sha2_context *c); ++int SHA256_Update(struct openssl_sha2_context *c, const void *data, size_t len); ++int SHA256_Final(unsigned char *md, struct openssl_sha2_context *c); ++ ++void sha256_block_data_order(struct openssl_sha2_context *c, const void *p, size_t num); ++ ++static inline void sha2_starts( sha2_context *ctx, int is224 ) ++{ ++ if ((ctx->is224 = is224)) ++ SHA224_Init(&ctx->octx); ++ else ++ SHA256_Init(&ctx->octx); ++} ++ ++static inline void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) ++{ ++ if (ctx->is224) ++ SHA224_Update(&ctx->octx, input, ilen); ++ else ++ SHA256_Update(&ctx->octx, input, ilen); ++} ++ ++static inline void sha2_finish( sha2_context *ctx, unsigned char output[32] ) ++{ ++ if (ctx->is224) ++ SHA224_Final(output, &ctx->octx); ++ else ++ SHA256_Final(output, &ctx->octx); ++} ++ ++static inline void sha2_process( sha2_context *ctx, const unsigned char data[64] ) ++{ ++ sha256_block_data_order(&ctx->octx, data, 1); ++} ++ ++#ifdef __cplusplus ++} ++#endif +diff -uNr polarssl-1.2.7/include/polarssl/sha4.h polarssl.new/include/polarssl/sha4.h +--- polarssl-1.2.7/include/polarssl/sha4.h 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/include/polarssl/sha4.h 2013-06-07 17:43:56.000000000 -0600 +@@ -29,6 +29,8 @@ + + #include + ++#include "config.h" ++ + #if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 + typedef unsigned __int64 uint64_t; +@@ -39,6 +41,12 @@ + + #define POLARSSL_ERR_SHA4_FILE_IO_ERROR -0x007A /**< Read/write error in file. */ + ++#ifdef POLARSSL_SHA4_ALT ++ ++#include "polarssl/sha4_alt.h" ++ ++#else ++ + /** + * \brief SHA-512 context structure + */ +@@ -83,6 +91,16 @@ + */ + void sha4_finish( sha4_context *ctx, unsigned char output[64] ); + ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* POLARSSL_SHA4_ALT */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ + /** + * \brief Output = SHA-512( input buffer ) + * +diff -uNr polarssl-1.2.7/include/polarssl/sha4_alt.h polarssl.new/include/polarssl/sha4_alt.h +--- polarssl-1.2.7/include/polarssl/sha4_alt.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/sha4_alt.h 2013-06-07 17:43:56.000000000 -0600 +@@ -0,0 +1,67 @@ ++/* ++ * Use OpenSSL implementation of SHA4 methods to get asm and hardware acceleration. ++ * Don't include this file directly, it is included by sha4.h when ++ * POLARSSL_SHA4_ALT is defined. ++ */ ++ ++#include "polarssl/sha_openssl.h" ++ ++struct openssl_sha4_context { ++ SHA_LONG64 h[8]; ++ SHA_LONG64 Nl,Nh; ++ union { ++ SHA_LONG64 d[SHA_LBLOCK]; ++ unsigned char p[SHA512_CBLOCK]; ++ } u; ++ unsigned int num,md_len; ++}; ++ ++typedef struct ++{ ++ struct openssl_sha4_context octx; ++ ++ unsigned char ipad[128]; /*!< HMAC: inner padding */ ++ unsigned char opad[128]; /*!< HMAC: outer padding */ ++ int is384; /*!< 0 => SHA-512, else SHA-384 */ ++} ++sha4_context; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int SHA384_Init(struct openssl_sha4_context *c); ++int SHA384_Update(struct openssl_sha4_context *c, const void *data, size_t len); ++int SHA384_Final(unsigned char *md, struct openssl_sha4_context *c); ++ ++int SHA512_Init(struct openssl_sha4_context *c); ++int SHA512_Update(struct openssl_sha4_context *c, const void *data, size_t len); ++int SHA512_Final(unsigned char *md, struct openssl_sha4_context *c); ++ ++static inline void sha4_starts( sha4_context *ctx, int is384 ) ++{ ++ if ((ctx->is384 = is384)) ++ SHA384_Init(&ctx->octx); ++ else ++ SHA512_Init(&ctx->octx); ++} ++ ++static inline void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen ) ++{ ++ if (ctx->is384) ++ SHA384_Update(&ctx->octx, input, ilen); ++ else ++ SHA512_Update(&ctx->octx, input, ilen); ++} ++ ++static inline void sha4_finish( sha4_context *ctx, unsigned char output[64] ) ++{ ++ if (ctx->is384) ++ SHA384_Final(output, &ctx->octx); ++ else ++ SHA512_Final(output, &ctx->octx); ++} ++ ++#ifdef __cplusplus ++} ++#endif +diff -uNr polarssl-1.2.7/include/polarssl/sha_openssl.h polarssl.new/include/polarssl/sha_openssl.h +--- polarssl-1.2.7/include/polarssl/sha_openssl.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/sha_openssl.h 2013-06-07 17:43:56.000000000 -0600 +@@ -0,0 +1,42 @@ ++/* ++ * Common header file for all OpenSSL-imported SHA methods ++ */ ++ ++#ifndef POLARSSL_SHA_OPENSSL_H ++#define POLARSSL_SHA_OPENSSL_H ++ ++/* ++ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ++ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! ++ * ! SHA_LONG_LOG2 has to be defined along. ! ++ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ++ */ ++ ++#if defined(__LP32__) ++#define SHA_LONG unsigned long ++#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) ++#define SHA_LONG unsigned long ++#define SHA_LONG_LOG2 3 ++#else ++#define SHA_LONG unsigned int ++#endif ++ ++#define SHA_LBLOCK 16 ++ ++/* ++ * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 ++ * being exactly 64-bit wide. See Implementation Notes in sha512.c ++ * for further details. ++ */ ++#define SHA512_CBLOCK (SHA_LBLOCK*8) /* SHA-512 treats input data as a ++ * contiguous array of 64 bit ++ * wide big-endian values. */ ++#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) ++#define SHA_LONG64 unsigned __int64 ++#elif defined(__arch64__) ++#define SHA_LONG64 unsigned long ++#else ++#define SHA_LONG64 unsigned long long ++#endif ++ ++#endif +diff -uNr polarssl-1.2.7/library/aes.c polarssl.new/library/aes.c +--- polarssl-1.2.7/library/aes.c 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/library/aes.c 2013-06-07 17:43:56.000000000 -0600 +@@ -38,6 +38,8 @@ + #include "polarssl/padlock.h" + #endif + ++#ifndef POLARSSL_AES_ALT ++ + /* + * 32-bit integer manipulation macros (little endian) + */ +@@ -914,6 +916,7 @@ + return( 0 ); + } + #endif /* POLARSSL_CIPHER_MODE_CTR */ ++#endif /* !POLARSSL_AES_ALT */ + + #if defined(POLARSSL_SELF_TEST) + +diff -uNr polarssl-1.2.7/library/sha1.c polarssl.new/library/sha1.c +--- polarssl-1.2.7/library/sha1.c 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/library/sha1.c 2013-06-07 17:43:56.000000000 -0600 +@@ -38,6 +38,8 @@ + #include + #endif + ++#ifndef POLARSSL_SHA1_ALT ++ + /* + * 32-bit integer manipulation macros (big endian) + */ +@@ -313,6 +315,8 @@ + PUT_UINT32_BE( ctx->state[4], output, 16 ); + } + ++#endif /* !POLARSSL_SHA1_ALT */ ++ + /* + * output = SHA-1( input buffer ) + */ +diff -uNr polarssl-1.2.7/library/sha2.c polarssl.new/library/sha2.c +--- polarssl-1.2.7/library/sha2.c 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/library/sha2.c 2013-06-07 17:43:56.000000000 -0600 +@@ -38,6 +38,8 @@ + #include + #endif + ++#ifndef POLARSSL_SHA2_ALT ++ + /* + * 32-bit integer manipulation macros (big endian) + */ +@@ -314,6 +316,8 @@ + PUT_UINT32_BE( ctx->state[7], output, 28 ); + } + ++#endif /* !POLARSSL_SHA2_ALT */ ++ + /* + * output = SHA-256( input buffer ) + */ +diff -uNr polarssl-1.2.7/library/sha4.c polarssl.new/library/sha4.c +--- polarssl-1.2.7/library/sha4.c 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/library/sha4.c 2013-06-07 17:43:56.000000000 -0600 +@@ -38,6 +38,8 @@ + #include + #endif + ++#ifndef POLARSSL_SHA4_ALT ++ + /* + * 64-bit integer manipulation macros (big endian) + */ +@@ -312,6 +314,8 @@ + } + } + ++#endif /* !POLARSSL_SHA4_ALT */ ++ + /* + * output = SHA-512( input buffer ) + */ +diff -uNr polarssl-1.2.7/library/ssl_tls.c polarssl.new/library/ssl_tls.c +--- polarssl-1.2.7/library/ssl_tls.c 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/library/ssl_tls.c 2013-06-07 17:43:56.000000000 -0600 +@@ -2550,8 +2550,10 @@ + SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); + ++#ifndef POLARSSL_SHA1_ALT + SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); ++#endif + + sender = ( from == SSL_IS_CLIENT ) ? (char *) "CLNT" + : (char *) "SRVR"; +@@ -2621,8 +2623,10 @@ + SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); + ++#ifndef POLARSSL_SHA1_ALT + SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); ++#endif + + sender = ( from == SSL_IS_CLIENT ) + ? (char *) "client finished" +@@ -2666,8 +2670,10 @@ + * Hash( handshake ) )[0.11] + */ + ++#ifndef POLARSSL_SHA2_ALT + SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha2.state, sizeof( sha2.state ) ); ++#endif + + sender = ( from == SSL_IS_CLIENT ) + ? (char *) "client finished" +@@ -2710,8 +2716,10 @@ + * Hash( handshake ) )[0.11] + */ + ++#ifndef POLARSSL_SHA4_ALT + SSL_DEBUG_BUF( 4, "finished sha4 state", (unsigned char *) + sha4.state, sizeof( sha4.state ) ); ++#endif + + sender = ( from == SSL_IS_CLIENT ) + ? (char *) "client finished" +diff -uNr polarssl-1.2.7/tests/suites/test_suite_aes.function polarssl.new/tests/suites/test_suite_aes.function +--- polarssl-1.2.7/tests/suites/test_suite_aes.function 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/tests/suites/test_suite_aes.function 2013-06-07 17:43:56.000000000 -0600 +@@ -1,4 +1,5 @@ + BEGIN_HEADER ++#include + #include + END_HEADER + +diff -uNr polarssl-1.2.7/tests/suites/test_suite_ctr_drbg.function polarssl.new/tests/suites/test_suite_ctr_drbg.function +--- polarssl-1.2.7/tests/suites/test_suite_ctr_drbg.function 2013-04-13 03:56:17.000000000 -0600 ++++ polarssl.new/tests/suites/test_suite_ctr_drbg.function 2013-06-07 17:43:56.000000000 -0600 +@@ -1,4 +1,5 @@ + BEGIN_HEADER ++#include + #include + + int test_offset; diff --git a/deps/polarssl/polarssl-minicrypto.patch b/deps/polarssl/polarssl-minicrypto.patch new file mode 100644 index 0000000..0331ae1 --- /dev/null +++ b/deps/polarssl/polarssl-minicrypto.patch @@ -0,0 +1,446 @@ +diff -uNr polarssl-1.2.7/include/polarssl/aes_alt.h polarssl.new/include/polarssl/aes_alt.h +--- polarssl-1.2.7/include/polarssl/aes_alt.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/aes_alt.h 2013-06-07 18:18:37.000000000 -0600 +@@ -0,0 +1,183 @@ ++/* ++ * Use OpenSSL implementation of AES methods to get asm and hardware acceleration. ++ * Don't include this file directly, it is included by aes.h when ++ * POLARSSL_AES_ALT is defined. ++ */ ++ ++#ifdef _MSC_VER ++#include ++typedef UINT32 uint32_t; ++#else ++#include ++#endif ++ ++#define OPENSSL_AES_BLOCK_SIZE 16 ++#define OPENSSL_AES_MAXNR 14 ++ ++/** ++ * \brief AES context structure ++ */ ++typedef struct ++{ ++ uint32_t rd_key[4 * (OPENSSL_AES_MAXNR + 1)]; ++ int rounds; ++} ++aes_context; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#if defined(POLARSSL_USE_OPENSSL_AES_NI) ++ ++int aesni_set_encrypt_key(const unsigned char *userKey, const int bits, ++ aes_context *key); ++int aesni_set_decrypt_key(const unsigned char *userKey, const int bits, ++ aes_context *key); ++void aesni_ecb_encrypt(const unsigned char *in, unsigned char *out, ++ size_t length, const aes_context *key, const int enc); ++void aesni_cbc_encrypt(const unsigned char *in, unsigned char *out, ++ size_t length, const aes_context *key, ++ unsigned char *ivec, const int enc); ++ ++#define OPENSSL_AES_SET_ENCRYPT_KEY(k,b,c) aesni_set_encrypt_key(k,b,c) ++#define OPENSSL_AES_SET_DECRYPT_KEY(k,b,c) aesni_set_decrypt_key(k,b,c) ++#define OPENSSL_AES_ECB_ENCRYPT(i,o,k) aesni_ecb_encrypt(i,o,16,k,AES_ENCRYPT) ++#define OPENSSL_AES_ECB_DECRYPT(i,o,k) aesni_ecb_encrypt(i,o,16,k,AES_DECRYPT) ++#define OPENSSL_AES_CBC_ENCRYPT(i,o,l,k,iv,e) aesni_cbc_encrypt(i,o,l,k,iv,e) ++ ++#else ++ ++int AES_set_encrypt_key(const unsigned char *userKey, const int bits, ++ aes_context *key); ++int AES_set_decrypt_key(const unsigned char *userKey, const int bits, ++ aes_context *key); ++ ++void AES_encrypt(const unsigned char *in, unsigned char *out, const aes_context *key); ++void AES_decrypt(const unsigned char *in, unsigned char *out, const aes_context *key); ++ ++ ++#define OPENSSL_AES_SET_ENCRYPT_KEY(k,b,c) AES_set_encrypt_key(k,b,c) ++#define OPENSSL_AES_SET_DECRYPT_KEY(k,b,c) AES_set_decrypt_key(k,b,c) ++#define OPENSSL_AES_ECB_ENCRYPT(i,o,k) AES_encrypt(i,o,k) ++#define OPENSSL_AES_ECB_DECRYPT(i,o,k) AES_decrypt(i,o,k) ++ ++#endif ++ ++/** ++ * \brief AES key schedule (encryption) ++ * ++ * \param ctx AES context to be initialized ++ * \param key encryption key ++ * \param keysize must be 128, 192 or 256 ++ * ++ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH ++ */ ++static inline int aes_setkey_enc( aes_context *ctx, const unsigned char *key, const unsigned int keysize ) ++{ ++ const int status = OPENSSL_AES_SET_ENCRYPT_KEY(key, keysize, ctx); ++ return status ? POLARSSL_ERR_AES_INVALID_KEY_LENGTH : 0; ++} ++ ++/** ++ * \brief AES key schedule (decryption) ++ * ++ * \param ctx AES context to be initialized ++ * \param key decryption key ++ * \param keysize must be 128, 192 or 256 ++ * ++ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH ++ */ ++static inline int aes_setkey_dec( aes_context *ctx, const unsigned char *key, const unsigned int keysize ) ++{ ++ const int status = OPENSSL_AES_SET_DECRYPT_KEY(key, keysize, ctx); ++ return status ? POLARSSL_ERR_AES_INVALID_KEY_LENGTH : 0; ++} ++ ++/** ++ * \brief AES-ECB block encryption/decryption ++ * ++ * \param ctx AES context ++ * \param mode AES_ENCRYPT or AES_DECRYPT ++ * \param input 16-byte input block ++ * \param output 16-byte output block ++ * ++ * \return 0 if successful ++ */ ++static inline int aes_crypt_ecb( aes_context *ctx, ++ const int mode, ++ const unsigned char input[16], ++ unsigned char output[16] ) ++{ ++ if (mode == AES_DECRYPT) ++ OPENSSL_AES_ECB_DECRYPT(input, output, ctx); ++ else ++ OPENSSL_AES_ECB_ENCRYPT(input, output, ctx); ++ return 0; ++} ++ ++/** ++ * \brief AES-CBC buffer encryption/decryption ++ * Length should be a multiple of the block ++ * size (16 bytes) ++ * ++ * \param ctx AES context ++ * \param mode AES_ENCRYPT or AES_DECRYPT ++ * \param length length of the input data ++ * \param iv initialization vector (updated after use) ++ * \param input buffer holding the input data ++ * \param output buffer holding the output data ++ * ++ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ++ */ ++static inline int aes_crypt_cbc( aes_context *ctx, ++ const int mode, ++ size_t length, ++ unsigned char iv[16], ++ const unsigned char *input, ++ unsigned char *output ) ++{ ++#ifdef OPENSSL_AES_CBC_ENCRYPT ++ if (length & (OPENSSL_AES_BLOCK_SIZE-1)) ++ return POLARSSL_ERR_AES_INVALID_INPUT_LENGTH; ++ OPENSSL_AES_CBC_ENCRYPT(input, output, length, ctx, iv, mode); ++ return 0; ++#else ++ int i; ++ unsigned char temp[16]; ++ if (length & (OPENSSL_AES_BLOCK_SIZE-1)) ++ return POLARSSL_ERR_AES_INVALID_INPUT_LENGTH; ++ if( mode == AES_DECRYPT ) ++ { ++ while( length > 0 ) ++ { ++ memcpy( temp, input, 16 ); ++ OPENSSL_AES_ECB_DECRYPT(input, output, ctx); ++ for( i = 0; i < 16; i++ ) ++ output[i] = (unsigned char)( output[i] ^ iv[i] ); ++ memcpy( iv, temp, 16 ); ++ input += 16; ++ output += 16; ++ length -= 16; ++ } ++ } ++ else ++ { ++ while( length > 0 ) ++ { ++ for( i = 0; i < 16; i++ ) ++ output[i] = (unsigned char)( input[i] ^ iv[i] ); ++ OPENSSL_AES_ECB_ENCRYPT(output, output, ctx); ++ memcpy( iv, output, 16 ); ++ input += 16; ++ output += 16; ++ length -= 16; ++ } ++ } ++ return( 0 ); ++#endif ++} ++ ++#ifdef __cplusplus ++} ++#endif +diff -uNr polarssl-1.2.7/include/polarssl/sha1_alt.h polarssl.new/include/polarssl/sha1_alt.h +--- polarssl-1.2.7/include/polarssl/sha1_alt.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/sha1_alt.h 2013-06-07 17:43:56.000000000 -0600 +@@ -0,0 +1,56 @@ ++/* ++ * Use OpenSSL implementation of SHA1 methods to get asm and hardware acceleration. ++ * Don't include this file directly, it is included by sha1.h when ++ * POLARSSL_SHA1_ALT is defined. ++ */ ++ ++#include "polarssl/sha_openssl.h" ++ ++struct openssl_sha_context { ++ SHA_LONG h0,h1,h2,h3,h4; ++ SHA_LONG Nl,Nh; ++ SHA_LONG data[SHA_LBLOCK]; ++ unsigned int num; ++}; ++ ++typedef struct ++{ ++ struct openssl_sha_context octx; ++ ++ unsigned char ipad[64]; /*!< HMAC: inner padding */ ++ unsigned char opad[64]; /*!< HMAC: outer padding */ ++} ++sha1_context; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int SHA1_Init(struct openssl_sha_context *c); ++int SHA1_Update(struct openssl_sha_context *c, const void *data, size_t len); ++int SHA1_Final(unsigned char *md, struct openssl_sha_context *c); ++void sha1_block_data_order(struct openssl_sha_context *c, const void *p, size_t num); ++ ++static inline void sha1_starts( sha1_context *ctx ) ++{ ++ SHA1_Init(&ctx->octx); ++} ++ ++static inline void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) ++{ ++ SHA1_Update(&ctx->octx, input, ilen); ++} ++ ++static inline void sha1_finish( sha1_context *ctx, unsigned char output[20] ) ++{ ++ SHA1_Final(output, &ctx->octx); ++} ++ ++static inline void sha1_process( sha1_context *ctx, const unsigned char data[64] ) ++{ ++ sha1_block_data_order(&ctx->octx, data, 1); ++} ++ ++#ifdef __cplusplus ++} ++#endif +diff -uNr polarssl-1.2.7/include/polarssl/sha256_alt.h polarssl.new/include/polarssl/sha256_alt.h +--- polarssl-1.2.7/include/polarssl/sha256_alt.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/sha256_alt.h 2013-06-07 17:43:56.000000000 -0600 +@@ -0,0 +1,71 @@ ++/* ++ * Use OpenSSL implementation of SHA256 methods to get asm and hardware acceleration. ++ * Don't include this file directly, it is included by sha256.h when ++ * POLARSSL_SHA256_ALT is defined. ++ */ ++ ++#include "polarssl/sha_openssl.h" ++ ++struct openssl_sha256_context { ++ SHA_LONG h[8]; ++ SHA_LONG Nl,Nh; ++ SHA_LONG data[SHA_LBLOCK]; ++ unsigned int num,md_len; ++}; ++ ++typedef struct ++{ ++ struct openssl_sha256_context octx; ++ ++ unsigned char ipad[64]; /*!< HMAC: inner padding */ ++ unsigned char opad[64]; /*!< HMAC: outer padding */ ++ int is224; /*!< 0 => SHA-256, else SHA-224 */ ++} ++sha256_context; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int SHA224_Init(struct openssl_sha256_context *c); ++int SHA224_Update(struct openssl_sha256_context *c, const void *data, size_t len); ++int SHA224_Final(unsigned char *md, struct openssl_sha256_context *c); ++ ++int SHA256_Init(struct openssl_sha256_context *c); ++int SHA256_Update(struct openssl_sha256_context *c, const void *data, size_t len); ++int SHA256_Final(unsigned char *md, struct openssl_sha256_context *c); ++ ++void sha256_block_data_order(struct openssl_sha256_context *c, const void *p, size_t num); ++ ++static inline void sha256_starts( sha256_context *ctx, int is224 ) ++{ ++ if ((ctx->is224 = is224)) ++ SHA224_Init(&ctx->octx); ++ else ++ SHA256_Init(&ctx->octx); ++} ++ ++static inline void sha256_update( sha256_context *ctx, const unsigned char *input, size_t ilen ) ++{ ++ if (ctx->is224) ++ SHA224_Update(&ctx->octx, input, ilen); ++ else ++ SHA256_Update(&ctx->octx, input, ilen); ++} ++ ++static inline void sha256_finish( sha256_context *ctx, unsigned char output[32] ) ++{ ++ if (ctx->is224) ++ SHA224_Final(output, &ctx->octx); ++ else ++ SHA256_Final(output, &ctx->octx); ++} ++ ++static inline void sha256_process( sha256_context *ctx, const unsigned char data[64] ) ++{ ++ sha256_block_data_order(&ctx->octx, data, 1); ++} ++ ++#ifdef __cplusplus ++} ++#endif +diff -uNr polarssl-1.2.7/include/polarssl/sha512_alt.h polarssl.new/include/polarssl/sha512_alt.h +--- polarssl-1.2.7/include/polarssl/sha512_alt.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/sha512_alt.h 2013-06-07 17:43:56.000000000 -0600 +@@ -0,0 +1,74 @@ ++/* ++ * Use OpenSSL implementation of SHA512 methods to get asm and hardware acceleration. ++ * Don't include this file directly, it is included by sha512.h when ++ * POLARSSL_SHA512_ALT is defined. ++ */ ++ ++#include "polarssl/sha_openssl.h" ++ ++struct openssl_sha512_context { ++ SHA_LONG64 h[8]; ++ SHA_LONG64 Nl,Nh; ++ union { ++ SHA_LONG64 d[SHA_LBLOCK]; ++ unsigned char p[SHA512_CBLOCK]; ++ } u; ++ unsigned int num,md_len; ++}; ++ ++typedef struct ++{ ++ struct openssl_sha512_context octx; ++ ++ unsigned char ipad[128]; /*!< HMAC: inner padding */ ++ unsigned char opad[128]; /*!< HMAC: outer padding */ ++ int is384; /*!< 0 => SHA-512, else SHA-384 */ ++} ++sha512_context; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int SHA384_Init(struct openssl_sha512_context *c); ++int SHA384_Update(struct openssl_sha512_context *c, const void *data, size_t len); ++int SHA384_Final(unsigned char *md, struct openssl_sha512_context *c); ++ ++int SHA512_Init(struct openssl_sha512_context *c); ++int SHA512_Update(struct openssl_sha512_context *c, const void *data, size_t len); ++int SHA512_Final(unsigned char *md, struct openssl_sha512_context *c); ++ ++void sha512_block_data_order(struct openssl_sha512_context *c, const void *p, size_t num); ++ ++static inline void sha512_starts( sha512_context *ctx, int is384 ) ++{ ++ if ((ctx->is384 = is384)) ++ SHA384_Init(&ctx->octx); ++ else ++ SHA512_Init(&ctx->octx); ++} ++ ++static inline void sha512_update( sha512_context *ctx, const unsigned char *input, size_t ilen ) ++{ ++ if (ctx->is384) ++ SHA384_Update(&ctx->octx, input, ilen); ++ else ++ SHA512_Update(&ctx->octx, input, ilen); ++} ++ ++static inline void sha512_finish( sha512_context *ctx, unsigned char output[64] ) ++{ ++ if (ctx->is384) ++ SHA384_Final(output, &ctx->octx); ++ else ++ SHA512_Final(output, &ctx->octx); ++} ++ ++static inline void sha512_process( sha512_context *ctx, const unsigned char data[128] ) ++{ ++ sha512_block_data_order(&ctx->octx, data, 1); ++} ++ ++#ifdef __cplusplus ++} ++#endif +diff -uNr polarssl-1.2.7/include/polarssl/sha_openssl.h polarssl.new/include/polarssl/sha_openssl.h +--- polarssl-1.2.7/include/polarssl/sha_openssl.h 1969-12-31 17:00:00.000000000 -0700 ++++ polarssl.new/include/polarssl/sha_openssl.h 2013-06-07 17:43:56.000000000 -0600 +@@ -0,0 +1,42 @@ ++/* ++ * Common header file for all OpenSSL-imported SHA methods ++ */ ++ ++#ifndef POLARSSL_SHA_OPENSSL_H ++#define POLARSSL_SHA_OPENSSL_H ++ ++/* ++ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ++ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! ++ * ! SHA_LONG_LOG2 has to be defined along. ! ++ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ++ */ ++ ++#if defined(__LP32__) ++#define SHA_LONG unsigned long ++#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) ++#define SHA_LONG unsigned long ++#define SHA_LONG_LOG2 3 ++#else ++#define SHA_LONG unsigned int ++#endif ++ ++#define SHA_LBLOCK 16 ++ ++/* ++ * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 ++ * being exactly 64-bit wide. See Implementation Notes in sha512.c ++ * for further details. ++ */ ++#define SHA512_CBLOCK (SHA_LBLOCK*8) /* SHA-512 treats input data as a ++ * contiguous array of 64 bit ++ * wide big-endian values. */ ++#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) ++#define SHA_LONG64 unsigned __int64 ++#elif defined(__arch64__) ++#define SHA_LONG64 unsigned long ++#else ++#define SHA_LONG64 unsigned long long ++#endif ++ ++#endif diff --git a/deps/polarssl/ref b/deps/polarssl/ref new file mode 100644 index 0000000..6e16cdd --- /dev/null +++ b/deps/polarssl/ref @@ -0,0 +1,24 @@ +AES_set_encrypt_key +AES_set_decrypt_key +AES_ecb_encrypt +AES_cbc_encrypt +BF_set_key +BF_ecb_encrypt +BF_cbc_encrypt +SHA1_Init +SHA1_Update +SHA1_Final +SHA224_Init +SHA224_Update +SHA224_Final +SHA256_Init +SHA256_Update +SHA256_Final +SHA384_Init +SHA384_Update +SHA384_Final +SHA512_Init +SHA512_Update +SHA512_Final +OPENSSL_ia32_cpuid +-OPENSSL_cpuid_setup diff --git a/deps/polarssl/ref-aesni b/deps/polarssl/ref-aesni new file mode 100644 index 0000000..0574500 --- /dev/null +++ b/deps/polarssl/ref-aesni @@ -0,0 +1,24 @@ +aesni_set_encrypt_key +aesni_set_decrypt_key +aesni_ecb_encrypt +aesni_cbc_encrypt +BF_set_key +BF_ecb_encrypt +BF_cbc_encrypt +SHA1_Init +SHA1_Update +SHA1_Final +SHA224_Init +SHA224_Update +SHA224_Final +SHA256_Init +SHA256_Update +SHA256_Final +SHA384_Init +SHA384_Update +SHA384_Final +SHA512_Init +SHA512_Update +SHA512_Final +OPENSSL_ia32_cpuid +-OPENSSL_cpuid_setup diff --git a/deps/polarssl/relaxed-x509-date.patch b/deps/polarssl/relaxed-x509-date.patch new file mode 100644 index 0000000..eb021f2 --- /dev/null +++ b/deps/polarssl/relaxed-x509-date.patch @@ -0,0 +1,118 @@ +diff -ur mbedtls-1.3.17/library/x509.c polarssl.new/library/x509.c +--- mbedtls-1.3.17/library/x509.c 2016-06-27 13:00:26.000000000 -0600 ++++ polarssl.new/library/x509.c 2016-08-04 17:21:52.000000000 -0600 +@@ -490,6 +490,73 @@ + } + + /* ++ * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) field. ++ */ ++static int x509_parse_time(unsigned char **p, size_t len, unsigned int yearlen, x509_time *time) ++{ ++ int ret; ++ ++ /* minimum length is 10 or 12 depending on yearlen */ ++ if (len < yearlen + 8) ++ return POLARSSL_ERR_X509_INVALID_DATE; ++ len -= yearlen + 8; ++ ++ /* parse year, month, day, hour, minute */ ++ CHECK( x509_parse_int( p, yearlen, &time->year ) ); ++ if (yearlen == 2) ++ { ++ if (time->year < 50) ++ time->year += 100; ++ time->year += 1900; ++ } ++ CHECK( x509_parse_int( p, 2, &time->mon ) ); ++ CHECK( x509_parse_int( p, 2, &time->day ) ); ++ CHECK( x509_parse_int( p, 2, &time->hour ) ); ++ CHECK( x509_parse_int( p, 2, &time->min ) ); ++ ++ /* parse seconds if present */ ++ if (len >= 2 && **p >= '0' && **p <= '9') ++ { ++ CHECK( x509_parse_int( p, 2, &time->sec ) ); ++ len -= 2; ++ } ++ else ++ { ++#if defined(POLARSSL_RELAXED_X509_DATE) ++ /* if relaxed mode, allow seconds to be absent */ ++ time->sec = 0; ++#else ++ return POLARSSL_ERR_X509_INVALID_DATE; ++#endif ++ } ++ ++ /* parse trailing 'Z' if present */ ++ if (len == 1 && **p == 'Z') ++ { ++ (*p)++; ++ return 0; ++ } ++ ++#if defined(POLARSSL_RELAXED_X509_DATE) ++ /* if relaxed mode, allow timezone to be present */ ++ else if (len == 5 && **p == '+') ++ { ++ int tz; /* throwaway timezone */ ++ (*p)++; ++ CHECK( x509_parse_int( p, 4, &tz ) ); ++ return 0; ++ } ++#endif ++ ++ /* okay if no trailing 'Z' or timezone specified */ ++ else if (len == 0) ++ return 0; ++ ++ else ++ return POLARSSL_ERR_X509_INVALID_DATE; ++} ++ ++/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } +@@ -515,20 +582,7 @@ + if( ret != 0 ) + return( POLARSSL_ERR_X509_INVALID_DATE + ret ); + +- CHECK( x509_parse_int( p, 2, &time->year ) ); +- CHECK( x509_parse_int( p, 2, &time->mon ) ); +- CHECK( x509_parse_int( p, 2, &time->day ) ); +- CHECK( x509_parse_int( p, 2, &time->hour ) ); +- CHECK( x509_parse_int( p, 2, &time->min ) ); +- if( len > 10 ) +- CHECK( x509_parse_int( p, 2, &time->sec ) ); +- if( len > 12 && *(*p)++ != 'Z' ) +- return( POLARSSL_ERR_X509_INVALID_DATE ); +- +- time->year += 100 * ( time->year < 50 ); +- time->year += 1900; +- +- return( 0 ); ++ return x509_parse_time(p, len, 2, time); + } + else if( tag == ASN1_GENERALIZED_TIME ) + { +@@ -538,17 +592,7 @@ + if( ret != 0 ) + return( POLARSSL_ERR_X509_INVALID_DATE + ret ); + +- CHECK( x509_parse_int( p, 4, &time->year ) ); +- CHECK( x509_parse_int( p, 2, &time->mon ) ); +- CHECK( x509_parse_int( p, 2, &time->day ) ); +- CHECK( x509_parse_int( p, 2, &time->hour ) ); +- CHECK( x509_parse_int( p, 2, &time->min ) ); +- if( len > 12 ) +- CHECK( x509_parse_int( p, 2, &time->sec ) ); +- if( len > 14 && *(*p)++ != 'Z' ) +- return( POLARSSL_ERR_X509_INVALID_DATE ); +- +- return( 0 ); ++ return x509_parse_time(p, len, 4, time); + } + else + return( POLARSSL_ERR_X509_INVALID_DATE + diff --git a/deps/polarssl/testpatch b/deps/polarssl/testpatch new file mode 100755 index 0000000..0330a9e --- /dev/null +++ b/deps/polarssl/testpatch @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +ver=1.2.7 +src=~/src/mac/polarssl-$ver +rm -rf polarssl-$ver polarssl-$ver.new +tar xfz $DL/polarssl-$ver-gpl.tgz +cp -a polarssl-$ver polarssl-$ver.new +cd polarssl-$ver.new +cp $src/include/polarssl/bn_mul.h include/polarssl/ +cp $src/library/bignum.c library/ +#cp $src/library/mpi_mul_hlp.c library/ +#cp $src/library/CMakeLists.txt library/ +cd .. +diff -uNr polarssl-$ver polarssl-$ver.new diff --git a/deps/polarssl/unused/polarssl-const-ciphersuite.patch b/deps/polarssl/unused/polarssl-const-ciphersuite.patch new file mode 100644 index 0000000..62013cf --- /dev/null +++ b/deps/polarssl/unused/polarssl-const-ciphersuite.patch @@ -0,0 +1,37 @@ +Make the ciphersuites array argument to ssl_set_ciphersuites const. +This should be done to assure callers that PolarSSL doesn't intend +to modify this array (which it apparently doesn't). + +diff -ur polarssl-1.1.1/include/polarssl/ssl.h polarssl-1.1.1.new/include/polarssl/ssl.h +--- polarssl-1.1.1/include/polarssl/ssl.h 2012-01-23 02:57:38.000000000 -0700 ++++ polarssl-1.1.1.new/include/polarssl/ssl.h 2012-03-14 02:46:30.315215130 -0600 +@@ -306,7 +306,7 @@ + sha1_context fin_sha1; /*!< Finished SHA-1 checksum */ + + int do_crypt; /*!< en(de)cryption flag */ +- int *ciphersuites; /*!< allowed ciphersuites */ ++ const int *ciphersuites; /*!< allowed ciphersuites */ + size_t pmslen; /*!< premaster length */ + unsigned int keylen; /*!< symmetric key length */ + size_t minlen; /*!< min. ciphertext length */ +@@ -495,7 +495,7 @@ + * \param ssl SSL context + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +-void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites ); ++void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ); + + /** + * \brief Set the data required to verify peer certificate +diff -ur polarssl-1.1.1/library/ssl_tls.c polarssl-1.1.1.new/library/ssl_tls.c +--- polarssl-1.1.1/library/ssl_tls.c 2012-01-23 02:57:38.000000000 -0700 ++++ polarssl-1.1.1.new/library/ssl_tls.c 2012-03-14 02:47:10.830001668 -0600 +@@ -1838,7 +1838,7 @@ + ssl->session = session; + } + +-void ssl_set_ciphersuites( ssl_context *ssl, int *ciphersuites ) ++void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ) + { + ssl->ciphersuites = ciphersuites; + } diff --git a/deps/polarssl/unused/polarssl-enum.patch b/deps/polarssl/unused/polarssl-enum.patch new file mode 100644 index 0000000..9dee1a1 --- /dev/null +++ b/deps/polarssl/unused/polarssl-enum.patch @@ -0,0 +1,15 @@ +This fixes an issue where the cipher.h header doesn't compile when included +by C++ code, as C++ is more strict than C about implicit enum casts. + +diff -ur polarssl-1.1.1/include/polarssl/cipher.h /home/james/polarssl-1.1.1/include/polarssl/cipher.h +--- polarssl-1.1.1/include/polarssl/cipher.h 2011-11-15 08:38:45.000000000 -0700 ++++ /home/james/polarssl-1.1.1/include/polarssl/cipher.h 2012-03-12 17:31:12.279631469 -0600 +@@ -313,7 +313,7 @@ + static inline cipher_type_t cipher_get_type( const cipher_context_t *ctx ) + { + if( NULL == ctx || NULL == ctx->cipher_info ) +- return 0; ++ return POLARSSL_CIPHER_NONE; + + return ctx->cipher_info->type; + } diff --git a/deps/polarssl/unused/polarssl-epki.patch b/deps/polarssl/unused/polarssl-epki.patch new file mode 100644 index 0000000..49ce2e5 --- /dev/null +++ b/deps/polarssl/unused/polarssl-epki.patch @@ -0,0 +1,181 @@ +This patch allows the caller to create a proxy object that can be used +in place of a private key. The proxy object must define sign and +decrypt methods. This functionality is similar to that provided by +POLARSSL_PKCS11_C except that it can accomodate any arbitrary +implementation of external private keys, not only that provided by +the PKCS#11 helper library. + +This is necessary to allow PolarSSL to interact with certificate/key +stores on many different platforms that don't natively support +PKCS#11 such as Mac (uses Keychain API), Windows (uses CryptoAPI), +and Android (android.security.KeyChain). + +In the basic usage model, the library is built with POLARSSL_PKCS11_C +and POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY. Doing this causes the +pkcs11_context object to become an interface to any arbitrary +external private key implementation that defines sign and decrypt +methods. Note that in this configuration, the PKCS#11 helper library +(libpkcs11-helper) is not used. + +When POLARSSL_PKCS11_C is defined in the absence of +POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY, the pkcs11_context object +reverts to its previous implementation, where it becomes a +connector to a certificate/private-key context in the PKCS#11 helper +library. + +diff -ur polarssl-1.1.1.orig/include/polarssl/config.h polarssl-1.1.1/include/polarssl/config.h +--- polarssl-1.1.1.orig/include/polarssl/config.h 2011-12-22 03:06:27.000000000 -0700 ++++ polarssl-1.1.1/include/polarssl/config.h 2012-03-14 02:31:04.000000000 -0600 +@@ -531,10 +531,26 @@ + * + * This module is required for SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) ++ * unless POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY is also defined. ++ * + #define POLARSSL_PKCS11_C + */ + + /** ++ * \def POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY ++ * ++ * Enable support for generic external private key implementations. ++ * ++ * Module: library/ssl_srv.c ++ * Caller: library/ssl_cli.c ++ * library/ssl_srv.c ++ * ++ * Requires: POLARSSL_PKCS11_C ++ * ++#define POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY ++ */ ++ ++/** + * \def POLARSSL_RSA_C + * + * Enable the RSA public-key cryptosystem. +diff -ur polarssl-1.1.1.orig/include/polarssl/pkcs11.h polarssl-1.1.1/include/polarssl/pkcs11.h +--- polarssl-1.1.1.orig/include/polarssl/pkcs11.h 2011-11-18 07:26:47.000000000 -0700 ++++ polarssl-1.1.1/include/polarssl/pkcs11.h 2012-03-14 02:28:34.000000000 -0600 +@@ -35,6 +35,95 @@ + + #include "x509.h" + ++#if defined(POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY) ++ ++/* inline preamble */ ++#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 */ ++ ++/** ++ * This object is a reference to an external private key, ++ * and can be used in place of a concrete private key. ++ */ ++typedef struct _pkcs11_context { ++ void *parameter; /** user-defined parameter */ ++ int len; /** private key length in bytes */ ++ ++ /** user-defined decrypt method, see pkcs11_decrypt doc below */ ++ int (*f_decrypt)( struct _pkcs11_context *ctx, ++ int mode, size_t *olen, ++ const unsigned char *input, ++ unsigned char *output, ++ unsigned int output_max_len ); ++ ++ /** user-defined sign method, see pkcs11_sign doc below */ ++ int (*f_sign)( struct _pkcs11_context *ctx, ++ int mode, ++ int hash_id, ++ unsigned int hashlen, ++ const unsigned char *hash, ++ unsigned char *sig ); ++ ++} pkcs11_context; ++ ++/** ++ * \brief Do an RSA private key decrypt, then remove the message padding ++ * ++ * \param ctx PKCS #11 context ++ * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature ++ * \param input buffer holding the encrypted data ++ * \param output buffer that will hold the plaintext ++ * \param olen will contain the plaintext length ++ * \param output_max_len maximum length of the output buffer ++ * ++ * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code ++ * ++ * \note The output buffer must be as large as the size ++ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise ++ * an error is thrown. ++ */ ++static inline int pkcs11_decrypt( pkcs11_context *ctx, ++ int mode, size_t *olen, ++ const unsigned char *input, ++ unsigned char *output, ++ unsigned int output_max_len ) ++{ ++ return (*ctx->f_decrypt)(ctx, mode, olen, input, output, output_max_len); ++} ++ ++/** ++ * \brief Do a private RSA to sign a message digest ++ * ++ * \param ctx PKCS #11 context ++ * \param mode must be RSA_PRIVATE, for compatibility with rsa.c's signature ++ * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} ++ * \param hashlen message digest length (for SIG_RSA_RAW only) ++ * \param hash buffer holding the message digest ++ * \param sig buffer that will hold the ciphertext ++ * ++ * \return 0 if the signing operation was successful, ++ * or an POLARSSL_ERR_RSA_XXX error code ++ * ++ * \note The "sig" buffer must be as large as the size ++ * of ctx->N (eg. 128 bytes if RSA-1024 is used). ++ */ ++static inline int pkcs11_sign( pkcs11_context *ctx, ++ int mode, ++ int hash_id, ++ unsigned int hashlen, ++ const unsigned char *hash, ++ unsigned char *sig ) ++{ ++ return (*ctx->f_sign)(ctx, mode, hash_id, hashlen, hash, sig); ++} ++ ++#else ++ + #include + + /** +@@ -121,6 +210,8 @@ + const unsigned char *hash, + unsigned char *sig ); + ++#endif /* POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY */ ++ + #endif /* POLARSSL_PKCS11_C */ + + #endif /* POLARSSL_PKCS11_H */ +diff -ur polarssl-1.1.1.orig/library/pkcs11.c polarssl-1.1.1/library/pkcs11.c +--- polarssl-1.1.1.orig/library/pkcs11.c 2011-04-24 02:57:21.000000000 -0600 ++++ polarssl-1.1.1/library/pkcs11.c 2012-03-14 02:28:22.000000000 -0600 +@@ -29,7 +29,7 @@ + + #include "polarssl/pkcs11.h" + +-#if defined(POLARSSL_PKCS11_C) ++#if defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY) + + #include + +@@ -235,4 +235,4 @@ + return( 0 ); + } + +-#endif /* defined(POLARSSL_PKCS11_C) */ ++#endif /* defined(POLARSSL_PKCS11_C) && !defined(POLARSSL_GENERIC_EXTERNAL_PRIVATE_KEY) */ diff --git a/deps/polarssl/unused/polarssl-invalid-mac.patch b/deps/polarssl/unused/polarssl-invalid-mac.patch new file mode 100644 index 0000000..7cc3799 --- /dev/null +++ b/deps/polarssl/unused/polarssl-invalid-mac.patch @@ -0,0 +1,12 @@ +diff -ur polarssl-1.1.3/library/ssl_tls.c polarssl-1.1.3.jy/library/ssl_tls.c +--- polarssl-1.1.3/library/ssl_tls.c 2012-04-20 07:33:14.000000000 -0600 ++++ polarssl-1.1.3.jy/library/ssl_tls.c 2012-05-29 09:12:11.687371794 -0600 +@@ -785,7 +785,7 @@ + /* + * Always compute the MAC (RFC4346, CBCTIME). + */ +- if( ssl->in_msglen <= ssl->maclen + padlen ) ++ if( ssl->in_msglen < ssl->maclen + padlen ) + { + SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", + ssl->in_msglen, ssl->maclen, padlen ) ); diff --git a/deps/polarssl/unused/trustex.patch b/deps/polarssl/unused/trustex.patch new file mode 100644 index 0000000..8605d1b --- /dev/null +++ b/deps/polarssl/unused/trustex.patch @@ -0,0 +1,44 @@ +Patch to 1.1.4 to allow X509 v3 trust extensions. +-------------------------------------------------- +Index: x509parse.c +=================================================================== +--- x509parse.c (revision 1322) ++++ x509parse.c (working copy) +@@ -1134,7 +1134,7 @@ + { + int ret; + size_t len; +- unsigned char *p, *end; ++ unsigned char *p, *end, *crt_end; + + /* + * Check for valid input +@@ -1168,13 +1168,14 @@ + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT ); + } + +- if( len != (size_t) ( end - p ) ) ++ if( len > (size_t) ( end - p ) ) + { + x509_free( crt ); + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } +- ++ crt_end = p + len; ++ + /* + * TBSCertificate ::= SEQUENCE { + */ +@@ -1344,7 +1345,7 @@ + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + +- end = crt->raw.p + crt->raw.len; ++ end = crt_end; + + /* + * signatureAlgorithm AlgorithmIdentifier, + +---------------------------------------------------- +End of patch file diff --git a/deps/snappy/build-snappy b/deps/snappy/build-snappy new file mode 100755 index 0000000..e05ff5f --- /dev/null +++ b/deps/snappy/build-snappy @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi + +[ -z "$DL" ] && DL=~/Downloads + +# source vars +. $O3/core/vars/vars-${TARGET} +. $O3/core/deps/lib-versions + +[ "$GCC_CMD" ] && export CC=$GCC_CMD +[ "$GPP_CMD" ] && export CXX=$GPP_CMD +[ "$LD_CMD" ] && export LD=$LD_CMD +[ "$AR_CMD" ] && export AR=$AR_CMD +[ "$RANLIB_CMD" ] && export RANLIB=$RANLIB_CMD + +case $PLATFORM in +android*) + echo PLATFORM android + host=arm + target=arm + ;; +ios*) + echo PLATFORM ios + host="x86_64-apple-darwin" + target=arm + ;; +*) + host="" + target="" + ;; +esac + +if [ "$target" ]; then + targ_opt="--target=$target" +fi + +if [ "$host" ]; then + host_opt="--host=$host" +fi + +if [ "$NO_WIPE" != "1" ]; then + rm -rf $SNAPPY_VERSION + tar xfz $DL/$SNAPPY_VERSION.tar.gz +fi + +DIST=$(pwd)/snappy/snappy-$PLATFORM +rm -rf $DIST +mkdir -p $DIST +cd $SNAPPY_VERSION +echo 'OPTIONS' CC=$CC LD=$LD AR=$AR RANLIB=$RANLIB host_opt=$host_opt targ_opt=$targ_opt +export CFLAGS="$PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC" +echo 'CFLAGS' $CFLAGS +export CXXFLAGS="$CFLAGS $CXX_COMPILER_FLAGS" +./configure --prefix=$DIST $host_opt $targ_opt --enable-static --disable-shared +make +make install +exit 0 diff --git a/doc/openvpn-protocol-extensions.txt b/doc/openvpn-protocol-extensions.txt new file mode 100644 index 0000000..593fd04 --- /dev/null +++ b/doc/openvpn-protocol-extensions.txt @@ -0,0 +1,198 @@ +OpenVPN Protocol extensions +2015-01-06 + +1. DATA_V2 opcode with 24-bit peer ID + + * The DATA_V2 opcode is 9. + * The DATA_V2 opcode/key_id byte is followed by 3 additional + (network endian) bytes indicating the peer ID. + * If a 4-byte DATA_V2 header is passed through ntohl, + the resulting high 8 bits will be the DATA_V2 opcode/key_id, + and the lower 24 bits will be the peer ID. + * A disabled peer ID is denoted by 0xFFFFFF. + * Server tells the client to use DATA_V2/peer_id by pushing + the directive "peer-id ID" where ID is a decimal integer + in the range [-1, 16777215]. Setting the peer ID to -1 + transmits DATA_V2 packets with the peer ID field set to + 0xFFFFFF. Setting the peer_id to -1 is the same as + setting it to 16777215 (i.e. 0xFFFFFF). + * Client never transmits DATA_V2 packets unless the server + has pushed a "peer-id" directive. + * Server never pushes a "peer-id" directive unless the + client has indicated its support for DATA_V2 by + including "IV_PROTO=2" in the peer info data. + * When DATA_V2 is used for "float" functionality, the server + must perform the following checks before allowing + a client to float, i.e. to assume a new source address. + (a) verify integrity (HMAC or GCM auth tag, replay + protection, etc.) of the DATA_V2 packet, and + (b) ensure that the float doesn't clobber a pre-existing + client (i.e. if the address floated to is already + owned by another client) unless it can be verified + that the pre-existing client is a previous instance + of the floating client. + +2. AEAD mode + + To support AEAD crypto modes such as AES-GCM, some protocol + changes are in order. AES-GCM, for example, requires a 12 + byte unique nonce for every packet. I would propose that 4 + bytes be taken from the Packet ID which increments for every + packet and therefore provides uniqueness. The remaining 8 + bytes would be derived from the random key material that would + normally be used to key the HMAC key. This is possible since + AEAD modes use a combined key for encryption and integrity + checking, therefore the random key material for HMAC is + unused and can be repurposed as an AEAD nonce source. The 8 + byte nonce component derived from the HMAC keying material + would remain constant for a given Key State. Only the 4 byte + Packet ID would increment for each packet. Because AEAD + encryption can be compromised if the nonce ever repeats for + a given key, the implementation MUST disable encryption + for a key if the 32-bit packet ID wraps. In practical usage, + renegotiation usually preempts wrapping, so the + disable-encryption-on-wrap feature is a failsafe. + + AEAD Nonce: + + [ Packet ID ] [ HMAC keying material ] + [ 4 bytes ] [ 8 bytes ] + [ AEAD nonce total: 12 bytes ] + + TLS wire protocol: + + [ DATA_V2 opcode ] [ Packet ID ] [ AEAD Auth tag ] [ ciphertext ] + [ 4 bytes ] [ 4 bytes ] [ 16 bytes ] + [ AEAD additional data (AD) ] + + Static Key wire protocol: + + [ DATA_V2 opcode ] [ Packet ID ] [ Nonce tail (random) ] [ AEAD Auth tag ] [ ciphertext ] + [ AEAD nonce ] + [ 4 bytes ] [ 8 bytes ] [ 4 bytes ] [ 16 bytes ] + [ AEAD additional data (AD) ] + + Note that the AEAD additional data (AD) includes all data + preceding the AEAD Auth tag including the DATA_V2/peer_id + opcode and packet ID. + + Also, note that because the HMAC keying material used to derive + the last 8 bytes of the AEAD nonce is negotiated once per key + as part of the control channel handshake, we can omit it from the + data channel packets, thereby saving 8 bytes per packet. So + only the 4-byte Packet ID component of the nonce must be + transmitted with every packet. + + When negotiating AEAD mode, the client indicates its support + of AES-128-GCM, AES-192-GCM, and AES-192-GCM by including: + + IV_NCP=2 + + in the peer info string (NCP stands for Negotiable Crypto + Parameters). + + When the IV_NCP value is 2 or higher, it indicates that + the server may push an AEAD "cipher" directive, e.g.: + + push "cipher AES-128-GCM" + + In the future, the IV_NCP value (2 in the current + implementation) may be increased to indicate the + availability of additional negotiable ciphers. + +3. Compression V2 + + I have observed that compression in many cases, even when + enabled, often does not produce packet size reduction + because much of the packet data typically generated by web + sessions is already compressed. Further, the single byte that + precedes the packet and indicates whether or not compression + occurred has the unfortunate side effect of misaligning the IP + packet in cases where compression did not occur. To remedy this, + I propose a Compression V2 header that is optimized for the + case where compression does not occur. + + a. No compression occurred and first byte of IP/Ethernet packet + is NOT 0x50 (0 bytes of overhead and maintains alignment): + + [ uncompressed IP/Ethernet packet ] + + b. No compression occurred and first byte of IP/Ethernet packet + is 0x50 (2 bytes of overhead but unlikely since no known + IP packet can begin with 0x50): + + [ 0x50 ] [ 0x00 ] [ uncompressed IP/Ethernet packet ] + + c. Compression occurred (2 bytes of overhead): + + [ 0x50 ] [ compression Alg ID byte ] [ compressed IP/Ethernet packet ] + + Compression Alg ID is one-byte algorithm identifier + for LZ4 (0x1), LZO (0x2), or Snappy (0x3). + + This approach has several beneficial effects: + + 1. In the common case where compression does not occur, no + compression op is required, therefore there is zero overhead. + + 2. When compression does not occur, the IP/Ethernet packet + alignment is retained. + + 3. This technique does not require any byte swapping with + the tail of the packet which can potentially incur an + expensive cache miss. + + When negotiating Compression V2 mode, the client indicates its + support by including the following in the peer info string: + + IV_LZ4v2=1 -> LZ4 compression available in V2 format + IV_COMP_STUBv2=1 -> stub compression available in V2 format + (i.e. disable compression but still + retain compression framing) + + In response, the server can push to the client: + + push "compress lz4-v2" -> enable LZ4 compression in V2 format + + or + + push "compress stub-v2" -> disable compression but retain + compression framing in V2 format + +4. TCP nonlinear mode + + The OpenVPN 2.x packet ID and replay protection code, when running + in TCP mode, requires that the packet ID follows a linearly + incrementing sequence, i.e. 1, 2, 2, 3, ... This was a reasonable + requirement, since the reliable nature of TCP guaranteed that a + linear sequence of packet IDs transmitted by the sender would be + received in the same order by the receiver. + + However, recent work has shown that multithreaded OpenVPN servers + may not be able to guarantee TCP packet ID linearity (on the + transmit side) without incurring a performance penalty. This + is because the packet ID for transmitted packets must be allocated + before the packet is encrypted, while a multithreaded OpenVPN server + might be concurrently encrypting and transmitting multiple packets + using different threads, where the order that the threads complete + encryption and transmit the packet is non-deterministic. This + non-deterministic ordering of packets over the TCP session means + that the client might see out-of-order packets and a non-linear + packet ID progression, just as clients now see with UDP. + + My proposed solution to the issue is to relax the Packet ID + validation on the receiver side to allow non-linear packet ID + sequences, even in TCP mode. This essentially means that the + packet ID validation logic is now the same for both UDP and TCP. + + The client indicates its ability to process non-linear packet + ID sequences in TCP mode by including the following in the + peer info string: + + IV_TCPNL=1 -> TCP non-linear receiver supported + + When the server receives a IV_TCPNL setting of 1 from the + client, it may transmit out-of-order packets in TCP mode. + Otherwise, servers must use other means (such as using thread + synchronization primitives) to ensure strictly linear packet + ID ordering in TCP mode. diff --git a/docker-build.sh b/docker-build.sh new file mode 100755 index 0000000..97bbe21 --- /dev/null +++ b/docker-build.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# build ovpn3-core with system-provided mbedtls and lz4 on various linux distros + +docker build -f dockerfiles/Dockerfile.debian -t deb . +docker run -it deb + +docker build -f dockerfiles/Dockerfile.ubu -t ubu . +docker run -it ubu + +docker build -f dockerfiles/Dockerfile.centos -t cnt . +docker run -it cnt diff --git a/dockerfiles/Dockerfile.centos b/dockerfiles/Dockerfile.centos new file mode 100644 index 0000000..32d1088 --- /dev/null +++ b/dockerfiles/Dockerfile.centos @@ -0,0 +1,19 @@ +FROM centos/devtoolset-7-toolchain-centos7 + +USER 0 +RUN yum -y update && yum -y install epel-release && \ + yum -y install -y mbedtls-devel lz4-devel git wget perl-Digest-SHA make + +ADD . /ovpn3/core + +ENV O3 /ovpn3/ +ENV DEP_DIR /ovpn3/deps +ENV DL /ovpn3/dl + +CMD mkdir $DEP_DIR && mkdir $DL && \ + /ovpn3/core/scripts/linux/build-all && \ + cd $O3/core/test/ovpncli && \ + ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \ + cd $O3/core/test/ssl && \ + ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \ + ./proto diff --git a/dockerfiles/Dockerfile.debian b/dockerfiles/Dockerfile.debian new file mode 100644 index 0000000..3aaceaa --- /dev/null +++ b/dockerfiles/Dockerfile.debian @@ -0,0 +1,17 @@ +FROM debian:9 + +RUN apt-get update && apt-get install -y autoconf build-essential wget git liblz4-dev libmbedtls-dev + +ADD . /ovpn3/core + +ENV O3 /ovpn3/ +ENV DEP_DIR /ovpn3/deps +ENV DL /ovpn3/dl + +CMD mkdir $DEP_DIR && mkdir $DL && \ + /ovpn3/core/scripts/linux/build-all && \ + cd $O3/core/test/ovpncli && \ + ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \ + cd $O3/core/test/ssl && \ + ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \ + ./proto diff --git a/dockerfiles/Dockerfile.ubu b/dockerfiles/Dockerfile.ubu new file mode 100644 index 0000000..1502a28 --- /dev/null +++ b/dockerfiles/Dockerfile.ubu @@ -0,0 +1,17 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y autoconf build-essential wget git liblz4-dev libmbedtls-dev + +ADD . /ovpn3/core + +ENV O3 /ovpn3/ +ENV DEP_DIR /ovpn3/deps +ENV DL /ovpn3/dl + +CMD mkdir $DEP_DIR && mkdir $DL && \ + /ovpn3/core/scripts/linux/build-all && \ + cd $O3/core/test/ovpncli && \ + ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \ + cd $O3/core/test/ssl && \ + ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \ + ./proto diff --git a/javacli/.gitignore b/javacli/.gitignore new file mode 100644 index 0000000..2ae5f45 --- /dev/null +++ b/javacli/.gitignore @@ -0,0 +1,7 @@ +build +ovpncli_wrap.cxx +ovpncli_wrap.h +ovpncli.java +ovpncliJNI.java +ClientAPI_*.java +SWIGTYPE_*.java diff --git a/javacli/Client.java b/javacli/Client.java new file mode 100644 index 0000000..b351789 --- /dev/null +++ b/javacli/Client.java @@ -0,0 +1,144 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// TESTING_ONLY + +public class Client implements OpenVPNClientThread.EventReceiver { + private OpenVPNClientThread client_thread; + + public static class ConfigError extends Exception { + public ConfigError(String msg) { super(msg); } + } + + public static class CredsUnspecifiedError extends Exception { + public CredsUnspecifiedError(String msg) { super(msg); } + } + + // Load OpenVPN core (implements ClientAPI_OpenVPNClient) from shared library + static { + System.loadLibrary("ovpncli"); + ClientAPI_OpenVPNClient.init_process(); + String test = ClientAPI_OpenVPNClient.crypto_self_test(); + System.out.format("CRYPTO SELF TEST: %s", test); + } + + public Client(String config_text, String username, String password) throws ConfigError, CredsUnspecifiedError { + // init client implementation object + client_thread = new OpenVPNClientThread(); + + // load/eval config + ClientAPI_Config config = new ClientAPI_Config(); + config.setContent(config_text); + config.setCompressionMode("yes"); + ClientAPI_EvalConfig ec = client_thread.eval_config(config); + if (ec.getError()) + throw new ConfigError("OpenVPN config file parse error: " + ec.getMessage()); + + // handle creds + ClientAPI_ProvideCreds creds = new ClientAPI_ProvideCreds(); + if (!ec.getAutologin()) + { + if (username.length() > 0) + { + creds.setUsername(username); + creds.setPassword(password); + creds.setReplacePasswordWithSessionID(true); + } + else + throw new CredsUnspecifiedError("OpenVPN config file requires username/password but none provided"); + } + client_thread.provide_creds(creds); + } + + public void connect() { + // connect + client_thread.connect(this); + + // wait for worker thread to exit + client_thread.wait_thread_long(); + } + + public void stop() { + client_thread.stop(); + } + + public void show_stats() { + int n = client_thread.stats_n(); + for (int i = 0; i < n; ++i) + { + String name = client_thread.stats_name(i); + long value = client_thread.stats_value(i); + if (value > 0) + System.out.format("STAT %s=%s%n", name, value); + } + } + + @Override + public void event(ClientAPI_Event event) { + boolean error = event.getError(); + String name = event.getName(); + String info = event.getInfo(); + System.out.format("EVENT: err=%b name=%s info='%s'%n", error, name, info); + } + + // Callback to get a certificate + @Override + public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req) { + req.setError(true); + req.setErrorText("cert request failed: external PKI not implemented"); + } + + // Callback to sign data + @Override + public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req) { + req.setError(true); + req.setErrorText("sign request failed: external PKI not implemented"); + } + + @Override + public void log(ClientAPI_LogInfo loginfo) { + String text = loginfo.getText(); + System.out.format("LOG: %s", text); + } + + @Override + public void done(ClientAPI_Status status) { + System.out.format("DONE ClientAPI_Status: err=%b msg='%s'%n", status.getError(), status.getMessage()); + } + + @Override + public boolean socket_protect(int socket) + { + return false; + } + + @Override + public boolean pause_on_connection_timeout() + { + return false; + } + + @Override + public OpenVPNClientThread.TunBuilder tun_builder_new() + { + return null; + } + } diff --git a/javacli/Main.java b/javacli/Main.java new file mode 100644 index 0000000..99936ea --- /dev/null +++ b/javacli/Main.java @@ -0,0 +1,97 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// TESTING_ONLY + +import java.io.*; +import java.nio.charset.Charset; + +public class Main { + // utility method to read a file and return as a String + public static String readFile(String filename) throws IOException { + return readStream(new FileInputStream(filename)); + } + + private static String readStream(InputStream stream) throws IOException { + // No real need to close the BufferedReader/InputStreamReader + // as they're only wrapping the stream + try { + Reader reader = new BufferedReader(new InputStreamReader(stream)); + StringBuilder builder = new StringBuilder(); + char[] buffer = new char[4096]; + int read; + while ((read = reader.read(buffer, 0, buffer.length)) > 0) { + builder.append(buffer, 0, read); + } + return builder.toString(); + } finally { + // Potential issue here: if this throws an IOException, + // it will mask any others. Normally I'd use a utility + // method which would log exceptions and swallow them + stream.close(); + } + } + + public static void main(String[] args) throws IOException, Client.ConfigError, Client.CredsUnspecifiedError { + if (args.length >= 1) + { + // load config file + String config = readFile(args[0]); + + // get creds + String username = ""; + String password = ""; + if (args.length >= 3) + { + username = args[1]; + password = args[2]; + } + + // instantiate client object + final Client client = new Client(config, username, password); + + // catch signals + final Thread mainThread = Thread.currentThread(); + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + client.stop(); + try { + mainThread.join(); + } + catch (InterruptedException e) { + } + } + }); + + // execute client session + client.connect(); + + // show stats before exit + client.show_stats(); + } + else + { + System.err.println("OpenVPN Java client"); + System.err.println("Usage: java Client [username] [password]"); + System.exit(2); + } + } +} diff --git a/javacli/OpenVPNClientThread.java b/javacli/OpenVPNClientThread.java new file mode 100644 index 0000000..269a22c --- /dev/null +++ b/javacli/OpenVPNClientThread.java @@ -0,0 +1,359 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// package OPENVPN_PACKAGE + +import java.util.HashSet; + +public class OpenVPNClientThread extends ClientAPI_OpenVPNClient implements Runnable { + private EventReceiver parent; + private TunBuilder tun_builder; + private Thread thread; + private ClientAPI_Status m_connect_status; + private boolean connect_called = false; + + private int bytes_in_index = -1; + private int bytes_out_index = -1; + + // thrown if instantiator attempts to call connect more than once + public static class ConnectCalledTwice extends RuntimeException { + } + + public interface EventReceiver { + // Called with events from core + void event(ClientAPI_Event event); + + // Called with log text from core + void log(ClientAPI_LogInfo loginfo); + + // Called when connect() thread exits + void done(ClientAPI_Status status); + + // Called to "protect" a socket from being routed through the tunnel + boolean socket_protect(int socket); + + // When a connection is close to timeout, the core will call this + // method. If it returns false, the core will disconnect with a + // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE + // state. + boolean pause_on_connection_timeout(); + + // Callback to construct a new tun builder + TunBuilder tun_builder_new(); + + // Callback to get a certificate + void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req); + + // Callback to sign data + void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req); + } + + public interface TunBuilder { + // Tun builder methods. + // Methods documented in openvpn/tun/builder/base.hpp + + boolean tun_builder_set_remote_address(String address, boolean ipv6); + boolean tun_builder_add_address(String address, int prefix_length, String gateway, boolean ipv6, boolean net30); + boolean tun_builder_reroute_gw(boolean ipv4, boolean ipv6, long flags); + boolean tun_builder_add_route(String address, int prefix_length, boolean ipv6); + boolean tun_builder_exclude_route(String address, int prefix_length, boolean ipv6); + boolean tun_builder_add_dns_server(String address, boolean ipv6); + boolean tun_builder_add_search_domain(String domain); + boolean tun_builder_set_mtu(int mtu); + boolean tun_builder_set_session_name(String name); + int tun_builder_establish(); + void tun_builder_teardown(boolean disconnect); + } + + public OpenVPNClientThread() { + final int n = stats_n(); + for (int i = 0; i < n; ++i) + { + String name = stats_name(i); + if (name.equals("BYTES_IN")) + bytes_in_index = i; + if (name.equals("BYTES_OUT")) + bytes_out_index = i; + } + } + + // start connect session in worker thread + public void connect(EventReceiver parent_arg) { + if (connect_called) + throw new ConnectCalledTwice(); + connect_called = true; + + // direct client callbacks to parent + parent = parent_arg; + + // clear status + m_connect_status = null; + + // execute client in a worker thread + thread = new Thread(this, "OpenVPNClientThread"); + thread.start(); + } + + // Wait for worker thread to complete; to stop thread, + // first call super stop() method then wait_thread(). + // This method will give the thread one second to + // exit and will abandon it after this time. + public void wait_thread_short() { + final int wait_millisecs = 5000; // max time that we will wait for thread to exit + Thread th = thread; + if (th != null) { + try { + th.join(wait_millisecs); + } + catch (InterruptedException e) { + } + + // thread failed to stop? + if (th.isAlive()) { + // abandon thread and deliver our own status object to instantiator. + ClientAPI_Status status = new ClientAPI_Status(); + status.setError(true); + status.setMessage("CORE_THREAD_ABANDONED"); + call_done(status); + } + } + } + + // Wait for worker thread to complete; to stop thread, + // first call super stop() method then wait_thread(). + // This method will wait forever for the thread to exit. + public void wait_thread_long() { + if (thread != null) { + boolean interrupted; + do { + interrupted = false; + try { + thread.join(); + } + catch (InterruptedException e) { + interrupted = true; + super.stop(); // send thread a stop message + } + } while (interrupted); + } + } + + public long bytes_in() + { + return super.stats_value(bytes_in_index); + } + + public long bytes_out() + { + return super.stats_value(bytes_out_index); + } + + private void call_done(ClientAPI_Status status) + { + EventReceiver p = finalize_thread(status); + if (p != null) + p.done(m_connect_status); + } + + private synchronized EventReceiver finalize_thread(ClientAPI_Status connect_status) + { + EventReceiver p = parent; + if (p != null) { + // save thread connection status + m_connect_status = connect_status; + + // disassociate client callbacks from parent + parent = null; + tun_builder = null; + thread = null; + } + return p; + } + + // Runnable overrides + + @Override + public void run() { + // Call out to core to start connection. + // Doesn't return until connection has terminated. + ClientAPI_Status status = super.connect(); + call_done(status); + } + + // ClientAPI_OpenVPNClient (C++ class) overrides + + @Override + public boolean socket_protect(int socket) { + EventReceiver p = parent; + if (p != null) + return p.socket_protect(socket); + else + return false; + } + + @Override + public boolean pause_on_connection_timeout() { + EventReceiver p = parent; + if (p != null) + return p.pause_on_connection_timeout(); + else + return false; + } + + @Override + public void event(ClientAPI_Event event) { + EventReceiver p = parent; + if (p != null) + p.event(event); + } + + @Override + public void log(ClientAPI_LogInfo loginfo) { + EventReceiver p = parent; + if (p != null) + p.log(loginfo); + } + + @Override + public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req) { + EventReceiver p = parent; + if (p != null) + p.external_pki_cert_request(req); + } + + @Override + public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req) { + EventReceiver p = parent; + if (p != null) + p.external_pki_sign_request(req); + } + + // TunBuilderBase (C++ class) overrides + + @Override + public boolean tun_builder_new() { + EventReceiver p = parent; + if (p != null) { + tun_builder = p.tun_builder_new(); + return tun_builder != null; + } else + return false; + } + + @Override + public boolean tun_builder_set_remote_address(String address, boolean ipv6) { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_set_remote_address(address, ipv6); + else + return false; + } + + @Override + public boolean tun_builder_add_address(String address, int prefix_length, String gateway, boolean ipv6, boolean net30) { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_add_address(address, prefix_length, gateway, ipv6, net30); + else + return false; + } + + @Override + public boolean tun_builder_reroute_gw(boolean ipv4, boolean ipv6, long flags) { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_reroute_gw(ipv4, ipv6, flags); + else + return false; + } + + @Override + public boolean tun_builder_add_route(String address, int prefix_length, int metric, boolean ipv6) { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_add_route(address, prefix_length, ipv6); + else + return false; + } + + @Override + public boolean tun_builder_exclude_route(String address, int prefix_length, int metric, boolean ipv6) { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_exclude_route(address, prefix_length, ipv6); + else + return false; + } + + @Override + public boolean tun_builder_add_dns_server(String address, boolean ipv6) { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_add_dns_server(address, ipv6); + else + return false; + } + + @Override + public boolean tun_builder_add_search_domain(String domain) + { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_add_search_domain(domain); + else + return false; + } + + @Override + public boolean tun_builder_set_mtu(int mtu) { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_set_mtu(mtu); + else + return false; + } + + @Override + public boolean tun_builder_set_session_name(String name) + { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_set_session_name(name); + else + return false; + } + + @Override + public int tun_builder_establish() { + TunBuilder tb = tun_builder; + if (tb != null) + return tb.tun_builder_establish(); + else + return -1; + } + + @Override + public void tun_builder_teardown(boolean disconnect) { + TunBuilder tb = tun_builder; + if (tb != null) + tb.tun_builder_teardown(disconnect); + } +} diff --git a/javacli/android/cpu.cpp b/javacli/android/cpu.cpp new file mode 100644 index 0000000..33fd3bb --- /dev/null +++ b/javacli/android/cpu.cpp @@ -0,0 +1,62 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#include +#include +#include + +#ifdef SWIGEXPORT +#define EXPORT SWIGEXPORT +#else +#define EXPORT +#endif + +#ifndef OPENVPN_PACKAGE_ID +#error OPENVPN_PACKAGE_ID must be defined +#endif + +#define MAKE_SYM2(pkg_id, suffix) Java_ ## pkg_id ## _CPUUsage_ ## suffix +#define MAKE_SYM(pkg_id, suffix) MAKE_SYM2(pkg_id, suffix) + +#define CPU_USAGE MAKE_SYM(OPENVPN_PACKAGE_ID, cpu_1usage) + +extern "C" { + jdouble CPU_USAGE(JNIEnv* env, jclass); +}; + +EXPORT jdouble CPU_USAGE(JNIEnv* env, jclass) +{ + char fnbuf[64]; + const pid_t pid = getpid(); + double ret = 0.0; + + snprintf(fnbuf, sizeof(fnbuf), "/proc/%u/stat", (unsigned int)pid); + FILE *fp = fopen(fnbuf, "r"); + if (fp) + { + double user = 0.0; + double system = 0.0; + if (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lf %lf", &user, &system) == 2) + ret = (user + system) / sysconf(_SC_CLK_TCK); + fclose(fp); + } + return ret; +} diff --git a/javacli/android/jellybean_hack.cpp b/javacli/android/jellybean_hack.cpp new file mode 100644 index 0000000..d9c0d4c --- /dev/null +++ b/javacli/android/jellybean_hack.cpp @@ -0,0 +1,178 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Native companion code for JellyBeanHack.java + +#include +#include +#include + +#include + +#ifdef SWIGEXPORT +#define EXPORT SWIGEXPORT +#else +#define EXPORT +#endif + +#ifndef OPENVPN_PACKAGE_ID +#error OPENVPN_PACKAGE_ID must be defined +#endif + +#define MAKE_SYM2(pkg_id, suffix) Java_ ## pkg_id ## _JellyBeanHack_ ## suffix +#define MAKE_SYM(pkg_id, suffix) MAKE_SYM2(pkg_id, suffix) + +#define RSA_SIGN_INIT MAKE_SYM(OPENVPN_PACKAGE_ID, rsa_1sign_1init) +#define RSA_SIGN MAKE_SYM(OPENVPN_PACKAGE_ID, rsa_1sign) +#define PKEY_RETAIN MAKE_SYM(OPENVPN_PACKAGE_ID, pkey_1retain) + +extern "C" { + jint RSA_SIGN_INIT(JNIEnv* env, jclass); + jbyteArray RSA_SIGN(JNIEnv* env, jclass, jbyteArray from, jint pkeyRef); + void PKEY_RETAIN(JNIEnv* env, jclass, jint pkeyRef); +}; + +typedef void *RSA; + +enum { + NID_md5_sha1=114, + CRYPTO_LOCK_EVP_PKEY=10, +}; + +struct EVP_PKEY +{ + int type; + int save_type; + int references; + void *ameth; + void *engine; + union { + RSA *rsa; + } pkey; +}; + +typedef int (*RSA_size_func_t)(const RSA *); + +typedef int (*RSA_sign_func_t)(int type, const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); + +typedef void (*ERR_print_errors_fp_func_t)(FILE *fp); + +typedef int (*CRYPTO_add_lock_func_t)(int *pointer, int amount, int type, const char *file, int line); + +static bool initialized; +static RSA_size_func_t RSA_size; +static RSA_sign_func_t RSA_sign; +static ERR_print_errors_fp_func_t ERR_print_errors_fp; +static CRYPTO_add_lock_func_t CRYPTO_add_lock; + +inline bool callbacks_defined() +{ + return RSA_size != NULL + && RSA_sign != NULL + && ERR_print_errors_fp != NULL + && CRYPTO_add_lock != NULL; +} + +EXPORT jint RSA_SIGN_INIT(JNIEnv* env, jclass) +{ + if (!initialized) + { + void *handle = dlopen("libcrypto.so", RTLD_NOW); + if (handle) + { + RSA_size = (RSA_size_func_t) dlsym(handle, "RSA_size"); + RSA_sign = (RSA_sign_func_t) dlsym(handle, "RSA_sign"); + ERR_print_errors_fp = (ERR_print_errors_fp_func_t) dlsym(handle, "ERR_print_errors_fp"); + CRYPTO_add_lock = (CRYPTO_add_lock_func_t) dlsym(handle, "CRYPTO_add_lock"); + } + initialized = true; + } + return callbacks_defined(); +} + +static int jni_throw(JNIEnv* env, const char* className, const char* msg) +{ + jclass exceptionClass = env->FindClass(className); + + if (exceptionClass == NULL) { + // ClassNotFoundException now pending + return -1; + } + + if (env->ThrowNew( exceptionClass, msg) != JNI_OK) { + // an exception, most likely OOM, will now be pending + return -1; + } + + env->DeleteLocalRef(exceptionClass); + return 0; +} + +EXPORT jbyteArray RSA_SIGN(JNIEnv* env, jclass, jbyteArray from, jint pkeyRef) +{ + if (!callbacks_defined()) + { + jni_throw(env, "java/lang/NullPointerException", "rsa_sign: OpenSSL callbacks undefined"); + return NULL; + } + + EVP_PKEY* pkey = reinterpret_cast(pkeyRef); + if (pkey == NULL || from == NULL) + { + jni_throw(env, "java/lang/NullPointerException", "rsa_sign: from/pkey is NULL"); + return NULL; + } + + jbyte* data = env->GetByteArrayElements(from, NULL); + if (data == NULL) + { + jni_throw(env, "java/lang/NullPointerException", "rsa_sign: data is NULL"); + return NULL; + } + int datalen = env->GetArrayLength(from); + + unsigned int siglen; + unsigned char* sigret = new unsigned char[(*RSA_size)(pkey->pkey.rsa)]; + + if ((*RSA_sign)(NID_md5_sha1, (unsigned char*) data, datalen, + sigret, &siglen, pkey->pkey.rsa) <= 0) + { + jni_throw(env, "java/security/InvalidKeyException", "OpenSSL RSA_sign failed"); + (*ERR_print_errors_fp)(stderr); + return NULL; + } + + jbyteArray jb = env->NewByteArray(siglen); + env->SetByteArrayRegion(jb, 0, siglen, (jbyte *)sigret); + delete [] sigret; + return jb; +} + +EXPORT void PKEY_RETAIN(JNIEnv* env, jclass, jint pkeyRef) +{ + EVP_PKEY* pkey = reinterpret_cast(pkeyRef); + if (pkey && CRYPTO_add_lock) + { + const int newref = (*CRYPTO_add_lock)(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY, __FILE__, __LINE__); + __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "pkey_retain ref=%d", newref); + } +} diff --git a/javacli/build-android b/javacli/build-android new file mode 100755 index 0000000..2fcfa40 --- /dev/null +++ b/javacli/build-android @@ -0,0 +1,126 @@ +#!/usr/bin/env bash +# generate expire time in python: time.mktime((2012, 5, 1, 0, 0, 0, 0, 0, -1)) +# -DAPP_EXPIRE_TIME=1364796000 \ +set -e + +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi + +cd $O3/core +. vars/android-sdk-path +cd javacli +git clean -q -fXd . + +if [ "$PKG" ]; then + pkg=$PKG + pkg_id_def="-DOPENVPN_PACKAGE_ID=${PKG//./_}" +else + pkg=net.openvpn.openvpn + pkg_id_def="-DOPENVPN_PACKAGE_ID=net_openvpn_openvpn" +fi +echo PACKAGE $PKG + +if [ "$PT_PROXY" = "1" ] && [ -d "$O3/common" ]; then + common="-I$O3/common -DPRIVATE_TUNNEL_PROXY" +else + common="" +fi + +echo SWIG +swig -c++ -java -package $pkg -I$O3/core/client -I$O3/core ovpncli.i + +TARGETS=${TARGETS:-android-a7a android-a8a android-x86} + +for TARGET in $TARGETS; do + +if [ "$DEBUG_BUILD" = "1" ]; then + . ../vars/vars-${TARGET}-dbg + vis1="" + vis2="" + opt2="$pkg_id_def $LIB_OPT_LEVEL" +else + . ../vars/vars-${TARGET} + vis1="-fvisibility=hidden" + vis2='-DSWIGEXPORT=__attribute__((visibility("default")))' + opt2="$pkg_id_def -Os" +fi + +if [ "$OPENSSL" = "1" ]; then + ssl_def="-DUSE_OPENSSL" + ssl_inc="-I$DEP_DIR/openssl/openssl-$PLATFORM/include" + ssl_lib="-lssl -lcrypto" + ssl_libdir="-L$DEP_DIR/openssl/openssl-$PLATFORM/lib" +else + ssl_def="-DUSE_MBEDTLS" + ssl_inc="-I$DEP_DIR/mbedtls/mbedtls-$PLATFORM/include" + ssl_lib="-lmbedtls" + ssl_libdir="-L$DEP_DIR/mbedtls/mbedtls-$PLATFORM/library" +fi + +[ -z "$GPP_CMD" ] && GPP_CMD=g++ + +echo CORE $ABI +$GPP_CMD \ + $CXX_COMPILER_FLAGS \ + $PLATFORM_FLAGS \ + $OTHER_COMPILER_FLAGS \ + $LIB_OPT_LEVEL $LIB_FPIC \ + -Wall -Wno-sign-compare -Wno-unused-parameter \ + -Wno-unused-local-typedefs \ + $vis1 \ + $ssl_def \ + -DUSE_ASIO \ + -DASIO_STANDALONE \ + -DASIO_NO_DEPRECATED \ + -DHAVE_LZ4 \ + -DOPENVPN_USE_TLS_MD5 \ + -DASIO_HAS_STD_STRING_VIEW \ + -I$O3/core/client \ + -I$O3/core \ + $common \ + -I$DEP_DIR/asio/asio/include \ + $ssl_inc \ + -I$DEP_DIR/lz4/lz4-$PLATFORM/include \ + -c $O3/core/client/ovpncli.cpp + +echo WRAP $ABI +$GPP_CMD \ + $CXX_COMPILER_FLAGS \ + $PLATFORM_FLAGS \ + $OTHER_COMPILER_FLAGS \ + $opt2 $LIB_FPIC \ + -fno-strict-aliasing \ + -Wall \ + $vis1 $vis2 \ + -I$O3/core/client \ + -I$O3/core \ + $common \ + $ssl_libdir \ + -L$DEP_DIR/lz4/lz4-$PLATFORM/lib \ + ovpncli_wrap.cxx \ + android/jellybean_hack.cpp \ + android/cpu.cpp \ + ovpncli.o \ + -o libovpncli.so \ + -shared -Wl,-soname,libovpncli.so \ + $ssl_lib \ + -llz4 \ + -llog + +if [ "$DEBUG_BUILD" != "1" ]; then + echo STRIP $ABI + strip libovpncli.so +fi + +mkdir -p build/libs/$ABI +mv libovpncli.so build/libs/$ABI/ +rm ovpncli.o +done + +mv ovpncli_wrap.cxx ovpncli_wrap.h ovpncli.java ovpncliJNI.java SWIGTYPE_*.java ClientAPI_*.java build/ +git clean -q -fX . + +tar -czf android-core-build.tgz build +mv android-core-build.tgz $O3/ diff --git a/javacli/build-linux b/javacli/build-linux new file mode 100755 index 0000000..d0e37a1 --- /dev/null +++ b/javacli/build-linux @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +# Build OpenVPN 3 core on Linux as a callable module from Java: +# +# ./build-linux +# java -Djava.library.path=. Main profile.ovpn + +set -e + +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi + +TARGET=linux +JINC="-I/usr/local/java/jdk1.7.0_55/include -I/usr/local/java/jdk1.7.0_55/include/linux" + +cd $O3/core/javacli +git clean -q -fXd . +git clean -q -fd . + +if [ "$DEBUG_BUILD" = "1" ]; then + . $O3/core/vars/vars-${TARGET}-dbg + vis1="" + vis2="" + opt2="$pkg_id_def $LIB_OPT_LEVEL" +else + . $O3/core/vars/vars-${TARGET} + vis1="-fvisibility=hidden" + vis2='-DSWIGEXPORT=__attribute__((visibility("default")))' + opt2="$pkg_id_def -Os" +fi + +if [ "$OPENSSL" = "1" ]; then + ssl_def="-DUSE_OPENSSL" + ssl_inc="-I$DEP_DIR/openssl/openssl-$PLATFORM/include" + ssl_lib="-lssl -lcrypto" + ssl_libdir="-L$DEP_DIR/openssl/openssl-$PLATFORM/lib" +else + ssl_def="-DUSE_MBEDTLS" + ssl_inc="-I$DEP_DIR/mbedtls/mbedtls-$PLATFORM/include" + ssl_lib="-lmbedtls" + ssl_libdir="-L$DEP_DIR/mbedtls/mbedtls-$PLATFORM/library" +fi + +echo SWIG +swig -c++ -java -I$O3/core/client -I$O3/core ovpncli.i + +echo JAVA +javac *.java + +echo CORE +g++ \ + $CXX_COMPILER_FLAGS \ + $PLATFORM_FLAGS \ + $LIB_OPT_LEVEL $LIB_FPIC \ + -Wall -Werror -Wno-sign-compare -Wno-unused-parameter \ + -Wno-unused-local-typedefs \ + $vis1 \ + $ssl_def \ + -DUSE_ASIO \ + -DASIO_STANDALONE \ + -DASIO_NO_DEPRECATED \ + -DHAVE_LZ4 \ + -I$O3/core/client \ + -I$O3/core \ + -I$DEP_DIR/asio/asio/include \ + $ssl_inc \ + -I$DEP_DIR/lz4/lz4-$PLATFORM/include \ + -c $O3/core/client/ovpncli.cpp + +echo WRAP +g++ \ + $CXX_COMPILER_FLAGS \ + $PLATFORM_FLAGS \ + $opt2 $LIB_FPIC \ + -fno-strict-aliasing \ + -Wall -Werror \ + $vis1 $vis2 \ + -I$O3/core/client \ + -I$O3/core \ + $JINC \ + $ssl_libdir \ + -L$DEP_DIR/lz4/lz4-$PLATFORM/lib \ + ovpncli_wrap.cxx \ + ovpncli.o \ + -o libovpncli.so \ + -shared -Wl,-soname,libovpncli.so \ + $ssl_lib \ + -llz4 + +if [ "$DEBUG_BUILD" != "1" ]; then + echo STRIP $ABI + strip libovpncli.so +fi diff --git a/javacli/ovpncli.i b/javacli/ovpncli.i new file mode 100644 index 0000000..0671a6d --- /dev/null +++ b/javacli/ovpncli.i @@ -0,0 +1,55 @@ +// SWIG interface file for OpenVPN client + +// enable director feature for OpenVPNClientBase virtual method callbacks +%module(directors="1") ovpncli +%feature("director") OpenVPNClient; + +%include "std_string.i" // for std::string typemaps +%include "std_vector.i" + +// top-level C++ implementation file +%{ +#include "ovpncli.hpp" +%} + +// ignore these ClientAPI::OpenVPNClient bases +%ignore openvpn::ClientAPI::LogReceiver; +%ignore openvpn::ExternalTun::Factory; +%ignore openvpn::ExternalTransport::Factory; + +// modify exported C++ class names to incorporate their enclosing namespace +%rename(ClientAPI_OpenVPNClient) OpenVPNClient; +%rename(ClientAPI_TunBuilderBase) TunBuilderBase; +%rename(ClientAPI_ExternalPKIBase) ExternalPKIBase; +%rename(ClientAPI_ServerEntry) ServerEntry; +%rename(ClientAPI_EvalConfig) EvalConfig; +%rename(ClientAPI_ProvideCreds) ProvideCreds; +%rename(ClientAPI_SessionToken) SessionToken; +%rename(ClientAPI_DynamicChallenge) DynamicChallenge; +%rename(ClientAPI_KeyValue) KeyValue; +%rename(ClientAPI_Config) Config; +%rename(ClientAPI_Event) Event; +%rename(ClientAPI_ConnectionInfo) ConnectionInfo; +%rename(ClientAPI_Status) Status; +%rename(ClientAPI_LogInfo) LogInfo; +%rename(ClientAPI_InterfaceStats) InterfaceStats; +%rename(ClientAPI_TransportStats) TransportStats; +%rename(ClientAPI_MergeConfig) MergeConfig; +%rename(ClientAPI_ExternalPKIRequestBase) ExternalPKIRequestBase; +%rename(ClientAPI_ExternalPKICertRequest) ExternalPKICertRequest; +%rename(ClientAPI_ExternalPKISignRequest) ExternalPKISignRequest; +%rename(ClientAPI_RemoteOverride) RemoteOverride; + +// declare vectors +namespace std { + %template(ClientAPI_ServerEntryVector) vector; + %template(ClientAPI_LLVector) vector; + %template(ClientAPI_StringVec) vector; +}; + +// interface to be bridged between C++ and target language +%include "openvpn/pki/epkibase.hpp" +%include "openvpn/tun/builder/base.hpp" +%import "openvpn/tun/extern/fw.hpp" // ignored +%import "openvpn/transport/client/extern/fw.hpp" // ignored +%include "ovpncli.hpp" diff --git a/mac/.gitignore b/mac/.gitignore new file mode 100644 index 0000000..14ce7f3 --- /dev/null +++ b/mac/.gitignore @@ -0,0 +1 @@ +**/xcuserdata/ diff --git a/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj b/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj new file mode 100644 index 0000000..4df459d --- /dev/null +++ b/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj @@ -0,0 +1,342 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + DF380AE2201F0A2F0003272D /* cli.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF380AE1201F0A2F0003272D /* cli.cpp */; }; + DF380AE5201F0D4F0003272D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE4201F0D4F0003272D /* CoreFoundation.framework */; }; + DF380AE7201F0D910003272D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE6201F0D910003272D /* SystemConfiguration.framework */; }; + DF380AE9201F0DB80003272D /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE8201F0DB80003272D /* IOKit.framework */; }; + DF380AEB201F0DDC0003272D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AEA201F0DDC0003272D /* CoreServices.framework */; }; + DF380AED201F0E0E0003272D /* libmbedtls.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AEC201F0E0E0003272D /* libmbedtls.a */; }; + DF838B412090AC2F00B68F90 /* liblz4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF838B402090AC2F00B68F90 /* liblz4.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + DF380AD4201F07AE0003272D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + DF380AD6201F07AE0003272D /* ovpn3-core */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ovpn3-core"; sourceTree = BUILT_PRODUCTS_DIR; }; + DF380AE0201F09B70003272D /* openvpn */ = {isa = PBXFileReference; lastKnownFileType = folder; name = openvpn; path = ../../../openvpn; sourceTree = ""; }; + DF380AE1201F0A2F0003272D /* cli.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cli.cpp; path = ../../../test/ovpncli/cli.cpp; sourceTree = ""; }; + DF380AE4201F0D4F0003272D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + DF380AE6201F0D910003272D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + DF380AE8201F0DB80003272D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + DF380AEA201F0DDC0003272D /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; + DF380AEC201F0E0E0003272D /* libmbedtls.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedtls.a; path = "../../../deps/mbedtls/mbedtls-osx/library/libmbedtls.a"; sourceTree = ""; }; + DF838B402090AC2F00B68F90 /* liblz4.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblz4.a; path = "../../../deps/lz4/lz4-osx/lib/liblz4.a"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DF380AD3201F07AE0003272D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DF838B412090AC2F00B68F90 /* liblz4.a in Frameworks */, + DF380AED201F0E0E0003272D /* libmbedtls.a in Frameworks */, + DF380AEB201F0DDC0003272D /* CoreServices.framework in Frameworks */, + DF380AE9201F0DB80003272D /* IOKit.framework in Frameworks */, + DF380AE7201F0D910003272D /* SystemConfiguration.framework in Frameworks */, + DF380AE5201F0D4F0003272D /* CoreFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + DF380ACD201F07AE0003272D = { + isa = PBXGroup; + children = ( + DF380AD8201F07AE0003272D /* ovpn3-core */, + DF380AD7201F07AE0003272D /* Products */, + DF380AE3201F0D4F0003272D /* Frameworks */, + ); + sourceTree = ""; + }; + DF380AD7201F07AE0003272D /* Products */ = { + isa = PBXGroup; + children = ( + DF380AD6201F07AE0003272D /* ovpn3-core */, + ); + name = Products; + sourceTree = ""; + }; + DF380AD8201F07AE0003272D /* ovpn3-core */ = { + isa = PBXGroup; + children = ( + DF380AE1201F0A2F0003272D /* cli.cpp */, + DF380AE0201F09B70003272D /* openvpn */, + ); + path = "ovpn3-core"; + sourceTree = ""; + }; + DF380AE3201F0D4F0003272D /* Frameworks */ = { + isa = PBXGroup; + children = ( + DF838B402090AC2F00B68F90 /* liblz4.a */, + DF380AEC201F0E0E0003272D /* libmbedtls.a */, + DF380AEA201F0DDC0003272D /* CoreServices.framework */, + DF380AE8201F0DB80003272D /* IOKit.framework */, + DF380AE6201F0D910003272D /* SystemConfiguration.framework */, + DF380AE4201F0D4F0003272D /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + DF380AD5201F07AE0003272D /* ovpn3-core */ = { + isa = PBXNativeTarget; + buildConfigurationList = DF380ADD201F07AE0003272D /* Build configuration list for PBXNativeTarget "ovpn3-core" */; + buildPhases = ( + DF380AD2201F07AE0003272D /* Sources */, + DF380AD3201F07AE0003272D /* Frameworks */, + DF380AD4201F07AE0003272D /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ovpn3-core"; + productName = "ovpn3-core"; + productReference = DF380AD6201F07AE0003272D /* ovpn3-core */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DF380ACE201F07AE0003272D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = "Lev Stipakov"; + TargetAttributes = { + DF380AD5201F07AE0003272D = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = DF380AD1201F07AE0003272D /* Build configuration list for PBXProject "ovpn3-core" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = DF380ACD201F07AE0003272D; + productRefGroup = DF380AD7201F07AE0003272D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DF380AD5201F07AE0003272D /* ovpn3-core */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + DF380AD2201F07AE0003272D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DF380AE2201F0A2F0003272D /* cli.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + DF380ADB201F07AE0003272D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + DF380ADC201F07AE0003272D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + DF380ADE201F07AE0003272D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + GCC_PREPROCESSOR_DEFINITIONS = ( + USE_ASIO, + ASIO_STANDALONE, + USE_MBEDTLS, + HAVE_LZ4, + LZ4_DISABLE_DEPRECATE_WARNINGS, + ); + HEADER_SEARCH_PATHS = ( + "\"$(SRCROOT)/../..\"", + "\"$(SRCROOT)/../../../deps/asio/asio/include\"", + "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/include\"", + "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/include\"", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\"", + "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/lib\"", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; + }; + name = Debug; + }; + DF380ADF201F07AE0003272D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + GCC_PREPROCESSOR_DEFINITIONS = ( + USE_ASIO, + ASIO_STANDALONE, + USE_MBEDTLS, + HAVE_LZ4, + LZ4_DISABLE_DEPRECATE_WARNINGS, + ); + HEADER_SEARCH_PATHS = ( + "\"$(SRCROOT)/../..\"", + "\"$(SRCROOT)/../../../deps/asio/asio/include\"", + "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/include\"", + "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/include\"", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\"", + "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/lib\"", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DF380AD1201F07AE0003272D /* Build configuration list for PBXProject "ovpn3-core" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DF380ADB201F07AE0003272D /* Debug */, + DF380ADC201F07AE0003272D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DF380ADD201F07AE0003272D /* Build configuration list for PBXNativeTarget "ovpn3-core" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DF380ADE201F07AE0003272D /* Debug */, + DF380ADF201F07AE0003272D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DF380ACE201F07AE0003272D /* Project object */; +} diff --git a/mac/ovpn3-core/ovpn3-core.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/mac/ovpn3-core/ovpn3-core.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1595398 --- /dev/null +++ b/mac/ovpn3-core/ovpn3-core.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/openvpn/addr/addrlist.hpp b/openvpn/addr/addrlist.hpp new file mode 100644 index 0000000..0db21d8 --- /dev/null +++ b/openvpn/addr/addrlist.hpp @@ -0,0 +1,65 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_ADDRLIST_H +#define OPENVPN_ADDR_ADDRLIST_H + +#include +#include + +namespace openvpn { + namespace IP { + + // A list of unique IP addresses + class AddrList : public std::vector, public RC + { + public: + typedef RCPtr Ptr; + + void add(const IP::Addr& a) + { + if (!exists(a)) + push_back(a); + } + + bool exists(const IP::Addr& a) const + { + for (const_iterator i = begin(); i != end(); ++i) + { + if (a == *i) + return true; + } + return false; + } + +#if 0 + void dump() const + { + OPENVPN_LOG("******* AddrList::dump"); + for (const_iterator i = begin(); i != end(); ++i) + OPENVPN_LOG(i->to_string()); + } +#endif + }; + } +} + +#endif diff --git a/openvpn/addr/addrpair.hpp b/openvpn/addr/addrpair.hpp new file mode 100644 index 0000000..b8bfc1e --- /dev/null +++ b/openvpn/addr/addrpair.hpp @@ -0,0 +1,218 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_ADDRPAIR_H +#define OPENVPN_ADDR_ADDRPAIR_H + +#include + +#include +#include +#include +#include + +namespace openvpn { + namespace IP { + + // AddrMaskPair is basically an object that combines an IP address (v4 or v6) + // with a netmask or prefix length. + struct AddrMaskPair + { + public: + OPENVPN_EXCEPTION(addr_pair_mask_parse_error); + + class StringPair { + public: + OPENVPN_SIMPLE_EXCEPTION(addr_pair_string_error); + + StringPair() + : size_(0) + { + } + + explicit StringPair(const std::string& s1) + : size_(1) + { + data[0] = s1; + } + + explicit StringPair(const std::string& s1, const std::string& s2) + : size_(2) + { + data[0] = s1; + data[1] = s2; + } + + void push_back(const std::string& s) + { + if (size_ < 2) + data[size_++] = s; + else + throw addr_pair_string_error(); + } + + const std::string& operator[](const size_t i) const + { + if (i >= 2) + throw addr_pair_string_error(); + return data[i]; + } + + std::string& operator[](const size_t i) + { + if (i >= 2) + throw addr_pair_string_error(); + return data[i]; + } + + size_t size() const { return size_; } + + std::string render() const + { + switch (size_) + { + case 1: + return data[0]; + case 2: + return data[0] + "/" + data[1]; + default: + return ""; + } + } + + private: + std::string data[2]; + unsigned int size_; + }; + + static AddrMaskPair from_string(const std::string& s1, const std::string& s2, const char *title = nullptr) + { + try { + if (s2.empty()) + { + const StringPair pair = Split::by_char(s1, '/'); + return from_string_impl(pair, title); + } + else + { + const StringPair pair(s1, s2); + return from_string_impl(pair, title); + } + } + catch (const std::exception& e) + { + const StringPair pair(s1, s2); + error(e, pair.render(), title); + } + return AddrMaskPair(); // NOTREACHED + } + + static AddrMaskPair from_string(const std::string& s, const char *title = nullptr) + { + try { + const StringPair pair = Split::by_char(s, '/'); + return from_string_impl(pair, title); + } + catch (const std::exception& e) + { + error(e, s, title); + } + return AddrMaskPair(); // NOTREACHED + } + + static AddrMaskPair from_string(const StringPair& pair, const char *title = nullptr) + { + try { + return from_string_impl(pair, title); + } + catch (const std::exception& e) + { + error(e, pair.render(), title); + } + return AddrMaskPair(); // NOTREACHED + } + + std::string to_string(const bool netmask_form=false) const + { + std::ostringstream os; + if (netmask_form) + os << addr.to_string() << '/' << netmask.to_string(); + else + os << addr.to_string() << '/' << netmask.prefix_len(); + return os.str(); + } + + bool is_canonical() const + { + return (addr & netmask) == addr; + } + + Addr::Version version() const + { + const Addr::Version v1 = addr.version(); + const Addr::Version v2 = netmask.version(); + if (v1 == v2) + return v1; + else + return Addr::UNSPEC; + } + + Addr addr; + Addr netmask; + + private: + static void error(const std::exception& e, const std::string& s, const char *title) + { + if (!title) + title = ""; + OPENVPN_THROW(addr_pair_mask_parse_error, "AddrMaskPair parse error '" << title << "': " << s << " : " << e.what()); + } + + static AddrMaskPair from_string_impl(const StringPair& pair, const char *title = nullptr) + { + AddrMaskPair ret; + if (pair.size() == 1 || pair.size() == 2) + { + ret.addr = Addr::from_string(pair[0], title); + if (pair.size() == 2 && !pair[1].empty()) + { + if (is_number(pair[1].c_str())) + ret.netmask = Addr::netmask_from_prefix_len(ret.addr.version(), + parse_number_throw(pair[1], "prefix length")); + else + ret.netmask = Addr::from_string(pair[1]); + ret.netmask.prefix_len(); // verify that netmask is ok + } + else + ret.netmask = Addr::from_zero_complement(ret.addr.version()); + ret.addr.verify_version_consistency(ret.netmask); + } + else + throw addr_pair_mask_parse_error("only one or two address terms allowed"); + return ret; + } + + }; + OPENVPN_OSTREAM(AddrMaskPair, to_string) + } +} + +#endif diff --git a/openvpn/addr/addrspacesplit.hpp b/openvpn/addr/addrspacesplit.hpp new file mode 100644 index 0000000..8edfa2b --- /dev/null +++ b/openvpn/addr/addrspacesplit.hpp @@ -0,0 +1,109 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Invert a route list. Used to support excluded routes on platforms that +// don't support them natively. + +#pragma once + +#include +#include + +namespace openvpn { + namespace IP { + class AddressSpaceSplitter : public RouteList + { + public: + OPENVPN_EXCEPTION(address_space_splitter); + + AddressSpaceSplitter() {} + + // NOTE: when passing AddressSpaceSplitter to this constructor, make sure + // to static_cast it to RouteList& so as to avoid matching the + // default copy constructor. + explicit AddressSpaceSplitter(const RouteList& in) + : AddressSpaceSplitter(in, in.version_mask()) + { + } + + AddressSpaceSplitter(const RouteList& in, const Addr::VersionMask vermask) + { + in.verify_canonical(); + if (vermask & Addr::V4_MASK) + descend(in, Route(Addr::from_zero(Addr::V4), 0)); + if (vermask & Addr::V6_MASK) + descend(in, Route(Addr::from_zero(Addr::V6), 0)); + } + + private: + enum Type { + EQUAL, + SUBROUTE, + LEAF, + }; + /** + * This method construct a non-overlapping list of routes spanning the address + * space in @param route. The routes are constructed in a way that each + * route in the returned list is smaller or equalto each route in + * parameter @param in + * + * @param route The route we currently are looking at and split if it does + * not meet the requirements + */ + void descend(const RouteList& in, const Route& route) + { + switch (find(in, route)) + { + case SUBROUTE: + { + Route r1, r2; + if (route.split(r1, r2)) + { + descend(in, r1); + descend(in, r2); + } + else + push_back(route); + break; + } + case EQUAL: + case LEAF: + push_back(route); + break; + } + } + + static Type find(const RouteList& in, const Route& route) + { + Type type = LEAF; + for (RouteList::const_iterator i = in.begin(); i != in.end(); ++i) + { + const Route& r = *i; + if (route == r) + type = EQUAL; + else if (route.contains(r)) + return SUBROUTE; + } + return type; + } + }; + } +} diff --git a/openvpn/addr/ip.hpp b/openvpn/addr/ip.hpp new file mode 100644 index 0000000..cd14e5c --- /dev/null +++ b/openvpn/addr/ip.hpp @@ -0,0 +1,992 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_IP_H +#define OPENVPN_ADDR_IP_H + +#include +#include // for std::memset + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + // This is our fundamental IP address class that handles IPv4 or IPv6 + // IP addresses. It is implemented as a discriminated union of IPv4::Addr + // and IPv6::Addr. + namespace IP { + + OPENVPN_EXCEPTION(ip_exception); + + class Addr + { + public: + enum Version { UNSPEC, V4, V6 }; + + enum { V4_MASK=(1<<0), V6_MASK=(1<<1) }; + typedef unsigned int VersionMask; + + enum VersionSize { + V4_SIZE = IPv4::Addr::SIZE, + V6_SIZE = IPv6::Addr::SIZE, + }; + + Addr(const Addr& other, const char *title = nullptr, Version required_version = UNSPEC) + : ver(other.ver) + { + other.validate_version(title, required_version); + switch (ver) + { + case V4: + u.v4 = other.u.v4; + break; + case V6: + u.v6 = other.u.v6; + break; + default: + break; + } + } + + Addr(const std::string& ipstr, const char *title = nullptr, Version required_version = UNSPEC) + : Addr(from_string(ipstr, title, required_version)) + { + } + +#ifndef SWIGPYTHON + // When calling IP:Addr with None as the second parameter, Swig will + // always pick this function and complain about not being able to convert + // a null pointer to a const std::string reference. Hide this function, so + // swig is forced to take the const char* variant of this function instead + Addr(const std::string& ipstr, const std::string& title, Version required_version = UNSPEC) + : Addr(from_string(ipstr, title.c_str(), required_version)) + { + } +#endif + + void validate_version(const char *title, Version required_version) const + { + if (required_version != UNSPEC && required_version != ver) + throw ip_exception(internal::format_error(to_string(), title, version_string_static(required_version), "wrong IP version")); + } + +#ifndef SWIGPYTHON + void validate_version(const std::string& title, Version required_version) const + { + validate_version(title.c_str(), required_version); + } +#endif + + static std::string validate(const std::string& ipstr, const char *title = nullptr, Version required_version = UNSPEC) + { + Addr a = from_string(ipstr, title, required_version); + return a.to_string(); + } + +#ifndef SWIGPYTHON + static std::string validate(const std::string& ipstr, const std::string& title, Version required_version = UNSPEC) + { + return validate(ipstr, title.c_str(), required_version); + } +#endif + + static bool is_valid(const std::string& ipstr) + { + // fast path -- rule out validity if invalid chars + for (size_t i = 0; i < ipstr.length(); ++i) + { + const char c = ipstr[i]; + if (!((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F') + || (c == '.' || c == ':' || c == '%'))) + return false; + } + + // slow path + { + openvpn_io::error_code ec; + openvpn_io::ip::make_address(ipstr, ec); + return !ec; + } + } + + static Addr from_string(const std::string& ipstr, const char *title = nullptr, Version required_version = UNSPEC) + { + openvpn_io::error_code ec; + openvpn_io::ip::address a = openvpn_io::ip::make_address(ipstr, ec); + if (ec) + throw ip_exception(internal::format_error(ipstr, title, "", ec)); + const Addr ret = from_asio(a); + if (required_version != UNSPEC && required_version != ret.ver) + throw ip_exception(internal::format_error(ipstr, title, version_string_static(required_version), "wrong IP version")); + return ret; + } + + static Addr from_hex(Version v, const std::string& s) + { + if (v == V4) + return from_ipv4(IPv4::Addr::from_hex(s)); + else if (v == V6) + return from_ipv6(IPv6::Addr::from_hex(s)); + else + throw ip_exception("address unspecified"); + } + + static Addr from_ipv4(IPv4::Addr addr) + { + Addr a; + a.ver = V4; + a.u.v4 = std::move(addr); + return a; + } + + static Addr from_ipv6(IPv6::Addr addr) + { + Addr a; + a.ver = V6; + a.u.v6 = std::move(addr); + return a; + } + + const IPv4::Addr& to_ipv4() const + { + if (ver == V4) + return u.v4; + else + throw ip_exception("address is not IPv4"); + } + + const IPv6::Addr& to_ipv6() const + { + if (ver == V6) + return u.v6; + else + throw ip_exception("address is not IPv6"); + } + + const IPv4::Addr& to_ipv4_nocheck() const + { + return u.v4; + } + + const IPv6::Addr& to_ipv6_nocheck() const + { + return u.v6; + } + + static Addr from_sockaddr(const struct sockaddr *sa) + { + if (sa->sa_family == AF_INET) + return from_ipv4(IPv4::Addr::from_sockaddr((struct sockaddr_in *)sa)); + else if (sa->sa_family == AF_INET6) + return from_ipv6(IPv6::Addr::from_sockaddr((struct sockaddr_in6 *)sa)); + else + return Addr(); + } + + static bool sockaddr_defined(const struct sockaddr *sa) + { + return sa && (sa->sa_family == AF_INET || sa->sa_family == AF_INET6); + } + + static Addr from_ulong(Version v, unsigned long ul) + { + if (v == V4) + return from_ipv4(IPv4::Addr::from_ulong(ul)); + else if (v == V6) + return from_ipv6(IPv6::Addr::from_ulong(ul)); + else + throw ip_exception("address unspecified"); + } + + // return *this as a ulong, will raise exception on overflow + unsigned long to_ulong() const + { + if (ver == V4) + return u.v4.to_ulong(); + else if (ver == V6) + return u.v6.to_ulong(); + else + throw ip_exception("address unspecified"); + } + + static Addr from_long(Version v, long ul) + { + if (v == V4) + return from_ipv4(IPv4::Addr::from_long(ul)); + else if (v == V6) + return from_ipv6(IPv6::Addr::from_long(ul)); + else + throw ip_exception("address unspecified"); + } + + // return *this as a long, will raise exception on overflow + long to_long() const + { + if (ver == V4) + return u.v4.to_long(); + else if (ver == V6) + return u.v6.to_long(); + else + throw ip_exception("address unspecified"); + } + + // return Addr from 16 byte binary string + static Addr from_byte_string(const unsigned char *bytestr) + { + Addr a; + if (IPv6::Addr::byte_string_is_v4(bytestr)) + { + a.ver = V4; + a.u.v4 = IPv4::Addr::from_uint32_net(IPv6::Addr::v4_from_byte_string(bytestr)); + } + else + { + a.ver = V6; + a.u.v6 = IPv6::Addr::from_byte_string(bytestr); + } + return a; + } + + // convert Addr to 16 byte binary string + void to_byte_string(unsigned char *bytestr) const + { + if (ver == V4) + IPv6::Addr::v4_to_byte_string(bytestr, u.v4.to_uint32_net()); + else if (ver == V6) + u.v6.to_byte_string(bytestr); + else + std::memset(bytestr, 0, 16); + } + + // convert Addr to variable length byte string + void to_byte_string_variable(unsigned char *bytestr) const + { + if (ver == V4) + u.v4.to_byte_string(bytestr); + else if (ver == V6) + u.v6.to_byte_string(bytestr); + else + throw ip_exception("address unspecified"); + } + + std::uint32_t to_uint32_net() const // return value in net byte order + { + if (ver == V4) + return u.v4.to_uint32_net(); + else + return 0; + } + + // construct an address where all bits are zero + static Addr from_zero(Version v) + { + if (v == V4) + return from_ipv4(IPv4::Addr::from_zero()); + else if (v == V6) + return from_ipv6(IPv6::Addr::from_zero()); + else + throw ip_exception("address unspecified"); + } + + // construct an address where all bits are zero + static Addr from_one(Version v) + { + if (v == V4) + return from_ipv4(IPv4::Addr::from_one()); + else if (v == V6) + return from_ipv6(IPv6::Addr::from_one()); + else + throw ip_exception("address unspecified"); + } + + // construct an address where all bits are one + static Addr from_zero_complement(Version v) + { + if (v == V4) + return from_ipv4(IPv4::Addr::from_zero_complement()); + else if (v == V6) + return from_ipv6(IPv6::Addr::from_zero_complement()); + else + throw ip_exception("address unspecified"); + } + + // validate the prefix length for the IP version + static bool validate_prefix_len(Version v, const unsigned int prefix_len) + { + if (v == V4) + { + if (prefix_len <= V4_SIZE) + return true; + } + else if (v == V6) + { + if (prefix_len <= V6_SIZE) + return true; + } + return false; + } + + // build a netmask using given prefix_len + static Addr netmask_from_prefix_len(Version v, const unsigned int prefix_len) + { + if (v == V4) + return from_ipv4(IPv4::Addr::netmask_from_prefix_len(prefix_len)); + else if (v == V6) + return from_ipv6(IPv6::Addr::netmask_from_prefix_len(prefix_len)); + else + throw ip_exception("address unspecified"); + } + + // build a netmask using *this as extent + Addr netmask_from_extent() const + { + if (ver == V4) + return from_ipv4(u.v4.netmask_from_extent()); + else if (ver == V6) + return from_ipv6(u.v6.netmask_from_extent()); + else + throw ip_exception("address unspecified"); + } + + std::string to_string() const + { + if (ver != UNSPEC) + { + const openvpn_io::ip::address a = to_asio(); + std::string ret = a.to_string(); + return ret; + } + else + return "UNSPEC"; + } + + std::string to_string_bracket_ipv6() const + { + std::string ret; + if (ver == V6) + ret += '['; + ret += to_string(); + if (ver == V6) + ret += ']'; + return ret; + } + + std::string to_hex() const + { + if (ver == V4) + return u.v4.to_hex(); + else if (ver == V6) + return u.v6.to_hex(); + else + throw ip_exception("address unspecified"); + } + + std::string arpa() const + { + if (ver == V4) + return u.v4.arpa(); + else if (ver == V6) + return u.v6.arpa(); + else + throw ip_exception("address unspecified"); + } + + static Addr from_asio(const openvpn_io::ip::address& addr) + { + if (addr.is_v4()) + { + Addr a; + a.ver = V4; + a.u.v4 = IPv4::Addr::from_asio(addr.to_v4()); + return a; + } + else if (addr.is_v6()) + { + Addr a; + a.ver = V6; + a.u.v6 = IPv6::Addr::from_asio(addr.to_v6()); + return a; + } + else + throw ip_exception("address unspecified"); + } + + openvpn_io::ip::address to_asio() const + { + switch (ver) + { + case V4: + return openvpn_io::ip::address_v4(u.v4.to_asio()); + case V6: + return openvpn_io::ip::address_v6(u.v6.to_asio()); + default: + throw ip_exception("address unspecified"); + } + } + + Addr operator+(const long delta) const { + switch (ver) + { + case V4: + { + Addr ret; + ret.ver = V4; + ret.u.v4 = u.v4 + delta; + return ret; + } + case V6: + { + Addr ret; + ret.ver = V6; + ret.u.v6 = u.v6 + delta; + return ret; + } + default: + throw ip_exception("address unspecified"); + } + } + + Addr operator-(const long delta) const { + return operator+(-delta); + } + +#define OPENVPN_IP_OPERATOR_BINOP(OP) \ + Addr operator OP (const Addr& other) const { \ + if (ver != other.ver) \ + throw ip_exception("version inconsistency"); \ + switch (ver) \ + { \ + case V4: \ + { \ + Addr ret; \ + ret.ver = V4; \ + ret.u.v4 = u.v4 OP other.u.v4; \ + return ret; \ + } \ + case V6: \ + { \ + Addr ret; \ + ret.ver = V6; \ + ret.u.v6 = u.v6 OP other.u.v6; \ + return ret; \ + } \ + default: \ + throw ip_exception("address unspecified"); \ + } \ + } + + OPENVPN_IP_OPERATOR_BINOP(+) + OPENVPN_IP_OPERATOR_BINOP(-) + OPENVPN_IP_OPERATOR_BINOP(*) + OPENVPN_IP_OPERATOR_BINOP(/) + OPENVPN_IP_OPERATOR_BINOP(%) + OPENVPN_IP_OPERATOR_BINOP(&) + OPENVPN_IP_OPERATOR_BINOP(|) + +#undef OPENVPN_IP_OPERATOR_BINOP + + Addr operator<<(const unsigned int shift) const { + switch (ver) + { + case V4: + { + Addr ret; + ret.ver = V4; + ret.u.v4 = u.v4 << shift; + return ret; + } + case V6: + { + Addr ret; + ret.ver = V6; + ret.u.v6 = u.v6 << shift; + return ret; + } + default: + throw ip_exception("address unspecified"); + } + } + + Addr operator>>(const unsigned int shift) const { + switch (ver) + { + case V4: + { + Addr ret; + ret.ver = V4; + ret.u.v4 = u.v4 >> shift; + return ret; + } + case V6: + { + Addr ret; + ret.ver = V6; + ret.u.v6 = u.v6 >> shift; + return ret; + } + default: + throw ip_exception("address unspecified"); + } + } + + Addr operator~() const { + switch (ver) + { + case V4: + { + Addr ret; + ret.ver = V4; + ret.u.v4 = ~u.v4; + return ret; + } + case V6: + { + Addr ret; + ret.ver = V6; + ret.u.v6 = ~u.v6; + return ret; + } + default: + throw ip_exception("address unspecified"); + } + } + + Addr network_addr(const unsigned int prefix_len) const { + switch (ver) + { + case V4: + { + Addr ret; + ret.ver = V4; + ret.u.v4 = u.v4.network_addr(prefix_len); + return ret; + } + case V6: + { + Addr ret; + ret.ver = V6; + ret.u.v6 = u.v6.network_addr(prefix_len); + return ret; + } + default: + throw ip_exception("address unspecified"); + } + } + + bool operator==(const Addr& other) const + { + switch (ver) + { + case UNSPEC: + return other.ver == UNSPEC; + case V4: + if (ver == other.ver) + return u.v4 == other.u.v4; + break; + case V6: + if (ver == other.ver) + return u.v6 == other.u.v6; + break; + } + return false; + } + + bool operator!=(const Addr& other) const + { + return !operator==(other); + } + +#define OPENVPN_IP_OPERATOR_REL(OP) \ + bool operator OP(const Addr& other) const \ + { \ + if (ver == other.ver) \ + { \ + switch (ver) \ + { \ + case V4: \ + return u.v4 OP other.u.v4; \ + case V6: \ + return u.v6 OP other.u.v6; \ + default: \ + return false; \ + } \ + } \ + else if (ver OP other.ver) \ + return true; \ + else \ + return false; \ + } + + OPENVPN_IP_OPERATOR_REL(<) + OPENVPN_IP_OPERATOR_REL(>) + OPENVPN_IP_OPERATOR_REL(<=) + OPENVPN_IP_OPERATOR_REL(>=) + +#undef OPENVPN_IP_OPERATOR_REL + + bool unspecified() const + { + return all_zeros(); + } + + bool specified() const + { + return !unspecified(); + } + + bool all_zeros() const + { + switch (ver) + { + case V4: + return u.v4.all_zeros(); + case V6: + return u.v6.all_zeros(); + default: + return true; + } + } + + bool all_ones() const + { + switch (ver) + { + case V4: + return u.v4.all_ones(); + case V6: + return u.v6.all_ones(); + default: + return false; + } + } + + bool is_loopback() const + { + switch (ver) + { + case V4: + return u.v4.is_loopback(); + case V6: + return u.v6.is_loopback(); + default: + return false; + } + } + + bool defined() const + { + return ver != UNSPEC; + } + + const char *version_string() const + { + return version_string_static(ver); + } + + static const char *version_string_static(Version ver) + { + switch (ver) + { + case V4: + return "v4"; + case V6: + return "v6"; + default: + return "v?"; + } + } + + Version version() const { return ver; } + + static VersionMask version_mask(const Version ver) + { + switch (ver) + { + case V4: + return V4_MASK; + case V6: + return V6_MASK; + default: + return 0; + } + } + + VersionMask version_mask() const + { + return version_mask(ver); + } + + int version_index() const + { + switch (ver) + { + case V4: + return 0; + case V6: + return 1; + default: + throw ip_exception("version index undefined"); + } + } + + int family() const + { + switch (ver) + { + case V4: + return AF_INET; + case V6: + return AF_INET6; + default: + return -1; + } + } + + bool is_compatible(const Addr& other) const + { + return ver == other.ver; + } + + bool is_ipv6() const + { + return ver == V6; + } + + void verify_version_consistency(const Addr& other) const + { + if (!is_compatible(other)) + throw ip_exception("version inconsistency"); + } + + // throw exception if address is not a valid netmask + void validate_netmask() + { + prefix_len(); + } + + // number of network bits in netmask, + // throws exception if addr is not a netmask + unsigned int prefix_len() const + { + switch (ver) + { + case V4: + return u.v4.prefix_len(); + case V6: + return u.v6.prefix_len(); + default: + throw ip_exception("address unspecified"); + } + } + + // IPv6 scope ID or -1 if not IPv6 + int scope_id() const + { + return ver == V6 ? u.v6.scope_id() : -1; + } + + // number of host bits in netmask + unsigned int host_len() const + { + switch (ver) + { + case V4: + return u.v4.host_len(); + case V6: + return u.v6.host_len(); + default: + throw ip_exception("address unspecified"); + } + } + + // return the number of host addresses contained within netmask + Addr extent_from_netmask() const + { + switch (ver) + { + case V4: + return from_ipv4(u.v4.extent_from_netmask()); + case V6: + return from_ipv6(u.v6.extent_from_netmask()); + default: + throw ip_exception("address unspecified"); + } + } + + // address size in bits + unsigned int size() const + { + return version_size(ver); + } + + // address size in bytes + unsigned int size_bytes() const + { + return size() / 8; + } + + // address size in bits of particular IP version + static unsigned int version_size(Version v) + { + if (v == V4) + return IPv4::Addr::SIZE; + else if (v == V6) + return IPv6::Addr::SIZE; + else + return 0; + } + + template + void hash(HASH& h) const + { + switch (ver) + { + case Addr::V4: + u.v4.hash(h); + break; + case Addr::V6: + u.v6.hash(h); + break; + default: + break; + } + } + +#ifdef HAVE_CITYHASH + std::size_t hashval() const + { + HashSizeT h; + hash(h); + return h.value(); + } +#endif + +#ifdef OPENVPN_IP_IMMUTABLE + private: +#endif + + Addr() + : ver(UNSPEC) + { + } + + void reset() + { + ver = UNSPEC; + } + + Addr& operator=(const Addr& other) + { + switch (ver = other.ver) + { + case V4: + u.v4 = other.u.v4; + break; + case V6: + u.v6 = other.u.v6; + break; + default: + break; + } + return *this; + } + + Addr& operator++() + { + switch (ver) + { + case V4: + ++u.v4; + break; + case V6: + ++u.v6; + break; + default: + break; + } + return *this; + } + + Addr& operator+=(const long delta) + { + switch (ver) + { + case V4: + u.v4 += delta; + break; + case V6: + u.v6 += delta; + break; + default: + break; + } + return *this; + } + + Addr& operator-=(const long delta) + { + switch (ver) + { + case V4: + u.v4 -= delta; + break; + case V6: + u.v6 -= delta; + break; + default: + break; + } + return *this; + } + + void reset_ipv4_from_uint32(const IPv4::Addr::base_type addr) + { + ver = V4; + u.v4 = IPv4::Addr::from_uint32(addr); + } + + private: + union { + IPv4::Addr v4; + IPv6::Addr v6; + } u; + + Version ver; + }; + + OPENVPN_OSTREAM(Addr, to_string) + } +} + +#ifdef HAVE_CITYHASH +OPENVPN_HASH_METHOD(openvpn::IP::Addr, hashval); +#endif + +#endif diff --git a/openvpn/addr/iperr.hpp b/openvpn/addr/iperr.hpp new file mode 100644 index 0000000..fa9af11 --- /dev/null +++ b/openvpn/addr/iperr.hpp @@ -0,0 +1,75 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_IPERR_H +#define OPENVPN_ADDR_IPERR_H + +#include + +#include + +namespace openvpn { + namespace IP { + namespace internal { + // Called internally by IP, IPv4, and IPv6 classes + + inline std::string format_error(const std::string& ipstr, const char *title, const char *ipver, const openvpn_io::error_code& ec) + { + std::string err = "error parsing"; + if (title) + { + err += ' '; + err += title; + } + err += " IP"; + err += ipver; + err += " address '"; + err += ipstr; + err += "' : "; + err += ec.message(); + return err; + } + + inline std::string format_error(const std::string& ipstr, const char *title, const char *ipver, const char *message) + { + std::string err = "error parsing"; + if (title) + { + err += ' '; + err += title; + } + err += " IP"; + err += ipver; + err += " address '"; + err += ipstr; + err += '\''; + if (message) + { + err += " : "; + err += message; + } + return err; + } + } + } +} + +#endif diff --git a/openvpn/addr/ipv4.hpp b/openvpn/addr/ipv4.hpp new file mode 100644 index 0000000..1fd55de --- /dev/null +++ b/openvpn/addr/ipv4.hpp @@ -0,0 +1,588 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_IPV4_H +#define OPENVPN_ADDR_IPV4_H + +#include // for std::memcpy, std::memset +#include +#include // for std::uint32_t + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + namespace IP { + class Addr; + } + + // Fundamental classes for representing an IPv4 IP address. + + namespace IPv4 { + + OPENVPN_EXCEPTION(ipv4_exception); + + class Addr // NOTE: must be union-legal, so default constructor does not initialize + { + friend class IP::Addr; + + public: + enum { SIZE=32 }; + + typedef std::uint32_t base_type; + typedef std::int32_t signed_base_type; + + bool defined() const + { + return true; + } + + static Addr from_addr(const Addr& addr) + { + return addr; + } + + static Addr from_in_addr(const struct in_addr *in4) + { + Addr ret; + ret.u.addr = ntohl(in4->s_addr); + return ret; + } + + struct in_addr to_in_addr() const + { + struct in_addr ret; + ret.s_addr = htonl(u.addr); + return ret; + } + + static Addr from_sockaddr(const struct sockaddr_in *sa) + { + Addr ret; + ret.u.addr = ntohl(sa->sin_addr.s_addr); + return ret; + } + + struct sockaddr_in to_sockaddr(const unsigned short port=0) const + { + struct sockaddr_in ret; + std::memset(&ret, 0, sizeof(ret)); + ret.sin_family = AF_INET; + ret.sin_port = htons(port); + ret.sin_addr.s_addr = htonl(u.addr); + return ret; + } + + static Addr from_uint32(const base_type addr) // host byte order + { + Addr ret; + ret.u.addr = addr; + return ret; + } + + std::uint32_t to_uint32() const // host byte order + { + return u.addr; + } + + static Addr from_uint32_net(const base_type addr) // addr in net byte order + { + Addr ret; + ret.u.addr = ntohl(addr); + return ret; + } + + void to_byte_string(unsigned char *bytestr) const + { + *(base_type*)bytestr = ntohl(u.addr); + } + + std::uint32_t to_uint32_net() const // return value in net byte order + { + return htonl(u.addr); + } + + static Addr from_ulong(unsigned long ul) + { + Addr ret; + ret.u.addr = (base_type)ul; + return ret; + } + + // return *this as a unsigned long + unsigned long to_ulong() const + { + return (unsigned long)u.addr; + } + + static Addr from_long(long ul) + { + Addr ret; + ret.u.addr = (base_type)(signed_base_type)ul; + return ret; + } + + // return *this as a long + long to_long() const + { + return (long)(signed_base_type)u.addr; + } + + static Addr from_bytes(const unsigned char *bytes) // host byte order + { + Addr ret; + std::memcpy(ret.u.bytes, bytes, 4); + return ret; + } + + static Addr from_bytes_net(const unsigned char *bytes) // network byte order + { + Addr ret; + std::memcpy(ret.u.bytes, bytes, 4); + ret.u.addr = ntohl(ret.u.addr); + return ret; + } + + static Addr from_zero() + { + Addr ret; + ret.zero(); + return ret; + } + + static Addr from_one() + { + Addr ret; + ret.one(); + return ret; + } + + static Addr from_zero_complement() + { + Addr ret; + ret.zero_complement(); + return ret; + } + + // build a netmask using given prefix_len + static Addr netmask_from_prefix_len(const unsigned int prefix_len) + { + Addr ret; + ret.u.addr = prefix_len_to_netmask(prefix_len); + return ret; + } + + // build a netmask using given extent + Addr netmask_from_extent() const + { + const int lb = find_last_set(u.addr - 1); + return netmask_from_prefix_len(SIZE - lb); + } + + static Addr from_string(const std::string& ipstr, const char *title = nullptr) + { + openvpn_io::error_code ec; + openvpn_io::ip::address_v4 a = openvpn_io::ip::make_address_v4(ipstr, ec); + if (ec) + throw ipv4_exception(IP::internal::format_error(ipstr, title, "v4", ec)); + return from_asio(a); + } + + std::string to_string() const + { + const openvpn_io::ip::address_v4 a = to_asio(); + std::string ret = a.to_string(); + return ret; + } + + static Addr from_hex(const std::string& s) + { + Addr ret; + ret.u.addr = 0; + size_t len = s.length(); + size_t base = 0; + if (len > 0 && s[len-1] == 'L') + len -= 1; + if (len >= 2 && s[0] == '0' && s[1] == 'x') + { + base = 2; + len -= 2; + } + if (len < 1 || len > 8) + throw ipv4_exception("parse hex error"); + size_t di = (len-1)>>1; + for (int i = (len & 1) ? -1 : 0; i < int(len); i += 2) + { + const size_t idx = base + i; + const int bh = (i >= 0) ? parse_hex_char(s[idx]) : 0; + const int bl = parse_hex_char(s[idx+1]); + if (bh == -1 || bl == -1) + throw ipv4_exception("parse hex error"); + ret.u.bytes[Endian::e4(di--)] = (bh<<4) + bl; + } + return ret; + } + + std::string to_hex() const + { + std::string ret; + ret.reserve(8); + bool firstnonzero = false; + for (size_t i = 0; i < 4; ++i) + { + const unsigned char b = u.bytes[Endian::e4rev(i)]; + if (b || firstnonzero || i == 3) + { + const char bh = b >> 4; + if (bh || firstnonzero) + ret += render_hex_char(bh); + ret += render_hex_char(b & 0x0F); + firstnonzero = true; + } + } + return ret; + } + + std::string arpa() const + { + std::ostringstream os; + os << int(u.bytes[Endian::e4(0)]) << '.' + << int(u.bytes[Endian::e4(1)]) << '.' + << int(u.bytes[Endian::e4(2)]) << '.' + << int(u.bytes[Endian::e4(3)]) << ".in-addr.arpa"; + return os.str(); + } + + static Addr from_asio(const openvpn_io::ip::address_v4& asio_addr) + { + Addr ret; + ret.u.addr = (std::uint32_t)asio_addr.to_uint(); + return ret; + } + + openvpn_io::ip::address_v4 to_asio() const + { + return openvpn_io::ip::address_v4(u.addr); + } + + Addr operator&(const Addr& other) const { + Addr ret; + ret.u.addr = u.addr & other.u.addr; + return ret; + } + + Addr operator|(const Addr& other) const { + Addr ret; + ret.u.addr = u.addr | other.u.addr; + return ret; + } + + Addr operator+(const long delta) const { + Addr ret; + ret.u.addr = u.addr + (std::uint32_t)delta; + return ret; + } + + Addr operator+(const Addr& other) const { + Addr ret; + ret.u.addr = u.addr + other.u.addr; + return ret; + } + + Addr operator-(const long delta) const { + return operator+(-delta); + } + + Addr operator-(const Addr& other) const { + Addr ret; + ret.u.addr = u.addr - other.u.addr; + return ret; + } + + Addr operator*(const Addr& other) const { + Addr ret; + ret.u.addr = u.addr * other.u.addr; + return ret; + } + + Addr operator/(const Addr& other) const { + Addr ret; + ret.u.addr = u.addr / other.u.addr; + return ret; + } + + Addr operator%(const Addr& other) const { + Addr ret; + ret.u.addr = u.addr % other.u.addr; + return ret; + } + + Addr operator<<(const unsigned int shift) const { + Addr ret; + ret.u.addr = u.addr << shift; + return ret; + } + + Addr operator>>(const unsigned int shift) const { + Addr ret; + ret.u.addr = u.addr >> shift; + return ret; + } + + Addr operator~() const { + Addr ret; + ret.u.addr = ~u.addr; + return ret; + } + + // return the network that contains the current address + Addr network_addr(const unsigned int prefix_len) const + { + Addr ret; + ret.u.addr = u.addr & prefix_len_to_netmask(prefix_len); + return ret; + } + + bool operator==(const Addr& other) const + { + return u.addr == other.u.addr; + } + + bool operator!=(const Addr& other) const + { + return u.addr != other.u.addr; + } + + bool operator<(const Addr& other) const + { + return u.addr < other.u.addr; + } + + bool operator>(const Addr& other) const + { + return u.addr > other.u.addr; + } + + bool operator<=(const Addr& other) const + { + return u.addr <= other.u.addr; + } + + bool operator>=(const Addr& other) const + { + return u.addr >= other.u.addr; + } + + bool unspecified() const + { + return all_zeros(); + } + + bool specified() const + { + return !unspecified(); + } + + bool all_zeros() const + { + return u.addr == 0; + } + + bool all_ones() const + { + return ~u.addr == 0; + } + + bool is_loopback() const + { + return (u.addr & 0x7F000000) == 0x7F000000; + } + + // number of network bits in netmask, + // throws exception if addr is not a netmask + unsigned int prefix_len() const + { + const int ret = prefix_len_32(u.addr); + if (ret >= 0) + return ret; + else + throw ipv4_exception("malformed netmask"); + } + + int prefix_len_nothrow() const + { + return prefix_len_32(u.addr); + } + + // number of host bits in netmask + unsigned int host_len() const + { + return SIZE - prefix_len(); + } + + // return the number of host addresses contained within netmask + Addr extent_from_netmask() const + { + Addr ret; + ret.u.addr = extent_from_netmask_uint32(); + return ret; + } + + std::uint32_t extent_from_netmask_uint32() const + { + const unsigned int hl = host_len(); + if (hl < SIZE) + return 1 << hl; + else if (hl == SIZE) + return 0; + else + throw ipv4_exception("extent overflow"); + } + + // convert netmask in addr to prefix_len, will return -1 on error + static int prefix_len_32(const std::uint32_t addr) + { + if (addr == ~std::uint32_t(0)) + return 32; + else if (addr == 0) + return 0; + else + { + unsigned int high = 32; + unsigned int low = 1; + for (unsigned int i = 0; i < 5; ++i) + { + const unsigned int mid = (high + low) / 2; + const IPv4::Addr::base_type test = prefix_len_to_netmask_unchecked(mid); + if (addr == test) + return mid; + else if (addr > test) + low = mid; + else + high = mid; + } + return -1; + } + } + + // address size in bits + static unsigned int size() + { + return SIZE; + } + + template + void hash(HASH& h) const + { + h(u.addr); + } + +#ifdef HAVE_CITYHASH + std::size_t hashval() const + { + HashSizeT h; + hash(h); + return h.value(); + } +#endif + +#ifdef OPENVPN_IP_IMMUTABLE + private: +#endif + + void negate() + { + u.addr = ~u.addr; + } + + void zero() + { + u.addr = 0; + } + + void zero_complement() + { + u.addr = ~0; + } + + void one() + { + u.addr = 1; + } + + Addr& operator++() + { + ++u.addr; + return *this; + } + + Addr& operator+=(const long delta) + { + u.addr += (std::uint32_t)delta; + return *this; + } + + Addr& operator-=(const long delta) + { + return operator+=(-delta); + } + + private: + static base_type prefix_len_to_netmask_unchecked(const unsigned int prefix_len) + { + if (prefix_len) + return ~((1 << (SIZE - prefix_len)) - 1); + else + return 0; + } + + static base_type prefix_len_to_netmask(const unsigned int prefix_len) + { + if (prefix_len <= SIZE) + return prefix_len_to_netmask_unchecked(prefix_len); + else + throw ipv4_exception("bad prefix len"); + } + + union { + base_type addr; // host byte order + unsigned char bytes[4]; + } u; + }; + + OPENVPN_OSTREAM(Addr, to_string) + } +} + +#ifdef HAVE_CITYHASH +OPENVPN_HASH_METHOD(openvpn::IPv4::Addr, hashval); +#endif + +#endif // OPENVPN_ADDR_IPV4_H diff --git a/openvpn/addr/ipv6.hpp b/openvpn/addr/ipv6.hpp new file mode 100644 index 0000000..d116934 --- /dev/null +++ b/openvpn/addr/ipv6.hpp @@ -0,0 +1,847 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_IPV6_H +#define OPENVPN_ADDR_IPV6_H + +#include // for std::memcpy, std::memset +#include // for std::min +#include // for std::uint32_t + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + namespace IP { + class Addr; + } + + // Fundamental classes for representing an IPv6 IP address. + + namespace IPv6 { + + OPENVPN_EXCEPTION(ipv6_exception); + + class Addr // NOTE: must be union-legal, so default constructor does not initialize + { + friend class IP::Addr; + + public: + enum { SIZE=128 }; + + bool defined() const + { + return true; + } + + static Addr from_addr(const Addr& addr) + { + return addr; + } + + static Addr from_in6_addr(const struct in6_addr *in6) + { + Addr ret; + network_to_host_order(&ret.u, (const union ipv6addr *)in6->s6_addr); + ret.scope_id_ = 0; + return ret; + } + + struct in6_addr to_in6_addr() const + { + struct in6_addr ret; + host_to_network_order((union ipv6addr *)&ret, &u); + return ret; + } + + static Addr from_sockaddr(const struct sockaddr_in6 *sa) + { + Addr ret; + network_to_host_order(&ret.u, (const union ipv6addr *)sa->sin6_addr.s6_addr); + ret.scope_id_ = sa->sin6_scope_id; + return ret; + } + + struct sockaddr_in6 to_sockaddr(const unsigned short port=0) const + { + struct sockaddr_in6 ret; + std::memset(&ret, 0, sizeof(ret)); + ret.sin6_family = AF_INET6; + ret.sin6_port = htons(port); + host_to_network_order((union ipv6addr *)&ret.sin6_addr.s6_addr, &u); + ret.sin6_scope_id = scope_id_; + return ret; + } + + static Addr from_string(const std::string& ipstr, const char *title = nullptr) + { + openvpn_io::error_code ec; + openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec); + if (ec) + throw ipv6_exception(IP::internal::format_error(ipstr, title, "v6", ec)); + return from_asio(a); + } + + std::string to_string() const + { + const openvpn_io::ip::address_v6 a = to_asio(); + std::string ret = a.to_string(); + return ret; + } + + static Addr from_hex(const std::string& s) + { + Addr ret; + ret.scope_id_ = 0; + ret.zero(); + size_t len = s.length(); + size_t base = 0; + if (len > 0 && s[len-1] == 'L') + len -= 1; + if (len >= 2 && s[0] == '0' && s[1] == 'x') + { + base = 2; + len -= 2; + } + if (len < 1 || len > 32) + throw ipv6_exception("parse hex error"); + size_t di = (len-1)>>1; + for (int i = (len & 1) ? -1 : 0; i < int(len); i += 2) + { + const size_t idx = base + i; + const int bh = (i >= 0) ? parse_hex_char(s[idx]) : 0; + const int bl = parse_hex_char(s[idx+1]); + if (bh == -1 || bl == -1) + throw ipv6_exception("parse hex error"); + ret.u.bytes[Endian::e16(di--)] = (bh<<4) + bl; + } + return ret; + } + + std::string to_hex() const + { + std::string ret; + ret.reserve(32); + bool firstnonzero = false; + for (size_t i = 0; i < 16; ++i) + { + const unsigned char b = u.bytes[Endian::e16rev(i)]; + if (b || firstnonzero || i == 15) + { + const char bh = b >> 4; + if (bh || firstnonzero) + ret += render_hex_char(bh); + ret += render_hex_char(b & 0x0F); + firstnonzero = true; + } + } + return ret; + } + + static Addr from_ulong(unsigned long ul) + { + Addr ret; + ret.scope_id_ = 0; + ret.u.u64[Endian::e2(0)] = std::uint64_t(ul); + ret.u.u64[Endian::e2(1)] = 0; + return ret; + } + + // return *this as a unsigned long + unsigned long to_ulong() const + { + const unsigned long ret = (unsigned long)u.u64[Endian::e2(0)]; + const std::uint64_t cmp = std::uint64_t(ret); + if (u.u64[Endian::e2(1)] || cmp != u.u64[Endian::e2(0)]) + throw ipv6_exception("overflow in conversion from IPv6.Addr to unsigned long"); + return ret; + } + + static Addr from_long(long ul) + { + bool neg = false; + Addr ret; + ret.scope_id_ = 0; + if (ul < 0) + { + ul = -(ul + 1); + neg = true; + } + ret.u.u64[Endian::e2(0)] = std::uint64_t(ul); + ret.u.u64[Endian::e2(1)] = 0; + if (neg) + ret.negate(); + return ret; + } + + // return *this as a long + long to_long() const + { + bool neg = false; + Addr a = *this; + if (a.u.u64[Endian::e2(1)]) + { + a.negate(); + neg = true; + } + const long ret = (long)a.u.u64[Endian::e2(0)]; + const std::uint64_t cmp = std::uint64_t(ret); + if (a.u.u64[Endian::e2(1)] || cmp != a.u.u64[Endian::e2(0)]) + throw ipv6_exception("overflow in conversion from IPv6.Addr to long"); + return neg ? -(ret + 1) : ret; + } + + std::string arpa() const + { + throw ipv6_exception("arpa() not implemented"); + } + + static Addr from_asio(const openvpn_io::ip::address_v6& asio_addr) + { + Addr ret; + union ipv6addr addr; + addr.asio_bytes = asio_addr.to_bytes(); + network_to_host_order(&ret.u, &addr); + ret.scope_id_ = (unsigned int)asio_addr.scope_id(); + return ret; + } + + static Addr from_byte_string(const unsigned char *bytestr) + { + Addr ret; + network_to_host_order(&ret.u, (const union ipv6addr *)bytestr); + ret.scope_id_ = 0; + return ret; + } + + void to_byte_string(unsigned char *bytestr) const + { + host_to_network_order((union ipv6addr *)bytestr, &u); + } + + static void v4_to_byte_string(unsigned char *bytestr, + const std::uint32_t v4addr) + { + union ipv6addr *a = (union ipv6addr *)bytestr; + a->u32[0] = a->u32[1] = a->u32[2] = 0; + a->u32[3] = v4addr; + } + + static bool byte_string_is_v4(const unsigned char *bytestr) + { + const union ipv6addr *a = (const union ipv6addr *)bytestr; + return a->u32[0] == 0 && a->u32[1] == 0 && a->u32[2] == 0; + } + + static std::uint32_t v4_from_byte_string(const unsigned char *bytestr) + { + const union ipv6addr *a = (const union ipv6addr *)bytestr; + return a->u32[3]; + } + + openvpn_io::ip::address_v6 to_asio() const + { + union ipv6addr addr; + host_to_network_order(&addr, &u); + return openvpn_io::ip::address_v6(addr.asio_bytes, scope_id_); + } + + static Addr from_zero() + { + Addr ret; + ret.scope_id_ = 0; + ret.zero(); + return ret; + } + + static Addr from_one() + { + Addr ret; + ret.scope_id_ = 0; + ret.one(); + return ret; + } + + static Addr from_zero_complement() + { + Addr ret; + ret.scope_id_ = 0; + ret.zero_complement(); + return ret; + } + + // build a netmask using given prefix_len + static Addr netmask_from_prefix_len(const unsigned int prefix_len) + { + Addr ret; + ret.scope_id_ = 0; + ret.prefix_len_to_netmask(prefix_len); + return ret; + } + + // build a netmask using given extent + Addr netmask_from_extent() const + { + const Addr lb = *this - 1; + for (size_t i = 4; i --> 0 ;) + { + const std::uint32_t v = lb.u.u32[Endian::e4(i)]; + if (v) + return netmask_from_prefix_len(SIZE - (((unsigned int)i<<5) + find_last_set(v))); + } + return from_zero_complement(); + } + + Addr operator&(const Addr& other) const { + Addr ret; + ret.scope_id_ = scope_id_; + ret.u.u64[0] = u.u64[0] & other.u.u64[0]; + ret.u.u64[1] = u.u64[1] & other.u.u64[1]; + return ret; + } + + Addr operator|(const Addr& other) const { + Addr ret; + ret.scope_id_ = scope_id_; + ret.u.u64[0] = u.u64[0] | other.u.u64[0]; + ret.u.u64[1] = u.u64[1] | other.u.u64[1]; + return ret; + } + + Addr operator+(const long delta) const { + Addr ret = *this; + ret.u.u64[Endian::e2(0)] += delta; + ret.u.u64[Endian::e2(1)] += (delta >= 0) + ? (ret.u.u64[Endian::e2(0)] < u.u64[Endian::e2(0)]) + : -(ret.u.u64[Endian::e2(0)] > u.u64[Endian::e2(0)]); + return ret; + } + + Addr operator+(const Addr& other) const { + Addr ret = *this; + add(ret.u, other.u); + return ret; + } + + Addr operator-(const long delta) const { + return operator+(-delta); + } + + Addr operator-(const Addr& other) const { + Addr ret = *this; + sub(ret.u, other.u); + return ret; + } + + Addr operator*(const Addr& d) const { + Addr m = d; + Addr ret = from_zero(); + for (unsigned int i = 0; i < SIZE; ++i) + { + if (bit(i)) + ret += m; + m <<= 1; + } + return ret; + } + + Addr operator/(const Addr& d) const { + Addr q, r; + div(*this, d, q, r); + return q; + } + + Addr operator%(const Addr& d) const { + Addr q, r; + div(*this, d, q, r); + return r; + } + + Addr operator<<(const unsigned int shift) const { + Addr ret = *this; + shiftl128(ret.u.u64[Endian::e2(0)], + ret.u.u64[Endian::e2(1)], + shift); + return ret; + } + + Addr operator>>(const unsigned int shift) const { + Addr ret = *this; + shiftr128(ret.u.u64[Endian::e2(0)], + ret.u.u64[Endian::e2(1)], + shift); + return ret; + } + + Addr operator~() const { + Addr ret; + ret.scope_id_ = scope_id_; + ret.u.u64[0] = ~u.u64[0]; + ret.u.u64[1] = ~u.u64[1]; + return ret; + } + + // return the network that contains the current address + Addr network_addr(const unsigned int prefix_len) const + { + return *this & netmask_from_prefix_len(prefix_len); + } + + bool operator==(const Addr& other) const + { + return u.u64[0] == other.u.u64[0] && u.u64[1] == other.u.u64[1] && scope_id_ == other.scope_id_; + } + + bool operator!=(const Addr& other) const + { + return !operator==(other); + } + +#define OPENVPN_IPV6_OPERATOR_REL(OP) \ + bool operator OP(const Addr& other) const \ + { \ + if (u.u64[Endian::e2(1)] == other.u.u64[Endian::e2(1)]) \ + { \ + if (u.u64[Endian::e2(0)] != other.u.u64[Endian::e2(0)]) \ + return u.u64[Endian::e2(0)] OP other.u.u64[Endian::e2(0)]; \ + else \ + return scope_id_ OP other.scope_id_; \ + } \ + else \ + return u.u64[Endian::e2(1)] OP other.u.u64[Endian::e2(1)]; \ + } + + OPENVPN_IPV6_OPERATOR_REL(<) + OPENVPN_IPV6_OPERATOR_REL(>) + OPENVPN_IPV6_OPERATOR_REL(<=) + OPENVPN_IPV6_OPERATOR_REL(>=) + +#undef OPENVPN_IPV6_OPERATOR_REL + + bool unspecified() const + { + return all_zeros(); + } + + bool specified() const + { + return !unspecified(); + } + + bool all_zeros() const + { + return u.u64[0] == 0 && u.u64[1] == 0; + } + + bool all_ones() const + { + return u.u64[0] == ~std::uint64_t(0) && u.u64[1] == ~std::uint64_t(0); + } + + bool is_loopback() const // ::1 + { + return u.u64[Endian::e2(1)] == 0 && u.u64[Endian::e2(0)] == 1; + } + + bool bit(unsigned int pos) const + { + if (pos < 64) + return (u.u64[Endian::e2(0)] & (std::uint64_t(1)<= 0) + { + const int ret = IPv4::Addr::prefix_len_32(u.u32[Endian::e4rev(idx)]); + if (ret >= 0) + return ret + (idx<<5); + } + throw ipv6_exception("malformed netmask"); + } + + // number of host bits in netmask + unsigned int host_len() const + { + return SIZE - prefix_len(); + } + + // return the number of host addresses contained within netmask + Addr extent_from_netmask() const + { + const unsigned int hl = host_len(); + if (hl < SIZE) + { + Addr a; + a.scope_id_ = 0; + a.one(); + return a << hl; + } + else if (hl == SIZE) + return from_zero(); + else + throw ipv6_exception("extent overflow"); + } + + // address size in bits + static unsigned int size() + { + return SIZE; + } + + template + void hash(HASH& h) const + { + h(u.bytes, sizeof(u.bytes)); + } + +#ifdef HAVE_CITYHASH + std::size_t hashval() const + { + HashSizeT h; + hash(h); + return h.value(); + } +#endif + +#ifdef OPENVPN_IP_IMMUTABLE + private: +#endif + + void negate() + { + u.u64[0] = ~u.u64[0]; + u.u64[1] = ~u.u64[1]; + } + + void zero() + { + u.u64[0] = 0; + u.u64[1] = 0; + } + + void zero_complement() + { + u.u64[0] = ~std::uint64_t(0); + u.u64[1] = ~std::uint64_t(0); + } + + void one() + { + u.u64[0] = 1; + u.u64[1] = 0; + } + + Addr& operator++() + { + if (++u.u64[Endian::e2(0)] == 0) + ++u.u64[Endian::e2(1)]; + return *this; + } + + Addr& operator+=(const long delta) + { + *this = *this + delta; + return *this; + } + + Addr& operator-=(const long delta) + { + return operator+=(-delta); + } + + Addr& operator+=(const Addr& other) { + add(u, other.u); + return *this; + } + + Addr& operator-=(const Addr& other) { + sub(u, other.u); + return *this; + } + + Addr& operator<<=(const unsigned int shift) { + shiftl128(u.u64[Endian::e2(0)], + u.u64[Endian::e2(1)], + shift); + return *this; + } + + Addr& operator>>=(const unsigned int shift) { + shiftr128(u.u64[Endian::e2(0)], + u.u64[Endian::e2(1)], + shift); + return *this; + } + + void set_clear_bit(unsigned int pos, bool value) + { + if (pos < 64) + { + if (value) + u.u64[Endian::e2(0)] |= (std::uint64_t(1)<>= 1; + ml.set_bit(SIZE-1, mh.bit(0)); + mh >>= 1; + if (mh.all_zeros() && r >= ml) + { + r -= ml; + q.set_bit((SIZE-1)-i, true); + } + } + } + + int scope_id() const + { + return scope_id_; + } + + private: + union ipv6addr { + std::uint64_t u64[2]; + std::uint32_t u32[4]; // generally stored in host byte order + unsigned char bytes[16]; + openvpn_io::ip::address_v6::bytes_type asio_bytes; + }; + + void prefix_len_to_netmask_unchecked(const unsigned int prefix_len) + { + if (prefix_len > 0) + { + const unsigned int pl = prefix_len - 1; + const std::uint32_t mask = ~((1 << (31 - (pl & 31))) - 1); + switch (pl >> 5) + { + case 0: + u.u32[Endian::e4(0)] = 0; + u.u32[Endian::e4(1)] = 0; + u.u32[Endian::e4(2)] = 0; + u.u32[Endian::e4(3)] = mask; + break; + case 1: + u.u32[Endian::e4(0)] = 0; + u.u32[Endian::e4(1)] = 0; + u.u32[Endian::e4(2)] = mask; + u.u32[Endian::e4(3)] = ~0; + break; + case 2: + u.u32[Endian::e4(0)] = 0; + u.u32[Endian::e4(1)] = mask; + u.u32[Endian::e4(2)] = ~0; + u.u32[Endian::e4(3)] = ~0; + break; + case 3: + u.u32[Endian::e4(0)] = mask; + u.u32[Endian::e4(1)] = ~0; + u.u32[Endian::e4(2)] = ~0; + u.u32[Endian::e4(3)] = ~0; + break; + } + } + else + zero(); + } + + void prefix_len_to_netmask(const unsigned int prefix_len) + { + if (prefix_len <= SIZE) + return prefix_len_to_netmask_unchecked(prefix_len); + else + throw ipv6_exception("bad prefix len"); + } + + static void host_to_network_order(union ipv6addr *dest, const union ipv6addr *src) + { + dest->u32[0] = htonl(src->u32[Endian::e4rev(0)]); + dest->u32[1] = htonl(src->u32[Endian::e4rev(1)]); + dest->u32[2] = htonl(src->u32[Endian::e4rev(2)]); + dest->u32[3] = htonl(src->u32[Endian::e4rev(3)]); + } + + static void network_to_host_order(union ipv6addr *dest, const union ipv6addr *src) + { + dest->u32[0] = ntohl(src->u32[Endian::e4rev(0)]); + dest->u32[1] = ntohl(src->u32[Endian::e4rev(1)]); + dest->u32[2] = ntohl(src->u32[Endian::e4rev(2)]); + dest->u32[3] = ntohl(src->u32[Endian::e4rev(3)]); + } + + static void shiftl128(std::uint64_t& low, + std::uint64_t& high, + unsigned int shift) + { + if (shift == 1) + { + high <<= 1; + if (low & (std::uint64_t(1) << 63)) + high |= 1; + low <<= 1; + } + else if (shift == 0) + ; + else if (shift <= 128) + { + if (shift >= 64) + { + high = low; + low = 0; + shift -= 64; + } + if (shift < 64) + { + high = (high << shift) | (low >> (64-shift)); + low <<= shift; + } + else // shift == 64 + high = 0; + } + else + throw ipv6_exception("l-shift too large"); + } + + static void shiftr128(std::uint64_t& low, + std::uint64_t& high, + unsigned int shift) + { + if (shift == 1) + { + low >>= 1; + if (high & 1) + low |= (std::uint64_t(1) << 63); + high >>= 1; + } + else if (shift == 0) + ; + else if (shift <= 128) + { + if (shift >= 64) + { + low = high; + high = 0; + shift -= 64; + } + if (shift < 64) + { + low = (low >> shift) | (high << (64-shift)); + high >>= shift; + } + else // shift == 64 + low = 0; + } + else + throw ipv6_exception("r-shift too large"); + } + + static void add(ipv6addr& dest, const ipv6addr& src) { + const std::uint64_t dorigl = dest.u64[Endian::e2(0)]; + dest.u64[Endian::e2(0)] += src.u64[Endian::e2(0)]; + dest.u64[Endian::e2(1)] += src.u64[Endian::e2(1)]; + // check for overflow of low 64 bits, add carry to high + if (dest.u64[Endian::e2(0)] < dorigl) + ++dest.u64[Endian::e2(1)]; + } + + static void sub(ipv6addr& dest, const ipv6addr& src) { + const std::uint64_t dorigl = dest.u64[Endian::e2(0)]; + dest.u64[Endian::e2(0)] -= src.u64[Endian::e2(0)]; + dest.u64[Endian::e2(1)] -= src.u64[Endian::e2(1)] + + (dorigl < dest.u64[Endian::e2(0)]); + } + + union ipv6addr u; + unsigned int scope_id_; + }; + + OPENVPN_OSTREAM(Addr, to_string) + } +} + +#ifdef HAVE_CITYHASH +OPENVPN_HASH_METHOD(openvpn::IPv6::Addr, hashval); +#endif + +#endif // OPENVPN_ADDR_IPV6_H diff --git a/openvpn/addr/macaddr.hpp b/openvpn/addr/macaddr.hpp new file mode 100644 index 0000000..d2e9b69 --- /dev/null +++ b/openvpn/addr/macaddr.hpp @@ -0,0 +1,67 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_MACADDR_H +#define OPENVPN_ADDR_MACADDR_H + +#include +#include +#include + +#include +#include +#include + +namespace openvpn { + + // Fundamental class for representing an ethernet MAC address. + + class MACAddr { + public: + MACAddr() + { + std::memset(addr_, 0, sizeof(addr_)); + } + + MACAddr(const unsigned char *addr) + { + reset(addr); + } + + void reset(const unsigned char *addr) + { + std::memcpy(addr_, addr, sizeof(addr_)); + } + + std::string to_string() const + { + return render_hex_sep(addr_, sizeof(addr_), ':'); + } + + private: + unsigned char addr_[6]; + }; + + OPENVPN_OSTREAM(MACAddr, to_string) + +} // namespace openvpn + +#endif // OPENVPN_ADDR_MACADDR_H diff --git a/openvpn/addr/pool.hpp b/openvpn/addr/pool.hpp new file mode 100644 index 0000000..b176f5d --- /dev/null +++ b/openvpn/addr/pool.hpp @@ -0,0 +1,164 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_POOL_H +#define OPENVPN_ADDR_POOL_H + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace openvpn { + namespace IP { + + // Maintain a pool of IP addresses. + // A should be IP::Addr, IPv4::Addr, or IPv6::Addr. + template + class PoolType + { + public: + PoolType() {} + + // Add range of addresses to pool (pool will own the addresses). + void add_range(const RangeType& range) + { + auto iter = range.iterator(); + while (iter.more()) + { + const ADDR& a = iter.addr(); + add_addr(a); + iter.next(); + } + } + + // Add single address to pool (pool will own the address). + void add_addr(const ADDR& addr) + { + auto e = map.find(addr); + if (e == map.end()) + { + freelist.push_back(addr); + map[addr] = false; + } + } + + // Return number of pool addresses currently in use. + size_t n_in_use() const + { + return map.size() - freelist.size(); + } + + // Return number of pool addresses currently in use. + size_t n_free() const + { + return freelist.size(); + } + + // Acquire an address from pool. Returns true if successful, + // with address placed in dest, or false if pool depleted. + bool acquire_addr(ADDR& dest) + { + while (true) + { + freelist_fill(); + if (freelist.empty()) + return false; + const ADDR& a = freelist.front(); + auto e = map.find(a); + if (e == map.end()) // any address in freelist must exist in map + throw Exception("PoolType: address in freelist doesn't exist in map"); + if (!e->second) + { + e->second = true; + dest = a; + freelist.pop_front(); + return true; + } + freelist.pop_front(); + } + } + + // Acquire a specific address from pool, returning true if + // successful, or false if the address is not available. + bool acquire_specific_addr(const ADDR& addr) + { + auto e = map.find(addr); + if (e != map.end() && !e->second) + { + e->second = true; + return true; + } + else + return false; + } + + // Return a previously acquired address to the pool. Does nothing if + // (a) the address is owned by the pool and marked as free, or + // (b) the address is not owned by the pool. + void release_addr(const ADDR& addr) + { + auto e = map.find(addr); + if (e != map.end() && e->second) + { + freelist.push_back(addr); + e->second = false; + } + } + + // DEBUGGING -- get the map load factor + float load_factor() const { return map.load_factor(); } + + // Override to refill freelist on demand + virtual void freelist_fill() + { + } + + std::string to_string() const + { + std::string ret; + for (const auto& e : map) + { + if (e.second) + { + ret += e.first.to_string(); + ret += '\n'; + } + } + return ret; + } + + private: + std::deque freelist; + std::unordered_map map; + }; + + typedef PoolType Pool; + } +} + +#endif diff --git a/openvpn/addr/quoteip.hpp b/openvpn/addr/quoteip.hpp new file mode 100644 index 0000000..cab2b8b --- /dev/null +++ b/openvpn/addr/quoteip.hpp @@ -0,0 +1,36 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include + +namespace openvpn { + + // return ip_addr in brackets if it is IPv6 + std::string quote_ip(const std::string& ip_addr) + { + if (ip_addr.find(':') != std::string::npos) + return '[' + ip_addr + ']'; + else + return ip_addr; + } +} diff --git a/openvpn/addr/randaddr.hpp b/openvpn/addr/randaddr.hpp new file mode 100644 index 0000000..e8cdac5 --- /dev/null +++ b/openvpn/addr/randaddr.hpp @@ -0,0 +1,68 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include +#include +#include + +namespace openvpn { + namespace IP { + + inline IPv4::Addr random_addr_v4(RandomAPI& prng) + { + return IPv4::Addr::from_uint32(prng.rand_get()); + } + + inline IPv6::Addr random_addr_v6(RandomAPI& prng) + { + unsigned char bytes[16]; + prng.rand_fill(bytes); + return IPv6::Addr::from_byte_string(bytes); + } + + inline Addr random_addr(const Addr::Version v, RandomAPI& prng) + { + switch (v) + { + case Addr::V4: + return Addr::from_ipv4(random_addr_v4(prng)); + case Addr::V6: + return Addr::from_ipv6(random_addr_v6(prng)); + default: + throw ip_exception("address unspecified"); + } + } + + // bit positions between templ.prefix_len and prefix_len are randomized + inline Route random_subnet(const Route& templ, + const unsigned int prefix_len, + RandomAPI& prng) + { + if (!templ.is_canonical()) + throw Exception("IP::random_subnet: template route not canonical: " + templ.to_string()); + return Route(((random_addr(templ.addr.version(), prng) & ~templ.netmask()) | templ.addr) + & Addr::netmask_from_prefix_len(templ.addr.version(), prefix_len), + prefix_len); + } + } +} diff --git a/openvpn/addr/range.hpp b/openvpn/addr/range.hpp new file mode 100644 index 0000000..8feaf74 --- /dev/null +++ b/openvpn/addr/range.hpp @@ -0,0 +1,137 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_RANGE_H +#define OPENVPN_ADDR_RANGE_H + +#include +#include + +#include +#include + +#include + +namespace openvpn { + namespace IP { + + // Denote a range of IP addresses with a start and extent, + // where A represents an address class. + // A should be a network address class such as IP::Addr, IPv4::Addr, or IPv6::Addr. + + template + class RangeType + { + public: + class Iterator + { + friend class RangeType; + public: + bool more() const { return remaining_ > 0; } + + const ADDR& addr() const { return addr_; } + + void next() + { + if (more()) + { + ++addr_; + --remaining_; + } + } + + private: + Iterator(const RangeType& range) + : addr_(range.start_), remaining_(range.extent_) {} + + ADDR addr_; + size_t remaining_; + }; + + RangeType() : extent_(0) {} + + RangeType(const ADDR& start, const size_t extent) + : start_(start), extent_(extent) {} + + Iterator iterator() const { return Iterator(*this); } + + const bool defined() const { return extent_ > 0; } + const ADDR& start() const { return start_; } + size_t extent() const { return extent_; } + + RangeType pull_front(size_t extent) + { + if (extent > extent_) + extent = extent_; + RangeType ret(start_, extent); + start_ += extent; + extent_ -= extent; + return ret; + } + + std::string to_string() const + { + std::ostringstream os; + os << start_.to_string() << '[' << extent_ << ']'; + return os.str(); + } + + private: + ADDR start_; + size_t extent_; + }; + + template + class RangePartitionType + { + public: + RangePartitionType(const RangeType& src_range, const size_t n_partitions) + : range(src_range), + remaining(n_partitions) + { + } + + bool next(RangeType& r) + { + if (remaining) + { + if (remaining > 1) + r = range.pull_front(range.extent() / remaining); + else + r = range; + --remaining; + return r.defined(); + } + else + return false; + } + + private: + RangeType range; + size_t remaining; + }; + + typedef RangeType Range; + typedef RangePartitionType RangePartition; + } +} + +#endif diff --git a/openvpn/addr/regex.hpp b/openvpn/addr/regex.hpp new file mode 100644 index 0000000..049b9fb --- /dev/null +++ b/openvpn/addr/regex.hpp @@ -0,0 +1,59 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Regular expressions for IPv4/v6 +// Source: http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses + +#ifndef OPENVPN_ADDR_REGEX_H +#define OPENVPN_ADDR_REGEX_H + +#include + +namespace openvpn { + namespace IP { + inline std::string v4_regex() + { + const std::string ipv4seg = "(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])"; + return "(?:" + ipv4seg + "\\.){3,3}" + ipv4seg; + } + + inline std::string v6_regex() + { + const std::string ipv6seg = "[0-9a-fA-F]{1,4}"; + return "(?:" + "(?:" + ipv6seg + ":){7,7}" + ipv6seg + "|" // 1:2:3:4:5:6:7:8 + "(?:" + ipv6seg + ":){1,7}:|" // 1:: 1:2:3:4:5:6:7:: + "(?:" + ipv6seg + ":){1,6}:" + ipv6seg + "|" // 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8 + "(?:" + ipv6seg + ":){1,5}(?::" + ipv6seg + "){1,2}|" // 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8 + "(?:" + ipv6seg + ":){1,4}(?::" + ipv6seg + "){1,3}|" // 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8 + "(?:" + ipv6seg + ":){1,3}(?::" + ipv6seg + "){1,4}|" // 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8 + "(?:" + ipv6seg + ":){1,2}(?::" + ipv6seg + "){1,5}|" + // 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8 + ipv6seg + ":(?:(?::" + ipv6seg + "){1,6})|" // 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8 + ":(?:(?::" + ipv6seg + "){1,7}|:)|" // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 :: + "fe80:(?::" + ipv6seg + "){0,4}%[0-9a-zA-Z]{1,}|" // fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index) + "::(?:ffff(?::0{1,4}){0,1}:){0,1}" + v4_regex() + "|" // ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses) + "(?:" + ipv6seg + ":){1,4}:" + v4_regex() + // 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address) + ")"; + } + } +} + +#endif diff --git a/openvpn/addr/route.hpp b/openvpn/addr/route.hpp new file mode 100644 index 0000000..d67c0d8 --- /dev/null +++ b/openvpn/addr/route.hpp @@ -0,0 +1,344 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ADDR_ROUTE_H +#define OPENVPN_ADDR_ROUTE_H + +#include +#include +#include +#include // for std::uint32_t +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + namespace IP { + // Basic route object + template + class RouteType + { + public: + typedef ADDR Addr; + + ADDR addr; + unsigned int prefix_len; + + OPENVPN_EXCEPTION(route_error); + + RouteType() + : prefix_len(0) + { + } + + RouteType(const std::string& rtstr, const char *title = nullptr) + : RouteType(RouteType::from_string(rtstr, title)) + { + } + + RouteType(const std::string& rtstr, const std::string& title) + : RouteType(RouteType::from_string(rtstr, title.c_str())) + { + } + + RouteType(const ADDR& addr_arg, + const unsigned int prefix_len_arg) + : addr(addr_arg), + prefix_len(prefix_len_arg) + { + } + + static RouteType from_string(const std::string& rtstr, const char *title = nullptr) + { + RouteType r; + std::vector pair; + pair.reserve(2); + Split::by_char_void, NullLex, Split::NullLimit>(pair, rtstr, '/', 0, 1); + r.addr = ADDR::from_string(pair[0], title); + if (pair.size() >= 2) + { + r.prefix_len = parse_number_throw(pair[1], "prefix length"); + if (r.prefix_len > r.addr.size()) + OPENVPN_THROW(route_error, (title ? title : "route") << " : bad prefix length : " << rtstr); + } + else + r.prefix_len = r.addr.size(); + return r; + } + + bool defined() const + { + return addr.defined(); + } + + IP::Addr::Version version() const + { + return addr.version(); + } + + IP::Addr::VersionMask version_mask() const + { + return addr.version_mask(); + } + + RouteType to_ipv4() const + { + return RouteType(addr.to_ipv4(), prefix_len); + } + + RouteType to_ipv6() const + { + return RouteType(addr.to_ipv6(), prefix_len); + } + + ADDR netmask() const + { + return netmask_(addr, prefix_len); + } + + size_t extent() const + { + return netmask().extent_from_netmask().to_ulong(); + } + + bool is_canonical() const + { + return (addr & netmask()) == addr; + } + + void force_canonical() + { + addr = addr & netmask(); + } + + void verify_canonical() const + { + if (!is_canonical()) + throw route_error("route not canonical: " + to_string()); + } + + bool is_host() const + { + return addr.defined() && prefix_len == addr.size(); + } + + unsigned int host_bits() const + { + if (prefix_len < addr.size()) + return addr.size() - prefix_len; + else + return 0; + } + + bool contains(const ADDR& a) const // assumes canonical address/routes + { + if (addr.defined() && version_eq(addr, a)) + return (a & netmask()) == addr; + else + return false; + } + + bool contains(const RouteType& r) const // assumes canonical routes + { + return contains(r.addr) && r.prefix_len >= prefix_len; + } + + bool split(RouteType& r1, RouteType& r2) const // assumes we are canonical + { + if (!is_host()) + { + const unsigned int newpl = prefix_len + 1; + r1.addr = addr; + r1.prefix_len = newpl; + + r2.addr = addr + netmask_(addr, newpl).extent_from_netmask(); + r2.prefix_len = newpl; + + return true; + } + return false; + } + + std::string to_string() const + { + return addr.to_string() + '/' + openvpn::to_string(prefix_len); + } + + std::string to_string_by_netmask() const + { + return addr.to_string() + ' ' + netmask().to_string(); + } + + bool operator==(const RouteType& other) const + { + return std::tie(prefix_len, addr) == std::tie(other.prefix_len, other.addr); + } + + bool operator!=(const RouteType& other) const + { + return std::tie(prefix_len, addr) != std::tie(other.prefix_len, other.addr); + } + + bool operator<(const RouteType& other) const + { + return std::tie(prefix_len, addr) < std::tie(other.prefix_len, other.addr); + } + + template + void hash(HASH& h) const + { + addr.hash(h); + h(prefix_len); + } + +#ifdef HAVE_CITYHASH + std::size_t hash_value() const + { + HashSizeT h; + hash(h); + return h.value(); + } +#endif + + private: + static IPv4::Addr netmask_(const IPv4::Addr&, unsigned int prefix_len) + { + return IPv4::Addr::netmask_from_prefix_len(prefix_len); + } + + static IPv6::Addr netmask_(const IPv6::Addr&, unsigned int prefix_len) + { + return IPv6::Addr::netmask_from_prefix_len(prefix_len); + } + + static IP::Addr netmask_(const IP::Addr& addr, unsigned int prefix_len) + { + return IP::Addr::netmask_from_prefix_len(addr.version(), prefix_len); + } + + static bool version_eq(const IPv4::Addr&, const IPv4::Addr&) + { + return true; + } + + static bool version_eq(const IPv6::Addr&, const IPv6::Addr&) + { + return true; + } + + static bool version_eq(const IP::Addr& a1, const IP::Addr& a2) + { + return a1.version() == a2.version(); + } + }; + + template + struct RouteTypeList : public std::vector> + { + typedef std::vector< RouteType > Base; + + OPENVPN_EXCEPTION(route_list_error); + + std::string to_string() const + { + std::ostringstream os; + for (auto &r : *this) + os << r.to_string() << std::endl; + return os.str(); + } + + IP::Addr::VersionMask version_mask() const + { + IP::Addr::VersionMask mask = 0; + for (auto &r : *this) + mask |= r.version_mask(); + return mask; + } + + void verify_canonical() const + { + for (auto &r : *this) + r.verify_canonical(); + } + + template + bool contains(const R& c) const + { + for (auto &r : *this) + if (r.contains(c)) + return true; + return false; + } + }; + + typedef RouteType Route; + typedef RouteType Route4; + typedef RouteType Route6; + + typedef RouteTypeList RouteList; + typedef RouteTypeList Route4List; + typedef RouteTypeList Route6List; + + OPENVPN_OSTREAM(Route, to_string); + OPENVPN_OSTREAM(Route4, to_string); + OPENVPN_OSTREAM(Route6, to_string); + + OPENVPN_OSTREAM(RouteList, to_string); + OPENVPN_OSTREAM(Route4List, to_string); + OPENVPN_OSTREAM(Route6List, to_string); + + inline Route route_from_string_prefix(const std::string& addrstr, + const unsigned int prefix_len, + const std::string& title, + const IP::Addr::Version required_version = IP::Addr::UNSPEC) + { + Route r; + r.addr = IP::Addr(addrstr, title, required_version); + r.prefix_len = prefix_len; + if (r.prefix_len > r.addr.size()) + OPENVPN_THROW(Route::route_error, title << " : bad prefix length : " << addrstr); + return r; + } + + inline Route route_from_string(const std::string& rtstr, + const std::string& title, + const IP::Addr::Version required_version = IP::Addr::UNSPEC) + { + Route r(rtstr, title); + r.addr.validate_version(title, required_version); + return r; + } + } +} + +#ifdef HAVE_CITYHASH +OPENVPN_HASH_METHOD(openvpn::IP::Route, hash_value); +OPENVPN_HASH_METHOD(openvpn::IP::Route4, hash_value); +OPENVPN_HASH_METHOD(openvpn::IP::Route6, hash_value); +#endif + +#endif diff --git a/openvpn/apple/cf/cf.hpp b/openvpn/apple/cf/cf.hpp new file mode 100644 index 0000000..f5e9e87 --- /dev/null +++ b/openvpn/apple/cf/cf.hpp @@ -0,0 +1,459 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_CF_H +#define OPENVPN_APPLECRYPTO_CF_CF_H + +#include +#include +#include +#include +#include +#include + +#include + +// Wrapper classes for Apple Core Foundation objects. + +#define OPENVPN_CF_WRAP(cls, castmeth, cftype, idmeth) \ + template <> \ + struct Type \ + { \ + static CFTypeRef cast(CFTypeRef obj) \ + { \ + if (obj && CFGetTypeID(obj) == idmeth()) \ + return obj; \ + else \ + return nullptr; \ + } \ + }; \ + typedef Wrap cls; \ + inline cls castmeth(CFTypeRef obj) \ + { \ + CFTypeRef o = Type::cast(obj); \ + if (o) \ + return cls(cftype(o), GET); \ + else \ + return cls(); \ + } + +namespace openvpn { + namespace CF + { + enum Rule { + CREATE, // create rule + GET // get rule + }; + + template struct Type {}; + + template + class Wrap + { + public: + Wrap() : obj_(nullptr) {} + + explicit Wrap(T obj, const Rule rule=CREATE) + { + if (rule == GET && obj) + CFRetain(obj); + obj_ = obj; + } + + Wrap(const Wrap& other) + { + obj_ = other.obj_; + if (obj_) + CFRetain(obj_); + } + + Wrap& operator=(const Wrap& other) + { + if (other.obj_) + CFRetain(other.obj_); + if (obj_) + CFRelease(obj_); + obj_ = other.obj_; + return *this; + } + + Wrap(Wrap&& other) noexcept + { + obj_ = other.obj_; + other.obj_ = nullptr; + } + + Wrap& operator=(Wrap&& other) noexcept + { + if (obj_) + CFRelease(obj_); + obj_ = other.obj_; + other.obj_ = nullptr; + return *this; + } + + void swap(Wrap& other) + { + std::swap(obj_, other.obj_); + } + + void reset(T obj=nullptr, const Rule rule=CREATE) + { + if (rule == GET && obj) + CFRetain(obj); + if (obj_) + CFRelease(obj_); + obj_ = obj; + } + + bool defined() const { return obj_ != nullptr; } + + explicit operator bool() const noexcept + { + return defined(); + } + + T operator()() const { return obj_; } + + CFTypeRef generic() const { return (CFTypeRef)obj_; } + + static T cast(CFTypeRef obj) { return T(Type::cast(obj)); } + + static Wrap from_generic(CFTypeRef obj, const Rule rule=CREATE) + { + return Wrap(cast(obj), rule); + } + + T release() + { + T ret = obj_; + obj_ = nullptr; + return ret; + } + + CFTypeRef generic_release() + { + T ret = obj_; + obj_ = nullptr; + return (CFTypeRef)ret; + } + + // Intended for use with Core Foundation methods that require + // a T* for saving a create-rule return value + T* mod_ref() + { + if (obj_) + { + CFRelease(obj_); + obj_ = nullptr; + } + return &obj_; + } + + void show() const + { + if (obj_) + CFShow(obj_); + else + std::cerr << "CF_UNDEFINED" << std::endl; + } + + virtual ~Wrap() + { + if (obj_) + CFRelease(obj_); + } + + private: + Wrap& operator=(T obj) = delete; // prevent use because no way to pass rule parameter + + T obj_; + }; + + // common CF types + + OPENVPN_CF_WRAP(String, string_cast, CFStringRef, CFStringGetTypeID) + OPENVPN_CF_WRAP(Number, number_cast, CFNumberRef, CFNumberGetTypeID) + OPENVPN_CF_WRAP(Bool, bool_cast, CFBooleanRef, CFBooleanGetTypeID) + OPENVPN_CF_WRAP(Data, data_cast, CFDataRef, CFDataGetTypeID) + OPENVPN_CF_WRAP(Array, array_cast, CFArrayRef, CFArrayGetTypeID) + OPENVPN_CF_WRAP(MutableArray, mutable_array_cast, CFMutableArrayRef, CFArrayGetTypeID) + OPENVPN_CF_WRAP(Dict, dict_cast, CFDictionaryRef, CFDictionaryGetTypeID) + OPENVPN_CF_WRAP(MutableDict, mutable_dict_cast, CFMutableDictionaryRef, CFDictionaryGetTypeID) + OPENVPN_CF_WRAP(Error, error_cast, CFErrorRef, CFErrorGetTypeID); + + // generic CFTypeRef wrapper + + typedef Wrap Generic; + + inline Generic generic_cast(CFTypeRef obj) + { + return Generic(obj, GET); + } + + // constructors + + inline String string(const char *str) + { + return String(CFStringCreateWithCString(kCFAllocatorDefault, str, kCFStringEncodingUTF8)); + } + + inline String string(CFStringRef str) + { + return String(str, GET); + } + + inline String string(const String& str) + { + return String(str); + } + + inline String string(const std::string& str) + { + return String(CFStringCreateWithCString(kCFAllocatorDefault, str.c_str(), kCFStringEncodingUTF8)); + } + + inline String string(const std::string* str) + { + return String(CFStringCreateWithCString(kCFAllocatorDefault, str->c_str(), kCFStringEncodingUTF8)); + } + + inline Number number_from_int(const int n) + { + return Number(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &n)); + } + + inline Number number_from_int32(const SInt32 n) + { + return Number(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &n)); + } + + inline Number number_from_long_long(const long long n) + { + return Number(CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &n)); + } + + inline Number number_from_index(const CFIndex n) + { + return Number(CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &n)); + } + + inline Data data(const void *bytes, CFIndex length) + { + return Data(CFDataCreate(kCFAllocatorDefault, (const UInt8 *)bytes, length)); + } + + inline Array array(const void **values, CFIndex numValues) + { + return Array(CFArrayCreate(kCFAllocatorDefault, values, numValues, &kCFTypeArrayCallBacks)); + } + + inline Dict dict(const void **keys, const void **values, CFIndex numValues) + { + return Dict(CFDictionaryCreate(kCFAllocatorDefault, + keys, + values, + numValues, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + } + + inline Dict const_dict(MutableDict& mdict) + { + return Dict(mdict(), CF::GET); + } + + inline Array const_array(MutableArray& marray) + { + return Array(marray(), CF::GET); + } + + inline Dict empty_dict() + { + return Dict(CFDictionaryCreate(kCFAllocatorDefault, + nullptr, + nullptr, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + } + + inline MutableArray mutable_array(const CFIndex capacity=0) + { + return MutableArray(CFArrayCreateMutable(kCFAllocatorDefault, capacity, &kCFTypeArrayCallBacks)); + } + + inline MutableDict mutable_dict(const CFIndex capacity=0) + { + return MutableDict(CFDictionaryCreateMutable(kCFAllocatorDefault, capacity, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + } + + template + inline MutableDict mutable_dict_copy(const DICT& dict, const CFIndex capacity=0) + { + if (dict.defined()) + return MutableDict(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, capacity, dict())); + else + return mutable_dict(capacity); + } + + inline Error error(CFStringRef domain, CFIndex code, CFDictionaryRef userInfo) + { + return Error(CFErrorCreate(kCFAllocatorDefault, domain, code, userInfo)); + } + + // accessors + + template + inline CFIndex array_len(const ARRAY& array) + { + if (array.defined()) + return CFArrayGetCount(array()); + else + return 0; + } + + template + inline CFIndex dict_len(const DICT& dict) + { + if (dict.defined()) + return CFDictionaryGetCount(dict()); + else + return 0; + } + + template + inline CFTypeRef array_index(const ARRAY& array, const CFIndex idx) + { + if (array.defined() && CFArrayGetCount(array()) > idx) + return CFArrayGetValueAtIndex(array(), idx); + else + return nullptr; + } + + template + inline CFTypeRef dict_index(const DICT& dict, const KEY& key) + { + if (dict.defined()) + { + String keystr = string(key); + if (keystr.defined()) + return CFDictionaryGetValue(dict(), keystr()); + } + return nullptr; + } + + // string methods + + struct cppstring_error : public std::exception + { + virtual const char* what() const throw() + { + return "cppstring_error"; + } + }; + + inline std::string cppstring(CFStringRef str) + { + const CFStringEncoding encoding = kCFStringEncodingUTF8; + if (str) + { + const CFIndex len = CFStringGetLength(str); + if (len > 0) + { + const CFIndex maxsize = CFStringGetMaximumSizeForEncoding(len, encoding); + char *buf = new char[maxsize]; + const Boolean status = CFStringGetCString(str, buf, maxsize, encoding); + if (status) + { + std::string ret(buf); + delete [] buf; + return ret; + } + else + { + delete [] buf; + throw cppstring_error(); + } + } + } + return ""; + } + + inline std::string cppstring(const String& str) + { + return cppstring(str()); + } + + inline std::string description(CFTypeRef obj) + { + if (obj) + { + String s(CFCopyDescription(obj)); + return cppstring(s); + } + else + return "UNDEF"; + } + + // format an array of strings (non-string elements in array are ignored) + template + inline std::string array_to_string(const ARRAY& array, const char delim=',') + { + std::ostringstream os; + const CFIndex len = array_len(array); + if (len) + { + bool sep = false; + for (CFIndex i = 0; i < len; ++i) + { + const String v(string_cast(array_index(array, i))); + if (v.defined()) + { + if (sep) + os << delim; + os << cppstring(v); + sep = true; + } + } + } + return os.str(); + } + + inline bool string_equal(const String& s1, const String& s2, const CFStringCompareFlags compareOptions = 0) + { + return s1.defined() && s2.defined() && CFStringCompare(s1(), s2(), compareOptions) == kCFCompareEqualTo; + } + + // property lists + inline Data plist(CFTypeRef obj) + { + return Data(CFPropertyListCreateData(kCFAllocatorDefault, + obj, + kCFPropertyListBinaryFormat_v1_0, + 0, + nullptr)); + } + + } // namespace CF +} // namespace openvpn + +#endif // OPENVPN_APPLECRYPTO_CF_CF_H diff --git a/openvpn/apple/cf/cfhelper.hpp b/openvpn/apple/cf/cfhelper.hpp new file mode 100644 index 0000000..4c8d336 --- /dev/null +++ b/openvpn/apple/cf/cfhelper.hpp @@ -0,0 +1,261 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_CFHELPER_H +#define OPENVPN_APPLECRYPTO_CF_CFHELPER_H + +#include +#include + +// These methods build on the Wrapper classes for Apple Core Foundation objects +// defined in cf.hpp. They add additional convenience methods, such as dictionary +// lookup. + +namespace openvpn { + namespace CF { + + // essentially a vector of void *, used as source for array and dictionary constructors + typedef BufferAllocatedType SrcList; + + inline Array array(const SrcList& values) + { + return array((const void **)values.c_data(), values.size()); + } + + inline Dict dict(const SrcList& keys, const SrcList& values) + { + return dict((const void **)keys.c_data(), (const void **)values.c_data(), std::min(keys.size(), values.size())); + } + + inline CFTypeRef mutable_dict_new() + { + return CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + + inline CFTypeRef mutable_array_new() + { + return CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + } + + // Lookup or create (if absent) an item in a mutable dictionary. + // Return the item, which will be owned by base. + template + inline CFTypeRef dict_get_create(CFMutableDictionaryRef base, + const KEY& key, + CFTypeRef (*create_method)()) + { + if (base) + { + String keystr = string(key); + CFTypeRef ret = CFDictionaryGetValue(base, keystr()); // try lookup first + if (!ret) + { + // doesn't exist, must create + ret = (*create_method)(); + CFDictionaryAddValue(base, keystr(), ret); + CFRelease(ret); // because ret is now owned by base + } + return ret; + } + return nullptr; + } + + // lookup a dict in another dict (base) and return or create if absent + template + inline MutableDict dict_get_create_dict(MutableDict& base, const KEY& key) + { + String keystr = string(key); + return mutable_dict_cast(dict_get_create(base(), keystr(), mutable_dict_new)); + } + + // lookup an array in a dict (base) and return or create if absent + template + inline MutableArray dict_get_create_array(MutableDict& base, const KEY& key) + { + String keystr = string(key); + return mutable_array_cast(dict_get_create(base(), keystr(), mutable_array_new)); + } + + // lookup an object in a dictionary (DICT should be a Dict or a MutableDict) + template + inline CFTypeRef dict_get_obj(const DICT& dict, const KEY& key) + { + return dict_index(dict, key); + } + + // lookup a string in a dictionary (DICT should be a Dict or a MutableDict) + template + inline std::string dict_get_str(const DICT& dict, const KEY& key) + { + return cppstring(string_cast(dict_index(dict, key))); + } + + // lookup a string in a dictionary (DICT should be a Dict or a MutableDict) + template + inline std::string dict_get_str(const DICT& dict, const KEY& key, const std::string& default_value) + { + String str(string_cast(dict_index(dict, key))); + if (str.defined()) + return cppstring(str()); + else + return default_value; + } + + // lookup an integer in a dictionary (DICT should be a Dict or a MutableDict) + template + inline int dict_get_int(const DICT& dict, const KEY& key, const int default_value) + { + int ret; + Number num = number_cast(dict_index(dict, key)); + if (num.defined() && CFNumberGetValue(num(), kCFNumberIntType, &ret)) + return ret; + else + return default_value; + } + + // lookup a boolean in a dictionary (DICT should be a Dict or a MutableDict) + template + inline bool dict_get_bool(const DICT& dict, const KEY& key, const bool default_value) + { + Bool b = bool_cast(dict_index(dict, key)); + if (b.defined()) + { + if (b() == kCFBooleanTrue) + return true; + else if (b() == kCFBooleanFalse) + return false; + } + return default_value; + } + + // like CFDictionarySetValue, but no-op if any args are NULL + inline void dictionarySetValue(CFMutableDictionaryRef theDict, const void *key, const void *value) + { + if (theDict && key && value) + CFDictionarySetValue(theDict, key, value); + } + + // like CFArrayAppendValue, but no-op if any args are NULL + inline void arrayAppendValue(CFMutableArrayRef theArray, const void *value) + { + if (theArray && value) + CFArrayAppendValue(theArray, value); + } + + // set a CFTypeRef in a mutable dictionary + template + inline void dict_set_obj(MutableDict& dict, const KEY& key, CFTypeRef value) + { + String keystr = string(key); + dictionarySetValue(dict(), keystr(), value); + } + + // set a string in a mutable dictionary + + template + inline void dict_set_str(MutableDict& dict, const KEY& key, const VALUE& value) + { + String keystr = string(key); + String valstr = string(value); + dictionarySetValue(dict(), keystr(), valstr()); + } + + // set a number in a mutable dictionary + + template + inline void dict_set_int(MutableDict& dict, const KEY& key, int value) + { + String keystr = string(key); + Number num = number_from_int(value); + dictionarySetValue(dict(), keystr(), num()); + } + + template + inline void dict_set_int32(MutableDict& dict, const KEY& key, SInt32 value) + { + String keystr = string(key); + Number num = number_from_int32(value); + dictionarySetValue(dict(), keystr(), num()); + } + + template + inline void dict_set_long_long(MutableDict& dict, const KEY& key, long long value) + { + String keystr = string(key); + Number num = number_from_long_long(value); + dictionarySetValue(dict(), keystr(), num()); + } + + template + inline void dict_set_index(MutableDict& dict, const KEY& key, CFIndex value) + { + String keystr = string(key); + Number num = number_from_index(value); + dictionarySetValue((CFMutableDictionaryRef)dict(), keystr(), num()); + } + + // set a boolean in a mutable dictionary + + template + inline void dict_set_bool(MutableDict& dict, const KEY& key, bool value) + { + String keystr = string(key); + CFBooleanRef boolref = value ? kCFBooleanTrue : kCFBooleanFalse; + dictionarySetValue(dict(), keystr(), boolref); + } + + // append string to a mutable array + + template + inline void array_append_str(MutableArray& array, const VALUE& value) + { + String valstr = string(value); + arrayAppendValue(array(), valstr()); + } + + // append a number to a mutable array + + inline void array_append_int(MutableArray& array, int value) + { + Number num = number_from_int(value); + arrayAppendValue(array(), num()); + } + + inline void array_append_int32(MutableArray& array, SInt32 value) + { + Number num = number_from_int32(value); + arrayAppendValue(array(), num()); + } + + inline void array_append_long_long(MutableArray& array, long long value) + { + Number num = number_from_long_long(value); + arrayAppendValue(array(), num()); + } + + inline void array_append_index(MutableArray& array, CFIndex value) + { + Number num = number_from_index(value); + arrayAppendValue(array(), num()); + } + } +} +#endif diff --git a/openvpn/apple/cf/cfhost.hpp b/openvpn/apple/cf/cfhost.hpp new file mode 100644 index 0000000..ab51494 --- /dev/null +++ b/openvpn/apple/cf/cfhost.hpp @@ -0,0 +1,33 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_CFHOST_H +#define OPENVPN_APPLECRYPTO_CF_CFHOST_H + +#include + +namespace openvpn { + namespace CF { + OPENVPN_CF_WRAP(Host, host_cast, CFHostRef, CFHostGetTypeID) + } +} + +#endif diff --git a/openvpn/apple/cf/cfrunloop.hpp b/openvpn/apple/cf/cfrunloop.hpp new file mode 100644 index 0000000..777af0c --- /dev/null +++ b/openvpn/apple/cf/cfrunloop.hpp @@ -0,0 +1,34 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_CFRUNLOOP_H +#define OPENVPN_APPLECRYPTO_CF_CFRUNLOOP_H + +#include + +namespace openvpn { + namespace CF { + OPENVPN_CF_WRAP(RunLoop, runloop_cast, CFRunLoopRef, CFRunLoopGetTypeID) + OPENVPN_CF_WRAP(RunLoopSource, runloop_source_cast, CFRunLoopSourceRef, CFRunLoopSourceGetTypeID); + } +} + +#endif diff --git a/openvpn/apple/cf/cfsec.hpp b/openvpn/apple/cf/cfsec.hpp new file mode 100644 index 0000000..87da3e5 --- /dev/null +++ b/openvpn/apple/cf/cfsec.hpp @@ -0,0 +1,58 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_CFSEC_H +#define OPENVPN_APPLECRYPTO_CF_CFSEC_H + +#include + +#include +#include +#include +#include + +#ifndef OPENVPN_PLATFORM_IPHONE +#include +#include +#endif + +#include +#include +#include + +// Define C++ wrappings for Apple security-related objects. + +namespace openvpn { + namespace CF { + OPENVPN_CF_WRAP(Cert, cert_cast, SecCertificateRef, SecCertificateGetTypeID) + OPENVPN_CF_WRAP(Key, key_cast, SecKeyRef, SecKeyGetTypeID) + OPENVPN_CF_WRAP(Identity, identity_cast, SecIdentityRef, SecIdentityGetTypeID) + OPENVPN_CF_WRAP(Policy, policy_cast, SecPolicyRef, SecPolicyGetTypeID) + OPENVPN_CF_WRAP(Trust, trust_cast, SecTrustRef, SecTrustGetTypeID) +#ifndef OPENVPN_PLATFORM_IPHONE + OPENVPN_CF_WRAP(Keychain, keychain_cast, SecKeychainRef, SecKeychainGetTypeID) + OPENVPN_CF_WRAP(Access, access_cast, SecAccessRef, SecAccessGetTypeID) +#endif + } // namespace CF + +} // namespace openvpn + +#endif // OPENVPN_APPLECRYPTO_CF_CFSEC_H diff --git a/openvpn/apple/cf/cfsocket.hpp b/openvpn/apple/cf/cfsocket.hpp new file mode 100644 index 0000000..285114f --- /dev/null +++ b/openvpn/apple/cf/cfsocket.hpp @@ -0,0 +1,33 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_CFSTREAM_H +#define OPENVPN_APPLECRYPTO_CF_CFSTREAM_H + +#include + +namespace openvpn { + namespace CF { + OPENVPN_CF_WRAP(Socket, socket_cast, CFSocketRef, CFSocketGetTypeID) + } +} + +#endif diff --git a/openvpn/apple/cf/cfstream.hpp b/openvpn/apple/cf/cfstream.hpp new file mode 100644 index 0000000..7976190 --- /dev/null +++ b/openvpn/apple/cf/cfstream.hpp @@ -0,0 +1,34 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_CFSTREAM_H +#define OPENVPN_APPLECRYPTO_CF_CFSTREAM_H + +#include + +namespace openvpn { + namespace CF { + OPENVPN_CF_WRAP(ReadStream, read_stream_cast, CFReadStreamRef, CFReadStreamGetTypeID) + OPENVPN_CF_WRAP(WriteStream, write_stream_cast, CFWriteStreamRef, CFWriteStreamGetTypeID) + } +} + +#endif diff --git a/openvpn/apple/cf/cftimer.hpp b/openvpn/apple/cf/cftimer.hpp new file mode 100644 index 0000000..5acc7ec --- /dev/null +++ b/openvpn/apple/cf/cftimer.hpp @@ -0,0 +1,33 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_CFTIMER_H +#define OPENVPN_APPLECRYPTO_CF_CFTIMER_H + +#include + +namespace openvpn { + namespace CF { + OPENVPN_CF_WRAP(Timer, timer_cast, CFRunLoopTimerRef, CFRunLoopTimerGetTypeID) + } +} + +#endif diff --git a/openvpn/apple/cf/error.hpp b/openvpn/apple/cf/error.hpp new file mode 100644 index 0000000..ca087a0 --- /dev/null +++ b/openvpn/apple/cf/error.hpp @@ -0,0 +1,67 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CF_ERROR_H +#define OPENVPN_APPLECRYPTO_CF_ERROR_H + +#include + +#include + +#include + +// An exception object that encapsulates Apple Core Foundation errors. + +namespace openvpn { + + // string exception class + class CFException : public std::exception + { + public: + CFException(const std::string& text) + { + errtxt = text; + } + + CFException(const std::string& text, const OSStatus status) + { + set_errtxt(text, status); + } + + virtual const char* what() const throw() { return errtxt.c_str(); } + std::string what_str() const { return errtxt; } + + virtual ~CFException() throw() {} + + private: + void set_errtxt(const std::string& text, const OSStatus status) + { + std::ostringstream s; + s << text << ": OSX Error code=" << status; + errtxt = s.str(); + } + + std::string errtxt; + }; + +} // namespace openvpn + +#endif // OPENVPN_APPLECRYPTO_CF_ERROR_H diff --git a/openvpn/apple/iosactiveiface.hpp b/openvpn/apple/iosactiveiface.hpp new file mode 100644 index 0000000..91d0b29 --- /dev/null +++ b/openvpn/apple/iosactiveiface.hpp @@ -0,0 +1,74 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#include + +#include +#include + +#ifndef OPENVPN_APPLECRYPTO_UTIL_IOSACTIVEIFACE_H +#define OPENVPN_APPLECRYPTO_UTIL_IOSACTIVEIFACE_H + +namespace openvpn { + + class iOSActiveInterface : public ReachabilityInterface + { + public: + virtual Status reachable() const + { + if (ei.iface_up("en0")) + return ReachableViaWiFi; + else if (ei.iface_up("pdp_ip0")) + return ReachableViaWWAN; + else + return NotReachable; + } + + virtual bool reachableVia(const std::string& net_type) const + { + const Status r = reachable(); + if (net_type == "cellular") + return r == ReachableViaWWAN; + else if (net_type == "wifi") + return r == ReachableViaWiFi; + else + return r != NotReachable; + } + + virtual std::string to_string() const + { + switch (reachable()) + { + case ReachableViaWiFi: + return "ReachableViaWiFi"; + case ReachableViaWWAN: + return "ReachableViaWWAN"; + case NotReachable: + return "NotReachable"; + } + } + + private: + EnumIface ei; + }; + +} +#endif diff --git a/openvpn/apple/maclife.hpp b/openvpn/apple/maclife.hpp new file mode 100644 index 0000000..e1a32ec --- /dev/null +++ b/openvpn/apple/maclife.hpp @@ -0,0 +1,325 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLE_MACLIFE_H +#define OPENVPN_APPLE_MACLIFE_H + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + class MacLifeCycle : public ClientLifeCycle, MacSleep, ReachabilityTracker + { + public: + OPENVPN_EXCEPTION(mac_lifecycle_error); + + MacLifeCycle() + : ReachabilityTracker(true, false), + nc(nullptr), + thread(nullptr), + paused(false) + { + } + + virtual ~MacLifeCycle() + { + stop_thread(); + } + + virtual bool network_available() + { + return net_up(); + } + + virtual void start(NotifyCallback* nc_arg) + { + if (!thread && nc_arg) + { + nc = nc_arg; + thread = new std::thread(&MacLifeCycle::thread_func, this); + } + } + + virtual void stop() + { + stop_thread(); + } + + private: + struct State + { + State() + : net_up(false), + sleep(false) + { + } + + State(bool net_up_arg, const std::string& iface_arg, bool sleep_arg) + : net_up(net_up_arg), + iface(iface_arg), + sleep(sleep_arg) + { + } + + bool operator==(const State& other) const + { + return net_up == other.net_up && iface == other.iface && sleep == other.sleep; + } + + bool operator!=(const State& other) const + { + return !operator==(other); + } + + std::string to_string() const + { + std::ostringstream os; + os << "[net_up=" << net_up << " iface=" << iface << " sleep=" << sleep << ']'; + return os.str(); + } + + bool net_up; + std::string iface; + bool sleep; + }; + + void stop_thread() + { + if (thread) + { + if (runloop.defined()) + CFRunLoopStop(runloop()); + thread->join(); + delete thread; + thread = nullptr; + } + } + + void thread_func() + { + runloop.reset(CFRunLoopGetCurrent(), CF::GET); + Log::Context logctx(logwrap); + try { + // set up dynamic store query object + dstore.reset(SCDynamicStoreCreate(kCFAllocatorDefault, + CFSTR("OpenVPN_MacLifeCycle"), + nullptr, + nullptr)); + + // init state + state = State(net_up(), primary_interface(), false); + prev_state = state; + paused = false; + + // enable sleep/wakeup notifications + mac_sleep_start(); + + // enable network reachability notifications + reachability_tracker_schedule(); + + // enable interface change notifications + iface_watch(); + + // process event loop until CFRunLoopStop is called from parent thread + CFRunLoopRun(); + } + catch (const std::exception& e) + { + OPENVPN_LOG("MacLifeCycle exception: " << e.what()); + } + + // cleanup + cancel_action_timer(); + mac_sleep_stop(); + reachability_tracker_cancel(); + dstore.reset(); + } + + std::string primary_interface() + { + CF::Dict dict(CF::DynamicStoreCopyDict(dstore, "State:/Network/Global/IPv4")); + return CF::dict_get_str(dict, "PrimaryInterface"); + } + + bool net_up() + { + ReachabilityViaInternet r; + return ReachabilityViaInternet::status_from_flags(r.flags()) != ReachabilityInterface::NotReachable; + } + + void iface_watch() + { + SCDynamicStoreContext context = {0, this, nullptr, nullptr, nullptr}; + CF::DynamicStore ds(SCDynamicStoreCreate(kCFAllocatorDefault, + CFSTR("OpenVPN_MacLifeCycle_iface_watch"), + iface_watch_callback_static, + &context)); + if (!ds.defined()) + throw mac_lifecycle_error("SCDynamicStoreCreate"); + CF::MutableArray watched_keys(CF::mutable_array()); + CF::array_append_str(watched_keys, "State:/Network/Global/IPv4"); + //CF::array_append_str(watched_keys, "State:/Network/Global/IPv6"); + if (!watched_keys.defined()) + throw mac_lifecycle_error("watched_keys is undefined"); + if (!SCDynamicStoreSetNotificationKeys(ds(), + watched_keys(), + nullptr)) + throw mac_lifecycle_error("SCDynamicStoreSetNotificationKeys failed"); + CF::RunLoopSource rls(SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, ds(), 0)); + if (!rls.defined()) + throw mac_lifecycle_error("SCDynamicStoreCreateRunLoopSource failed"); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls(), kCFRunLoopDefaultMode); + } + + static void iface_watch_callback_static(SCDynamicStoreRef store, CFArrayRef changedKeys, void *arg) + { + MacLifeCycle *self = (MacLifeCycle *)arg; + self->iface_watch_callback(store, changedKeys); + } + + void iface_watch_callback(SCDynamicStoreRef store, CFArrayRef changedKeys) + { + state.iface = primary_interface(); + OPENVPN_LOG("MacLifeCycle NET_IFACE " << state.iface); + schedule_action_timer(1); + } + + virtual void notify_sleep() + { + OPENVPN_LOG("MacLifeCycle SLEEP"); + state.sleep = true; + schedule_action_timer(0); + } + + virtual void notify_wakeup() + { + OPENVPN_LOG("MacLifeCycle WAKEUP"); + state.sleep = false; + schedule_action_timer(1); + } + + virtual void reachability_tracker_event(const ReachabilityBase& rb, SCNetworkReachabilityFlags flags) + { + if (rb.vtype() == ReachabilityBase::Internet) + { + const ReachabilityBase::Status status = rb.vstatus(flags); + state.net_up = (status != ReachabilityInterface::NotReachable); + OPENVPN_LOG("MacLifeCycle NET_STATE " << state.net_up << " status=" << ReachabilityBase::render_status(status) << " flags=" << ReachabilityBase::render_flags(flags)); + schedule_action_timer(1); + } + } + + void schedule_action_timer(const int seconds) + { + cancel_action_timer(); + if (seconds) + { + CFRunLoopTimerContext context = { 0, this, nullptr, nullptr, nullptr }; + action_timer.reset(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + seconds, 0, 0, 0, action_timer_callback_static, &context)); + if (action_timer.defined()) + CFRunLoopAddTimer(CFRunLoopGetCurrent(), action_timer(), kCFRunLoopCommonModes); + else + OPENVPN_LOG("MacLifeCycle::schedule_action_timer: failed to create timer"); + } + else + action_timer_callback(nullptr); + } + + void cancel_action_timer() + { + if (action_timer.defined()) + { + CFRunLoopTimerInvalidate(action_timer()); + action_timer.reset(nullptr); + } + } + + static void action_timer_callback_static(CFRunLoopTimerRef timer, void *info) + { + MacLifeCycle* self = (MacLifeCycle*)info; + self->action_timer_callback(timer); + } + + void action_timer_callback(CFRunLoopTimerRef timer) + { + try { + if (state != prev_state) + { + OPENVPN_LOG("MacLifeCycle ACTION pause=" << paused << " state=" << state.to_string() << " prev=" << prev_state.to_string()); + if (paused) + { + if (!state.sleep && state.net_up) + { + nc->cln_resume(); + paused = false; + } + } + else + { + if (state.sleep) + { + nc->cln_pause("sleep"); + paused = true; + } + else if (!state.net_up) + { + nc->cln_pause("network-unavailable"); + paused = true; + } + else + { + if (state.iface != prev_state.iface) + nc->cln_reconnect(0); + } + } + prev_state = state; + } + } + catch (const std::exception& e) + { + OPENVPN_LOG("MacLifeCycle::action_timer_callback exception: " << e.what()); + } + } + + NotifyCallback* nc; + std::thread* thread; + CF::RunLoop runloop; // run loop in thread + CF::DynamicStore dstore; + State state; + State prev_state; + bool paused; + CF::Timer action_timer; + Log::Context::Wrapper logwrap; // used to carry forward the log context from parent thread + }; +} + +#endif diff --git a/openvpn/apple/macsleep.hpp b/openvpn/apple/macsleep.hpp new file mode 100644 index 0000000..eeaa6d7 --- /dev/null +++ b/openvpn/apple/macsleep.hpp @@ -0,0 +1,129 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLE_MACSLEEP_H +#define OPENVPN_APPLE_MACSLEEP_H + +#include +#include +#include + +#include +#include + +#include + +namespace openvpn { + class MacSleep + { + MacSleep(const MacSleep&) = delete; + MacSleep& operator=(const MacSleep&) = delete; + + public: + MacSleep() + : root_port(0), + notifyPortRef(nullptr), + notifierObject(0) + { + } + + virtual ~MacSleep() + { + mac_sleep_stop(); + } + + bool mac_sleep_start() + { + if (!root_port) + { + root_port = IORegisterForSystemPower(this, ¬ifyPortRef, callback_static, ¬ifierObject); + if (!root_port) + return false; + CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes); + } + return true; + } + + void mac_sleep_stop() + { + if (root_port) + { + // remove the sleep notification port from the application runloop + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), + IONotificationPortGetRunLoopSource(notifyPortRef), + kCFRunLoopCommonModes); + + // deregister for system sleep notifications + IODeregisterForSystemPower(¬ifierObject); + + // IORegisterForSystemPower implicitly opens the Root Power Domain IOService + // so we close it here + IOServiceClose(root_port); + + // destroy the notification port allocated by IORegisterForSystemPower + IONotificationPortDestroy(notifyPortRef); + + // reset object members + root_port = 0; + notifyPortRef = nullptr; + notifierObject = 0; + } + } + + virtual void notify_sleep() = 0; + virtual void notify_wakeup() = 0; + + private: + static void callback_static(void* arg, io_service_t service, natural_t messageType, void *messageArgument) + { + MacSleep* self = (MacSleep*)arg; + self->callback(service, messageType, messageArgument); + } + + void callback(io_service_t service, natural_t messageType, void *messageArgument) + { + switch (messageType) + { + case kIOMessageCanSystemSleep: + IOAllowPowerChange(root_port, (long)messageArgument); + break; + case kIOMessageSystemWillSleep: + notify_sleep(); + IOAllowPowerChange(root_port, (long)messageArgument); + break; + case kIOMessageSystemHasPoweredOn: + notify_wakeup(); + break; + } + } + + // a reference to the Root Power Domain IOService + io_connect_t root_port; + + // notification port allocated by IORegisterForSystemPower + IONotificationPortRef notifyPortRef; + + // notifier object, used to deregister later + io_object_t notifierObject; + }; +} + +#endif diff --git a/openvpn/apple/macver.hpp b/openvpn/apple/macver.hpp new file mode 100644 index 0000000..b3c128b --- /dev/null +++ b/openvpn/apple/macver.hpp @@ -0,0 +1,75 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLE_MACVER_H +#define OPENVPN_APPLE_MACVER_H + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace openvpn { + namespace Mac { + class Version : public AppleVersion + { + public: + // Mac OS X versions + // 15.x.x OS X 10.11.x El Capitan + // 14.x.x OS X 10.10.x Yosemite + // 13.x.x OS X 10.9.x Mavericks + // 12.x.x OS X 10.8.x Mountain Lion + // 11.x.x OS X 10.7.x Lion + // 10.x.x OS X 10.6.x Snow Leopard + // 9.x.x OS X 10.5.x Leopard + // 8.x.x OS X 10.4.x Tiger + // 7.x.x OS X 10.3.x Panther + // 6.x.x OS X 10.2.x Jaguar + // 5.x OS X 10.1.x Puma + + enum { + OSX_10_11=15, + OSX_10_10=14, + OSX_10_9=13, + OSX_10_8=12, + OSX_10_7=11, + OSX_10_6=10, + }; + + Version() + { + char str[256]; + size_t size = sizeof(str); + int ret = sysctlbyname("kern.osrelease", str, &size, nullptr, 0); + if (!ret) + init(std::string(str, size)); + } + }; + } +} + +#endif diff --git a/openvpn/apple/reach.hpp b/openvpn/apple/reach.hpp new file mode 100644 index 0000000..8aaf136 --- /dev/null +++ b/openvpn/apple/reach.hpp @@ -0,0 +1,43 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_UTIL_REACH_H +#define OPENVPN_APPLECRYPTO_UTIL_REACH_H + +// An interface to various network reachability implementations, +// primarily for iOS. + +namespace openvpn { + struct ReachabilityInterface + { + enum Status { + NotReachable, + ReachableViaWiFi, + ReachableViaWWAN + }; + + virtual Status reachable() const = 0; + virtual bool reachableVia(const std::string& net_type) const = 0; + virtual std::string to_string() const = 0; + virtual ~ReachabilityInterface() {} + }; +} +#endif diff --git a/openvpn/apple/reachable.hpp b/openvpn/apple/reachable.hpp new file mode 100644 index 0000000..abf808a --- /dev/null +++ b/openvpn/apple/reachable.hpp @@ -0,0 +1,468 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . +// +// This code is derived from the Apple sample Reachability.m under +// the following license. +// +// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple +// Inc. ("Apple") in consideration of your agreement to the following +// terms, and your use, installation, modification or redistribution of +// this Apple software constitutes acceptance of these terms. If you do +// not agree with these terms, please do not use, install, modify or +// redistribute this Apple software. +// +// In consideration of your agreement to abide by the following terms, and +// subject to these terms, Apple grants you a personal, non-exclusive +// license, under Apple's copyrights in this original Apple software (the +// "Apple Software"), to use, reproduce, modify and redistribute the Apple +// Software, with or without modifications, in source and/or binary forms; +// provided that if you redistribute the Apple Software in its entirety and +// without modifications, you must retain this notice and the following +// text and disclaimers in all such redistributions of the Apple Software. +// Neither the name, trademarks, service marks or logos of Apple Inc. may +// be used to endorse or promote products derived from the Apple Software +// without specific prior written permission from Apple. Except as +// expressly stated in this notice, no other rights or licenses, express or +// implied, are granted by Apple herein, including but not limited to any +// patent rights that may be infringed by your derivative works or by other +// works in which the Apple Software may be incorporated. +// +// The Apple Software is provided by Apple on an "AS IS" basis. APPLE +// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION +// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND +// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. +// +// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL +// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, +// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED +// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), +// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Copyright (C) 2013 Apple Inc. All Rights Reserved. + +// Wrapper for Apple SCNetworkReachability methods. + +#ifndef OPENVPN_APPLECRYPTO_UTIL_REACHABLE_H +#define OPENVPN_APPLECRYPTO_UTIL_REACHABLE_H + +#import "TargetConditionals.h" + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace openvpn { + namespace CF { + OPENVPN_CF_WRAP(NetworkReachability, network_reachability_cast, SCNetworkReachabilityRef, SCNetworkReachabilityGetTypeID); + } + + class ReachabilityBase + { + public: + typedef ReachabilityInterface::Status Status; + + enum Type { + Internet, + WiFi, + }; + + std::string to_string() const + { + return to_string(flags()); + } + + std::string to_string(const SCNetworkReachabilityFlags f) const + { + const Status s = vstatus(f); + const Type t = vtype(); + + std::string ret; + ret += render_type(t); + ret += ':'; + ret += render_status(s); + ret += '/'; + ret += render_flags(f); + return ret; + } + + Status status() const + { + return vstatus(flags()); + } + + SCNetworkReachabilityFlags flags() const + { + SCNetworkReachabilityFlags f = 0; + if (SCNetworkReachabilityGetFlags(reach(), &f) == TRUE) + return f; + else + return 0; + } + + static std::string render_type(Type type) + { + switch (type) { + case Internet: + return "Internet"; + case WiFi: + return "WiFi"; + default: + return "Type???"; + } + } + + static std::string render_status(const Status status) + { + switch (status) { + case ReachabilityInterface::NotReachable: + return "NotReachable"; + case ReachabilityInterface::ReachableViaWiFi: + return "ReachableViaWiFi"; + case ReachabilityInterface::ReachableViaWWAN: + return "ReachableViaWWAN"; + default: + return "ReachableVia???"; + } + } + + static std::string render_flags(const SCNetworkReachabilityFlags flags) + { + std::string ret; +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR // Mac OS X doesn't define WWAN flags + if (flags & kSCNetworkReachabilityFlagsIsWWAN) + ret += 'W'; + else +#endif + ret += '-'; + if (flags & kSCNetworkReachabilityFlagsReachable) + ret += 'R'; + else + ret += '-'; + ret += ' '; + if (flags & kSCNetworkReachabilityFlagsTransientConnection) + ret += 't'; + else + ret += '-'; + if (flags & kSCNetworkReachabilityFlagsConnectionRequired) + ret += 'c'; + else + ret += '-'; + if (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) + ret += 'C'; + else + ret += '-'; + if (flags & kSCNetworkReachabilityFlagsInterventionRequired) + ret += 'i'; + else + ret += '-'; + if (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) + ret += 'D'; + else + ret += '-'; + if (flags & kSCNetworkReachabilityFlagsIsLocalAddress) + ret += 'l'; + else + ret += '-'; + if (flags & kSCNetworkReachabilityFlagsIsDirect) + ret += 'd'; + else + ret += '-'; + return ret; + } + + virtual Type vtype() const = 0; + virtual Status vstatus(const SCNetworkReachabilityFlags flags) const = 0; + + virtual ~ReachabilityBase() {} + + CF::NetworkReachability reach; + }; + + class ReachabilityViaInternet : public ReachabilityBase + { + public: + ReachabilityViaInternet() + { + struct sockaddr_in addr; + bzero(&addr, sizeof(addr)); + addr.sin_len = sizeof(addr); + addr.sin_family = AF_INET; + reach.reset(SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr*)&addr)); + } + + virtual Type vtype() const + { + return Internet; + } + + virtual Status vstatus(const SCNetworkReachabilityFlags flags) const + { + return status_from_flags(flags); + } + + static Status status_from_flags(const SCNetworkReachabilityFlags flags) + { + if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) + { + // The target host is not reachable. + return ReachabilityInterface::NotReachable; + } + + Status ret = ReachabilityInterface::NotReachable; + + if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) + { + // If the target host is reachable and no connection is required then + // we'll assume (for now) that you're on Wi-Fi... + ret = ReachabilityInterface::ReachableViaWiFi; + } + +#if 0 // don't contaminate result by considering on-demand viability + if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) + { + // ... and the connection is on-demand (or on-traffic) if the + // calling application is using the CFSocketStream or higher APIs... + + if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) + { + // ... and no [user] intervention is needed... + ret = ReachabilityInterface::ReachableViaWiFi; + } + } +#endif + +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR // Mac OS X doesn't define WWAN flags + if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) + { + // ... but WWAN connections are OK if the calling application + // is using the CFNetwork APIs. + ret = ReachabilityInterface::ReachableViaWWAN; + } +#endif + + return ret; + } + }; + + class ReachabilityViaWiFi : public ReachabilityBase + { + public: + ReachabilityViaWiFi() + { + struct sockaddr_in addr; + bzero(&addr, sizeof(addr)); + addr.sin_len = sizeof(addr); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); // 169.254.0.0. + reach.reset(SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr*)&addr)); + } + + virtual Type vtype() const + { + return WiFi; + } + + virtual Status vstatus(const SCNetworkReachabilityFlags flags) const + { + return status_from_flags(flags); + } + + static Status status_from_flags(const SCNetworkReachabilityFlags flags) + { + Status ret = ReachabilityInterface::NotReachable; + if ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) + ret = ReachabilityInterface::ReachableViaWiFi; + return ret; + } + }; + + class Reachability : public ReachabilityInterface + { + public: + Reachability(const bool enable_internet, const bool enable_wifi) + { + if (enable_internet) + internet.reset(new ReachabilityViaInternet); + if (enable_wifi) + wifi.reset(new ReachabilityViaWiFi); + } + + bool reachableViaWiFi() const { + if (internet) + { + if (wifi) + return internet->status() == ReachableViaWiFi && wifi->status() == ReachableViaWiFi; + else + return internet->status() == ReachableViaWiFi; + } + else + { + if (wifi) + return wifi->status() == ReachableViaWiFi; + else + return false; + } + } + + bool reachableViaCellular() const + { + if (internet) + return internet->status() == ReachableViaWWAN; + else + return false; + } + + virtual Status reachable() const + { + if (reachableViaWiFi()) + return ReachableViaWiFi; + else if (reachableViaCellular()) + return ReachableViaWWAN; + else + return NotReachable; + } + + virtual bool reachableVia(const std::string& net_type) const + { + if (net_type == "cellular") + return reachableViaCellular(); + else if (net_type == "wifi") + return reachableViaWiFi(); + else + return reachableViaWiFi() || reachableViaCellular(); + } + + virtual std::string to_string() const + { + std::string ret; + if (internet) + ret += internet->to_string(); + if (internet && wifi) + ret += ' '; + if (wifi) + ret += wifi->to_string(); + return ret; + } + + std::unique_ptr internet; + std::unique_ptr wifi; + }; + + class ReachabilityTracker + { + public: + ReachabilityTracker(const bool enable_internet, const bool enable_wifi) + : reachability(enable_internet, enable_wifi), + scheduled(false) + { + } + + void reachability_tracker_schedule() + { + if (!scheduled) + { + if (reachability.internet) + schedule(*reachability.internet, internet_callback_static); + if (reachability.wifi) + schedule(*reachability.wifi, wifi_callback_static); + scheduled = true; + } + } + + void reachability_tracker_cancel() + { + if (scheduled) + { + if (reachability.internet) + cancel(*reachability.internet); + if (reachability.wifi) + cancel(*reachability.wifi); + scheduled = false; + } + } + + virtual void reachability_tracker_event(const ReachabilityBase& rb, SCNetworkReachabilityFlags flags) = 0; + + virtual ~ReachabilityTracker() + { + reachability_tracker_cancel(); + } + + private: + bool schedule(ReachabilityBase& rb, SCNetworkReachabilityCallBack cb) + { + SCNetworkReachabilityContext context = { 0, this, nullptr, nullptr, nullptr }; + if (rb.reach.defined()) + { + if (SCNetworkReachabilitySetCallback(rb.reach(), + cb, + &context) == FALSE) + return false; + if (SCNetworkReachabilityScheduleWithRunLoop(rb.reach(), + CFRunLoopGetCurrent(), + kCFRunLoopCommonModes) == FALSE) + return false; + return true; + } + else + return false; + } + + void cancel(ReachabilityBase& rb) + { + if (rb.reach.defined()) + SCNetworkReachabilityUnscheduleFromRunLoop(rb.reach(), CFRunLoopGetCurrent(), kCFRunLoopCommonModes); + } + + static void internet_callback_static(SCNetworkReachabilityRef target, + SCNetworkReachabilityFlags flags, + void *info) + { + ReachabilityTracker* self = (ReachabilityTracker*)info; + self->reachability_tracker_event(*self->reachability.internet, flags); + } + + static void wifi_callback_static(SCNetworkReachabilityRef target, + SCNetworkReachabilityFlags flags, + void *info) + { + ReachabilityTracker* self = (ReachabilityTracker*)info; + self->reachability_tracker_event(*self->reachability.wifi, flags); + } + + Reachability reachability; + bool scheduled; + }; +} + +#endif diff --git a/openvpn/apple/scdynstore.hpp b/openvpn/apple/scdynstore.hpp new file mode 100644 index 0000000..647c9fc --- /dev/null +++ b/openvpn/apple/scdynstore.hpp @@ -0,0 +1,52 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLE_SCDYNSTORE_H +#define OPENVPN_APPLE_SCDYNSTORE_H + +#include + +#include + +namespace openvpn { + namespace CF { + OPENVPN_CF_WRAP(DynamicStore, dynamic_store_cast, SCDynamicStoreRef, SCDynamicStoreGetTypeID) + + template + inline RET DynamicStoreCopy(const DynamicStore& ds, const KEY& key) + { + String keystr = string(key); + return RET(RET::cast(SCDynamicStoreCopyValue(ds(), keystr()))); + } + + template + inline Dict DynamicStoreCopyDict(const DynamicStore& ds, const KEY& key) + { + Dict dict = DynamicStoreCopy(ds, key); + if (dict.defined()) + return dict; + else + return CF::empty_dict(); + } + } +} + +#endif diff --git a/openvpn/apple/ver.hpp b/openvpn/apple/ver.hpp new file mode 100644 index 0000000..2e716da --- /dev/null +++ b/openvpn/apple/ver.hpp @@ -0,0 +1,81 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLE_VER_H +#define OPENVPN_APPLE_VER_H + +#include +#include + +#include +#include +#include + +#include +#include + +namespace openvpn { + class AppleVersion + { + public: + int major() const { return ver[0]; } + int minor() const { return ver[1]; } + int build() const { return ver[2]; } + + std::string to_string() const + { + std::ostringstream os; + os << major() << '.' << minor() << '.' << build(); + return os.str(); + } + + protected: + AppleVersion() + { + reset(); + } + + // verstr should be in the form major.minor.build + void init(const std::string& verstr) + { + typedef std::vector StringList; + reset(); + StringList sl; + sl.reserve(3); + Split::by_char_void(sl, verstr, '.'); + for (size_t i = 0; i < 3; ++i) + { + if (i < sl.size()) + parse_number(sl[i], ver[i]); + } + } + + private: + void reset() + { + ver[0] = ver[1] = ver[2] = -1; + } + + int ver[3]; + }; +} + +#endif diff --git a/openvpn/applecrypto/crypto/api.hpp b/openvpn/applecrypto/crypto/api.hpp new file mode 100644 index 0000000..d8147b1 --- /dev/null +++ b/openvpn/applecrypto/crypto/api.hpp @@ -0,0 +1,46 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CRYPTO_API_H +#define OPENVPN_APPLECRYPTO_CRYPTO_API_H + +#include +#include +#include +#include + +namespace openvpn { + + // type container for Apple Crypto-level API + struct AppleCryptoAPI { + // cipher + typedef AppleCrypto::CipherContext CipherContext; + typedef AppleCrypto::CipherContextGCM CipherContextGCM; + + // digest + typedef AppleCrypto::DigestContext DigestContext; + + // HMAC + typedef AppleCrypto::HMACContext HMACContext; + }; +} + +#endif diff --git a/openvpn/applecrypto/crypto/cipher.hpp b/openvpn/applecrypto/crypto/cipher.hpp new file mode 100644 index 0000000..bc686ed --- /dev/null +++ b/openvpn/applecrypto/crypto/cipher.hpp @@ -0,0 +1,201 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Wrap the Apple cipher API defined in so +// that it can be used as part of the crypto layer of the OpenVPN core. + +#ifndef OPENVPN_APPLECRYPTO_CRYPTO_CIPHER_H +#define OPENVPN_APPLECRYPTO_CRYPTO_CIPHER_H + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + namespace AppleCrypto { + class CipherContext + { + CipherContext(const CipherContext&) = delete; + CipherContext& operator=(const CipherContext&) = delete; + + public: + OPENVPN_SIMPLE_EXCEPTION(apple_cipher_mode_error); + OPENVPN_SIMPLE_EXCEPTION(apple_cipher_uninitialized); + OPENVPN_EXCEPTION(apple_cipher_error); + + // mode parameter for constructor + enum { + MODE_UNDEF = -1, + ENCRYPT = kCCEncrypt, + DECRYPT = kCCDecrypt + }; + + enum { + MAX_IV_LENGTH = 16, + CIPH_CBC_MODE = 0 + }; + + CipherContext() + : cinfo(nullptr), cref(nullptr) + { + } + + ~CipherContext() { erase() ; } + + void init(const CryptoAlgs::Type alg, const unsigned char *key, const int mode) + { + erase(); + + // check that mode is valid + if (!(mode == ENCRYPT || mode == DECRYPT)) + throw apple_cipher_mode_error(); + + // initialize cipher context with cipher type + const CCCryptorStatus status = CCCryptorCreate(mode, + cipher_type(alg), + kCCOptionPKCS7Padding, + key, + CryptoAlgs::key_length(alg), + nullptr, + &cref); + if (status != kCCSuccess) + throw CFException("CipherContext: CCCryptorCreate", status); + + cinfo = CryptoAlgs::get_ptr(alg); + } + + void reset(const unsigned char *iv) + { + check_initialized(); + const CCCryptorStatus status = CCCryptorReset(cref, iv); + if (status != kCCSuccess) + throw CFException("CipherContext: CCCryptorReset", status); + } + + bool update(unsigned char *out, const size_t max_out_size, + const unsigned char *in, const size_t in_size, + size_t& out_acc) + { + check_initialized(); + size_t dataOutMoved; + const CCCryptorStatus status = CCCryptorUpdate(cref, in, in_size, out, max_out_size, &dataOutMoved); + if (status == kCCSuccess) + { + out_acc += dataOutMoved; + return true; + } + else + return false; + } + + bool final(unsigned char *out, const size_t max_out_size, size_t& out_acc) + { + check_initialized(); + size_t dataOutMoved; + const CCCryptorStatus status = CCCryptorFinal(cref, out, max_out_size, &dataOutMoved); + if (status == kCCSuccess) + { + out_acc += dataOutMoved; + return true; + } + else + return false; + } + + bool is_initialized() const { return cinfo != nullptr; } + + size_t iv_length() const + { + check_initialized(); + return cinfo->iv_length(); + } + + size_t block_size() const + { + check_initialized(); + return cinfo->block_size(); + } + + // return cipher mode (such as CIPH_CBC_MODE, etc.) + int cipher_mode() const + { + check_initialized(); + return CIPH_CBC_MODE; + } + + private: + static CCAlgorithm cipher_type(const CryptoAlgs::Type alg) + { + switch (alg) + { + case CryptoAlgs::AES_128_CBC: + case CryptoAlgs::AES_192_CBC: + case CryptoAlgs::AES_256_CBC: + case CryptoAlgs::AES_256_CTR: + return kCCAlgorithmAES128; + case CryptoAlgs::DES_CBC: + return kCCAlgorithmDES; + case CryptoAlgs::DES_EDE3_CBC: + return kCCAlgorithm3DES; +#ifdef OPENVPN_PLATFORM_IPHONE + case CryptoAlgs::BF_CBC: + return kCCAlgorithmBlowfish; +#endif + default: + OPENVPN_THROW(apple_cipher_error, CryptoAlgs::name(alg) << ": not usable"); + } + } + + void erase() + { + if (cinfo) + { + if (cref) + CCCryptorRelease(cref); + cref = nullptr; + cinfo = nullptr; + } + } + + void check_initialized() const + { +#ifdef OPENVPN_ENABLE_ASSERT + if (!cinfo) + throw apple_cipher_uninitialized(); +#endif + } + + const CryptoAlgs::Alg* cinfo; + CCCryptorRef cref; + }; + } +} + +#endif diff --git a/openvpn/applecrypto/crypto/digest.hpp b/openvpn/applecrypto/crypto/digest.hpp new file mode 100644 index 0000000..79b7149 --- /dev/null +++ b/openvpn/applecrypto/crypto/digest.hpp @@ -0,0 +1,255 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Wrap the Apple digest API defined in +// so that it can be used as part of the crypto layer of the OpenVPN core. + +#ifndef OPENVPN_APPLECRYPTO_CRYPTO_DIGEST_H +#define OPENVPN_APPLECRYPTO_CRYPTO_DIGEST_H + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define OPENVPN_DIGEST_CONTEXT(TYPE) CC_##TYPE##_CTX TYPE##_ctx + +#define OPENVPN_DIGEST_ALG_CLASS(TYPE) \ + class DigestAlgorithm##TYPE : public DigestAlgorithm \ + { \ + public: \ + DigestAlgorithm##TYPE() {} \ + virtual int init(DigestCTX& ctx) const \ + { \ + return CC_##TYPE##_Init(&ctx.u.TYPE##_ctx); \ + } \ + virtual int update(DigestCTX& ctx, const unsigned char *data, size_t size) const \ + { \ + return CC_##TYPE##_Update(&ctx.u.TYPE##_ctx, data, size); \ + } \ + virtual int final(DigestCTX& ctx, unsigned char *md) const \ + { \ + return CC_##TYPE##_Final(md, &ctx.u.TYPE##_ctx); \ + } \ + } + +#define OPENVPN_DIGEST_ALG_DECLARE(TYPE) const DigestAlgorithm##TYPE alg_##TYPE; + +#define OPENVPN_DIGEST_INFO_DECLARE(TYPE) const DigestInfo info_##TYPE(CryptoAlgs::TYPE, &alg_##TYPE, kCCHmacAlg##TYPE) + +#define OPENVPN_DIGEST_INFO_DECLARE_NO_HMAC(TYPE) const DigestInfo info_##TYPE(CryptoAlgs::TYPE, &alg_##TYPE, DigestInfo::NO_HMAC_ALG) + +namespace openvpn { + namespace AppleCrypto { + typedef CC_SHA256_CTX CC_SHA224_CTX; + typedef CC_SHA512_CTX CC_SHA384_CTX; + + struct DigestCTX { + union { + OPENVPN_DIGEST_CONTEXT(MD4); + OPENVPN_DIGEST_CONTEXT(MD5); + OPENVPN_DIGEST_CONTEXT(SHA1); + OPENVPN_DIGEST_CONTEXT(SHA224); + OPENVPN_DIGEST_CONTEXT(SHA256); + OPENVPN_DIGEST_CONTEXT(SHA384); + OPENVPN_DIGEST_CONTEXT(SHA512); + } u; + }; + + struct DigestAlgorithm { + virtual int init(DigestCTX& ctx) const = 0; + virtual int update(DigestCTX& ctx, const unsigned char *data, size_t size) const = 0; + virtual int final(DigestCTX& ctx, unsigned char *md) const = 0; + }; + + // individual digest algorithm classes (each inherits from DigestAlgorithm) + OPENVPN_DIGEST_ALG_CLASS(MD4); + OPENVPN_DIGEST_ALG_CLASS(MD5); + OPENVPN_DIGEST_ALG_CLASS(SHA1); + OPENVPN_DIGEST_ALG_CLASS(SHA224); + OPENVPN_DIGEST_ALG_CLASS(SHA256); + OPENVPN_DIGEST_ALG_CLASS(SHA384); + OPENVPN_DIGEST_ALG_CLASS(SHA512); + + class DigestInfo + { + public: + enum { + NO_HMAC_ALG = -1 + }; + + DigestInfo(CryptoAlgs::Type type, + const DigestAlgorithm* digest_alg, + const CCHmacAlgorithm hmac_alg) + : type_(type), + digest_alg_(digest_alg), + hmac_alg_(hmac_alg) {} + + CryptoAlgs::Type type() const { return type_; } + const char *name() const { return CryptoAlgs::name(type_); } + size_t size() const { return CryptoAlgs::size(type_); } + const DigestAlgorithm* digest_alg() const { return digest_alg_; } + CCHmacAlgorithm hmac_alg() const { return hmac_alg_; } + + private: + CryptoAlgs::Type type_; + const DigestAlgorithm* digest_alg_; + CCHmacAlgorithm hmac_alg_; + }; + + // instantiate individual digest algorithm class instances (each inherits from DigestAlgorithm), + // naming convention is alg_TYPE + OPENVPN_DIGEST_ALG_DECLARE(MD4); + OPENVPN_DIGEST_ALG_DECLARE(MD5); + OPENVPN_DIGEST_ALG_DECLARE(SHA1); + OPENVPN_DIGEST_ALG_DECLARE(SHA224); + OPENVPN_DIGEST_ALG_DECLARE(SHA256); + OPENVPN_DIGEST_ALG_DECLARE(SHA384); + OPENVPN_DIGEST_ALG_DECLARE(SHA512); + + // instantiate individual digest info class instances (each is a DigestInfo), + // naming convention is info_TYPE + OPENVPN_DIGEST_INFO_DECLARE_NO_HMAC(MD4); + OPENVPN_DIGEST_INFO_DECLARE(MD5); + OPENVPN_DIGEST_INFO_DECLARE(SHA1); + OPENVPN_DIGEST_INFO_DECLARE(SHA224); + OPENVPN_DIGEST_INFO_DECLARE(SHA256); + OPENVPN_DIGEST_INFO_DECLARE(SHA384); + OPENVPN_DIGEST_INFO_DECLARE(SHA512); + + class HMACContext; + + class DigestContext + { + DigestContext(const DigestContext&) = delete; + DigestContext& operator=(const DigestContext&) = delete; + + public: + friend class HMACContext; + + OPENVPN_SIMPLE_EXCEPTION(apple_digest_uninitialized); + OPENVPN_SIMPLE_EXCEPTION(apple_digest_final_overflow); + OPENVPN_EXCEPTION(apple_digest_error); + + enum { + MAX_DIGEST_SIZE = CC_SHA512_DIGEST_LENGTH // largest known is SHA512 + }; + + DigestContext() + { + clear(); + } + + DigestContext(const CryptoAlgs::Type alg) + { + init(alg); + } + + void init(const CryptoAlgs::Type alg) + { + clear(); + info = digest_type(alg); + meth = info->digest_alg(); + if (meth->init(ctx) != 1) + throw apple_digest_error("init"); + initialized = true; + } + + void update(const unsigned char *in, const size_t size) + { + check_initialized(); + if (meth->update(ctx, in, size) != 1) + throw apple_digest_error("update"); + } + + size_t final(unsigned char *out) + { + check_initialized(); + if (meth->final(ctx, out) != 1) + throw apple_digest_error("final"); + return info->size(); + } + + size_t size() const + { + check_initialized(); + return info->size(); + } + + bool is_initialized() const { return initialized; } + + private: + static const DigestInfo *digest_type(const CryptoAlgs::Type alg) + { + switch (alg) + { + case CryptoAlgs::MD4: + return &info_MD4; + case CryptoAlgs::MD5: + return &info_MD5; + case CryptoAlgs::SHA1: + return &info_SHA1; + case CryptoAlgs::SHA224: + return &info_SHA224; + case CryptoAlgs::SHA256: + return &info_SHA256; + case CryptoAlgs::SHA384: + return &info_SHA384; + case CryptoAlgs::SHA512: + return &info_SHA512; + default: + OPENVPN_THROW(apple_digest_error, CryptoAlgs::name(alg) << ": not usable"); + } + } + + void clear() + { + initialized = false; + } + + void check_initialized() const + { +#ifdef OPENVPN_ENABLE_ASSERT + if (!initialized) + throw apple_digest_uninitialized(); +#endif + } + + bool initialized; + const DigestInfo *info; + const DigestAlgorithm *meth; + DigestCTX ctx; + }; + } +} + +#undef OPENVPN_DIGEST_CONTEXT +#undef OPENVPN_DIGEST_ALG_CLASS +#undef OPENVPN_DIGEST_ALG_DECLARE +#undef OPENVPN_DIGEST_INFO_DECLARE + +#endif diff --git a/openvpn/applecrypto/crypto/hmac.hpp b/openvpn/applecrypto/crypto/hmac.hpp new file mode 100644 index 0000000..f53b5f0 --- /dev/null +++ b/openvpn/applecrypto/crypto/hmac.hpp @@ -0,0 +1,145 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_APPLECRYPTO_CRYPTO_HMAC_H +#define OPENVPN_APPLECRYPTO_CRYPTO_HMAC_H + +// Wrap the Apple HMAC API defined in so that +// it can be used as part of the crypto layer of the OpenVPN core. + +#include +#include + +#include + +#include +#include +#include + +namespace openvpn { + namespace AppleCrypto { + class HMACContext + { + HMACContext(const HMACContext&) = delete; + HMACContext& operator=(const HMACContext&) = delete; + + public: + OPENVPN_EXCEPTION(digest_cannot_be_used_with_hmac); + OPENVPN_SIMPLE_EXCEPTION(hmac_uninitialized); + OPENVPN_SIMPLE_EXCEPTION(hmac_keysize_error); + + enum { + MAX_HMAC_SIZE = DigestContext::MAX_DIGEST_SIZE, + MAX_HMAC_KEY_SIZE = 128, + }; + + HMACContext() + { + state = PRE; + } + + HMACContext(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) + { + init(digest, key, key_size); + } + + ~HMACContext() + { + } + + void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) + { + state = PRE; + info = DigestContext::digest_type(digest); + digest_size_ = CryptoAlgs::size(digest); + hmac_alg = info->hmac_alg(); + if (hmac_alg == DigestInfo::NO_HMAC_ALG) + throw digest_cannot_be_used_with_hmac(info->name()); + if (key_size > MAX_HMAC_KEY_SIZE) + throw hmac_keysize_error(); + std::memcpy(key_, key, key_size_ = key_size); + state = PARTIAL; + } + + void reset() // Apple HMAC API is missing reset method, so we have to reinit + { + cond_reset(true); + } + + void update(const unsigned char *in, const size_t size) + { + cond_reset(false); + CCHmacUpdate(&ctx, in, size); + } + + size_t final(unsigned char *out) + { + cond_reset(false); + CCHmacFinal(&ctx, out); + return digest_size_; + } + + size_t size() const + { + if (!is_initialized()) + throw hmac_uninitialized(); + return digest_size_; + } + + bool is_initialized() const + { + return state >= PARTIAL; + } + + private: + void cond_reset(const bool force_init) + { + switch (state) + { + case PRE: + throw hmac_uninitialized(); + case READY: + if (!force_init) + return; + case PARTIAL: + CCHmacInit(&ctx, hmac_alg, key_, key_size_); + state = READY; + } + } + + enum State { + PRE=0, + PARTIAL, + READY + }; + int state; + + const DigestInfo *info; + CCHmacAlgorithm hmac_alg; + size_t key_size_; + size_t digest_size_; + unsigned char key_[MAX_HMAC_KEY_SIZE]; + CCHmacContext ctx; + }; + } +} + +#endif diff --git a/openvpn/applecrypto/ssl/sslctx.hpp b/openvpn/applecrypto/ssl/sslctx.hpp new file mode 100644 index 0000000..699fb0b --- /dev/null +++ b/openvpn/applecrypto/ssl/sslctx.hpp @@ -0,0 +1,493 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Wrap the Apple SSL API as defined in +// so that it can be used as the SSL layer by the OpenVPN core. +// NOTE: not used in production code. + +// Note that the Apple SSL API is missing some functionality (as of +// Mac OS X 10.8) that makes it difficult to use as a drop in replacement +// for OpenSSL or MbedTLS. The biggest issue is that the API doesn't +// allow an SSL context to be built out of PEM-based certificates and +// keys. It requires an "Identity" in the Keychain that was imported +// by the user as a PKCS#12 file. + +#ifndef OPENVPN_APPLECRYPTO_SSL_SSLCTX_H +#define OPENVPN_APPLECRYPTO_SSL_SSLCTX_H + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// An SSL Context is essentially a configuration that can be used +// to generate an arbitrary number of actual SSL connections objects. + +// AppleSSLContext is an SSL Context implementation that uses the +// Mac/iOS SSL library as a backend. + +namespace openvpn { + + // Represents an SSL configuration that can be used + // to instantiate actual SSL sessions. + class AppleSSLContext : public SSLFactoryAPI + { + public: + typedef RCPtr Ptr; + + enum { + MAX_CIPHERTEXT_IN = 64 + }; + + // The data needed to construct an AppleSSLContext. + class Config : public SSLConfigAPI + { + friend class AppleSSLContext; + + public: + typedef RCPtr Ptr; + + Config() {} + + void load_identity(const std::string& subject_match) + { + identity = load_identity_(subject_match); + if (!identity()) + OPENVPN_THROW(ssl_context_error, "AppleSSLContext: identity '" << subject_match << "' undefined"); + } + + virtual SSLFactoryAPI::Ptr new_factory() + { + return SSLFactoryAPI::Ptr(new AppleSSLContext(this)); + } + + virtual void set_mode(const Mode& mode_arg) + { + mode = mode_arg; + } + + virtual const Mode& get_mode() const + { + return mode; + } + + virtual void set_frame(const Frame::Ptr& frame_arg) + { + frame = frame_arg; + } + + virtual void load(const OptionList& opt, const unsigned int lflags) + { + // client/server + if (lflags & LF_PARSE_MODE) + mode = opt.exists("client") ? Mode(Mode::CLIENT) : Mode(Mode::SERVER); + + // identity + { + const std::string& subject_match = opt.get("identity", 1, 256); + load_identity(subject_match); + } + } + + virtual void set_external_pki_callback(ExternalPKIBase* external_pki_arg) + { + not_implemented("set_external_pki_callback"); + } + + virtual void set_private_key_password(const std::string& pwd) + { + return not_implemented("set_private_key_password"); + } + + virtual void load_ca(const std::string& ca_txt, bool strict) + { + return not_implemented("load_ca"); + } + + virtual void load_crl(const std::string& crl_txt) + { + return not_implemented("load_crl"); + } + + virtual void load_cert(const std::string& cert_txt) + { + return not_implemented("load_cert"); + } + + virtual void load_cert(const std::string& cert_txt, const std::string& extra_certs_txt) + { + return not_implemented("load_cert"); + } + + virtual void load_private_key(const std::string& key_txt) + { + return not_implemented("load_private_key"); + } + + virtual void load_dh(const std::string& dh_txt) + { + return not_implemented("load_dh"); + } + + virtual void set_debug_level(const int debug_level) + { + return not_implemented("set_debug_level"); + } + + virtual void set_flags(const unsigned int flags_arg) + { + return not_implemented("set_flags"); + } + + virtual void set_ns_cert_type(const NSCert::Type ns_cert_type_arg) + { + return not_implemented("set_ns_cert_type"); + } + + virtual void set_remote_cert_tls(const KUParse::TLSWebType wt) + { + return not_implemented("set_remote_cert_tls"); + } + + virtual void set_tls_remote(const std::string& tls_remote_arg) + { + return not_implemented("set_tls_remote"); + } + + virtual void set_tls_version_min(const TLSVersion::Type tvm) + { + return not_implemented("set_tls_version_min"); + } + + virtual void set_local_cert_enabled(const bool v) + { + return not_implemented("set_local_cert_enabled"); + } + + virtual void set_enable_renegotiation(const bool v) + { + return not_implemented("set_enable_renegotiation"); + } + + virtual void set_force_aes_cbc_ciphersuites(const bool v) + { + return not_implemented("set_force_aes_cbc_ciphersuites"); + } + + virtual void set_rng(const RandomAPI::Ptr& rng_arg) + { + return not_implemented("set_rng"); + } + + private: + void not_implemented(const char *funcname) + { + OPENVPN_LOG("AppleSSL: " << funcname << " not implemented"); + } + + Mode mode; + CF::Array identity; // as returned by load_identity + Frame::Ptr frame; + }; + + // Represents an actual SSL session. + // Normally instantiated by AppleSSLContext::ssl(). + class SSL : public SSLAPI + { + friend class AppleSSLContext; + + public: + typedef RCPtr Ptr; + + virtual void start_handshake() + { + SSLHandshake(ssl); + } + + virtual ssize_t write_cleartext_unbuffered(const void *data, const size_t size) + { + size_t actual = 0; + const OSStatus status = SSLWrite(ssl, data, size, &actual); + if (status < 0) + { + if (status == errSSLWouldBlock) + return SSLConst::SHOULD_RETRY; + else + throw CFException("AppleSSLContext::SSL::write_cleartext failed", status); + } + else + return actual; + } + + virtual ssize_t read_cleartext(void *data, const size_t capacity) + { + if (!overflow) + { + size_t actual = 0; + const OSStatus status = SSLRead(ssl, data, capacity, &actual); + if (status < 0) + { + if (status == errSSLWouldBlock) + return SSLConst::SHOULD_RETRY; + else + throw CFException("AppleSSLContext::SSL::read_cleartext failed", status); + } + else + return actual; + } + else + throw ssl_ciphertext_in_overflow(); + } + + virtual bool read_cleartext_ready() const + { + // fixme: need to detect data buffered at SSL layer + return !ct_in.empty(); + } + + virtual void write_ciphertext(const BufferPtr& buf) + { + if (ct_in.size() < MAX_CIPHERTEXT_IN) + ct_in.write_buf(buf); + else + overflow = true; + } + + virtual bool read_ciphertext_ready() const + { + return !ct_out.empty(); + } + + virtual BufferPtr read_ciphertext() + { + return ct_out.read_buf(); + } + + virtual std::string ssl_handshake_details() const // fixme -- code me + { + return "[AppleSSL not implemented]"; + } + + virtual const AuthCert::Ptr& auth_cert() const + { + OPENVPN_THROW(ssl_context_error, "AppleSSL::SSL: auth_cert() not implemented"); + } + + ~SSL() + { + ssl_erase(); + } + + private: + SSL(const AppleSSLContext& ctx) + { + ssl_clear(); + try { + OSStatus s; + +#ifdef OPENVPN_PLATFORM_IPHONE + // init SSL object, select client or server mode + if (ctx.mode().is_server()) + ssl = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType); + else if (ctx.mode().is_client()) + ssl = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType); + else + OPENVPN_THROW(ssl_context_error, "AppleSSLContext::SSL: unknown client/server mode"); + if (ssl == nullptr) + throw CFException("SSLCreateContext failed"); + + // use TLS v1 + s = SSLSetProtocolVersionMin(ssl, kTLSProtocol1); + if (s) + throw CFException("SSLSetProtocolVersionMin failed", s); +#else + // init SSL object, select client or server mode + if (ctx.mode().is_server()) + s = SSLNewContext(true, &ssl); + else if (ctx.mode().is_client()) + s = SSLNewContext(false, &ssl); + else + OPENVPN_THROW(ssl_context_error, "AppleSSLContext::SSL: unknown client/server mode"); + if (s) + throw CFException("SSLNewContext failed", s); + + // use TLS v1 + s = SSLSetProtocolVersionEnabled(ssl, kSSLProtocol2, false); + if (s) + throw CFException("SSLSetProtocolVersionEnabled !S2 failed", s); + s = SSLSetProtocolVersionEnabled(ssl, kSSLProtocol3, false); + if (s) + throw CFException("SSLSetProtocolVersionEnabled !S3 failed", s); + s = SSLSetProtocolVersionEnabled(ssl, kTLSProtocol1, true); + if (s) + throw CFException("SSLSetProtocolVersionEnabled T1 failed", s); +#endif + // configure cert, private key, and supporting CAs via identity wrapper + s = SSLSetCertificate(ssl, ctx.identity()()); + if (s) + throw CFException("SSLSetCertificate failed", s); + + // configure ciphertext buffers + ct_in.set_frame(ctx.frame()); + ct_out.set_frame(ctx.frame()); + + // configure the "connection" object to be self + s = SSLSetConnection(ssl, this); + if (s) + throw CFException("SSLSetConnection", s); + + // configure ciphertext read/write callbacks + s = SSLSetIOFuncs(ssl, ct_read_func, ct_write_func); + if (s) + throw CFException("SSLSetIOFuncs failed", s); + } + catch (...) + { + ssl_erase(); + throw; + } + } + + static OSStatus ct_read_func(SSLConnectionRef cref, void *data, size_t *length) + { + try { + SSL *self = (SSL *)cref; + const size_t actual = self->ct_in.read((unsigned char *)data, *length); + const OSStatus ret = (*length == actual) ? 0 : errSSLWouldBlock; + *length = actual; + return ret; + } + catch (...) + { + return errSSLInternal; + } + } + + static OSStatus ct_write_func(SSLConnectionRef cref, const void *data, size_t *length) + { + try { + SSL *self = (SSL *)cref; + self->ct_out.write((const unsigned char *)data, *length); + return 0; + } + catch (...) + { + return errSSLInternal; + } + } + + void ssl_clear() + { + ssl = nullptr; + overflow = false; + } + + void ssl_erase() + { + if (ssl) + { +#ifdef OPENVPN_PLATFORM_IPHONE + CFRelease(ssl); +#else + SSLDisposeContext(ssl); +#endif + } + ssl_clear(); + } + + SSLContextRef ssl; // underlying SSL connection object + MemQStream ct_in; // write ciphertext to here + MemQStream ct_out; // read ciphertext from here + bool overflow; + }; + + /////// start of main class implementation + + // create a new SSL instance + virtual SSLAPI::Ptr ssl() + { + return SSL::Ptr(new SSL(*this)); + } + + // like ssl() above but verify hostname against cert CommonName and/or SubjectAltName + virtual SSLAPI::Ptr ssl(const std::string& hostname) + { + OPENVPN_THROW(ssl_context_error, "AppleSSLContext: ssl session with CommonName and/or SubjectAltName verification not implemented"); + } + + virtual const Mode& mode() const + { + return config_->mode; + } + + private: + AppleSSLContext(Config* config) + : config_(config) + { + if (!config_->identity()) + OPENVPN_THROW(ssl_context_error, "AppleSSLContext: identity undefined"); + } + + const Frame::Ptr& frame() const { return config_->frame; } + const CF::Array& identity() const { return config_->identity; } + + // load an identity from keychain, return as an array that can + // be passed to SSLSetCertificate + static CF::Array load_identity_(const std::string& subj_match) + { + const CF::String label = CF::string(subj_match); + const void *keys[] = { kSecClass, kSecMatchSubjectContains, kSecMatchTrustedOnly, kSecReturnRef }; + const void *values[] = { kSecClassIdentity, label(), kCFBooleanTrue, kCFBooleanTrue }; + const CF::Dict query = CF::dict(keys, values, sizeof(keys)/sizeof(keys[0])); + CF::Generic result; + const OSStatus s = SecItemCopyMatching(query(), result.mod_ref()); + if (!s && result.defined()) + { + const void *asrc[] = { result() }; + return CF::array(asrc, 1); + } + else + return CF::Array(); // not found + } + + Config::Ptr config_; + }; + + typedef AppleSSLContext::Ptr AppleSSLContextPtr; + +} // namespace openvpn + +#endif // OPENVPN_APPLECRYPTO_SSL_SSLCTX_H diff --git a/openvpn/applecrypto/util/rand.hpp b/openvpn/applecrypto/util/rand.hpp new file mode 100644 index 0000000..e026897 --- /dev/null +++ b/openvpn/applecrypto/util/rand.hpp @@ -0,0 +1,78 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Wrap the Apple Cryptographic Random API defined in +// so that it can be used as the primary source of cryptographic entropy by +// the OpenVPN core. + +#ifndef OPENVPN_APPLECRYPTO_UTIL_RAND_H +#define OPENVPN_APPLECRYPTO_UTIL_RAND_H + +#include + +#include + +namespace openvpn { + class AppleRandom : public RandomAPI + { + public: + OPENVPN_EXCEPTION(rand_error_apple); + + typedef RCPtr Ptr; + + AppleRandom(const bool prng) + { + } + + virtual std::string name() const + { + return "AppleRandom"; + } + + // Return true if algorithm is crypto-strength + virtual bool is_crypto() const + { + return true; + } + + // Fill buffer with random bytes + virtual void rand_bytes(unsigned char *buf, size_t size) + { + if (!rndbytes(buf, size)) + throw rand_error_apple("rand_bytes"); + } + + // Like rand_bytes, but don't throw exception. + // Return true on successs, false on fail. + virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) + { + return rndbytes(buf, size); + } + + private: + bool rndbytes(unsigned char *buf, size_t size) + { + return SecRandomCopyBytes(kSecRandomDefault, size, buf) ? false : true; + } + }; +} + +#endif diff --git a/openvpn/asio/asioboundsock.hpp b/openvpn/asio/asioboundsock.hpp new file mode 100644 index 0000000..f116751 --- /dev/null +++ b/openvpn/asio/asioboundsock.hpp @@ -0,0 +1,99 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Asio TCP socket that can be configured so that open() method +// always prebinds the socket to a given local address. Useful +// for TCP clients. + +#ifndef OPENVPN_ASIO_ASIOBOUNDSOCK_H +#define OPENVPN_ASIO_ASIOBOUNDSOCK_H + +#include + +#include +#include +#include + +namespace openvpn { + namespace AsioBoundSocket { + + typedef openvpn_io::basic_stream_socket SocketBase; + + class Socket : public SocketBase + { + public: + explicit Socket(openvpn_io::io_context& io_context) + : SocketBase(io_context) + { + } + + // if port 0, kernel will dynamically allocate free port + void bind_local(const IP::Addr& addr, const unsigned short port=0) + { + bind_local_addr = addr; + bind_local_port = port; + } + + std::string to_string() const + { + std::string ret; + ret.reserve(64); + if (bind_local_addr.defined()) + { + ret += "local=["; + ret += bind_local_addr.to_string(); + ret += "]:"; + ret += openvpn::to_string(bind_local_port); + } + try { + const std::string re = openvpn::to_string(remote_endpoint()); + if (!ret.empty()) + ret += ' '; + ret += "remote="; + ret += re; + } + catch (const std::exception& e) + { + } + return ret; + } + + protected: + virtual void async_connect_post_open(const protocol_type& protocol, openvpn_io::error_code& ec) override + { + if (bind_local_addr.defined()) + { + set_option(openvpn_io::socket_base::reuse_address(true), ec); + if (ec) + return; + bind(openvpn_io::ip::tcp::endpoint(bind_local_addr.to_asio(), bind_local_port), ec); + } + } + + private: + IP::Addr bind_local_addr; + unsigned short bind_local_port = 0; + }; + + } +} + +#endif diff --git a/openvpn/asio/asiocontext.hpp b/openvpn/asio/asiocontext.hpp new file mode 100644 index 0000000..c685ac6 --- /dev/null +++ b/openvpn/asio/asiocontext.hpp @@ -0,0 +1,51 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ASIO_ASIOCONTEXT_H +#define OPENVPN_ASIO_ASIOCONTEXT_H + +#include +#include +#include + +#include + +namespace openvpn { + class AsioContextStore + { + public: + openvpn_io::io_context& new_context(int concurrency_hint) + { + openvpn_io::io_context* ioc = new openvpn_io::io_context(concurrency_hint); + { + std::lock_guard lock(mutex); + contexts.emplace_back(ioc); + } + return *ioc; + } + + private: + std::mutex mutex; + std::vector> contexts; + }; +} + +#endif diff --git a/openvpn/asio/asioerr.hpp b/openvpn/asio/asioerr.hpp new file mode 100644 index 0000000..d0204a4 --- /dev/null +++ b/openvpn/asio/asioerr.hpp @@ -0,0 +1,41 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ASIO_ASIOERR_H +#define OPENVPN_ASIO_ASIOERR_H + +#include + +#include // was: #include + +namespace openvpn { + + // returns a string describing an i/o error code + template + inline std::string errinfo(ErrorCode err) + { + openvpn_io::error_code e(err, openvpn_io::system_category()); + return e.message(); + } + +} + +#endif diff --git a/openvpn/asio/asiopolysock.hpp b/openvpn/asio/asiopolysock.hpp new file mode 100644 index 0000000..d81e309 --- /dev/null +++ b/openvpn/asio/asiopolysock.hpp @@ -0,0 +1,377 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Asio polymorphic socket for handling TCP +// and unix domain sockets. + +#ifndef OPENVPN_ASIO_ASIOPOLYSOCK_H +#define OPENVPN_ASIO_ASIOPOLYSOCK_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) +#include +#elif defined(OPENVPN_POLYSOCK_SUPPORTS_BIND) +#include +#endif + +#ifdef ASIO_HAS_LOCAL_SOCKETS +#include +#endif + +namespace openvpn { + namespace AsioPolySock { + // for shutdown() + enum ShutdownFlags { + SHUTDOWN_SEND = (1<<0), + SHUTDOWN_RECV = (1<<1), + }; + + class Base : public RC + { + public: + typedef RCPtr Ptr; + + virtual void async_send(const openvpn_io::const_buffer& buf, + Function&& callback) = 0; + + virtual void async_receive(const openvpn_io::mutable_buffer& buf, + Function&& callback) = 0; + + virtual std::string remote_endpoint_str() const = 0; + virtual bool remote_ip_port(IP::Addr& addr, unsigned int& port) const = 0; + + virtual void non_blocking(const bool state) = 0; + + virtual void close() = 0; + + virtual void shutdown(const unsigned int flags) {} + + virtual void tcp_nodelay() {} + virtual void set_cloexec() {} + + virtual int native_handle() + { + return -1; + } + +#ifdef ASIO_HAS_LOCAL_SOCKETS + virtual bool peercreds(SockOpt::Creds& cr) + { + return false; + } +#endif + +#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) + virtual bool alt_routing_enabled() + { + return false; + } +#endif + + virtual bool is_open() const = 0; + virtual bool is_local() const = 0; + + size_t index() const { return index_; } + + protected: + Base(const size_t index) + : index_(index) + { + } + + private: + size_t index_; + }; + + struct TCP : public Base + { + typedef RCPtr Ptr; + + TCP(openvpn_io::io_context& io_context, + const size_t index) + : Base(index), + socket(io_context) + { + } + + virtual void async_send(const openvpn_io::const_buffer& buf, + Function&& callback) override + { + socket.async_send(buf, std::move(callback)); + } + + virtual void async_receive(const openvpn_io::mutable_buffer& buf, + Function&& callback) override + { + socket.async_receive(buf, std::move(callback)); + } + +#if !defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) + virtual std::string remote_endpoint_str() const override + { + try { + return "TCP " + openvpn::to_string(socket.remote_endpoint()); + } + catch (const std::exception&) + { + return "TCP"; + } + } +#endif + + virtual bool remote_ip_port(IP::Addr& addr, unsigned int& port) const override + { + try { + addr = IP::Addr::from_asio(socket.remote_endpoint().address()); + port = socket.remote_endpoint().port(); + return true; + } + catch (const std::exception&) + { + return false; + } + } + + virtual void non_blocking(const bool state) override + { + socket.non_blocking(state); + } + + virtual void tcp_nodelay() override + { + socket.set_option(openvpn_io::ip::tcp::no_delay(true)); + } + +#if !defined(OPENVPN_PLATFORM_WIN) + virtual void set_cloexec() override + { + const int fd = socket.native_handle(); + if (fd >= 0) + SockOpt::set_cloexec(fd); + } +#endif + + virtual void shutdown(const unsigned int flags) override + { + if (flags & SHUTDOWN_SEND) + socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send); + else if (flags & SHUTDOWN_RECV) + socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive); + } + + virtual void close() override + { + socket.close(); + } + + virtual bool is_open() const override + { + return socket.is_open(); + } + + virtual bool is_local() const override + { + return false; + } + + virtual int native_handle() override + { + return socket.native_handle(); + } + +#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) + virtual std::string remote_endpoint_str() const override + { + const char *proto = (socket.alt_routing_enabled() ? "TCP ALT " : "TCP "); + return proto + socket.to_string(); + } + + virtual bool alt_routing_enabled() override + { + return socket.alt_routing_enabled(); + } + + AltRouting::Socket socket; +#elif defined(OPENVPN_POLYSOCK_SUPPORTS_BIND) + AsioBoundSocket::Socket socket; +#else + openvpn_io::ip::tcp::socket socket; +#endif + }; + +#ifdef ASIO_HAS_LOCAL_SOCKETS + struct Unix : public Base + { + typedef RCPtr Ptr; + + Unix(openvpn_io::io_context& io_context, + const size_t index) + : Base(index), + socket(io_context) + { + } + + virtual void async_send(const openvpn_io::const_buffer& buf, + Function&& callback) override + { + socket.async_send(buf, std::move(callback)); + } + + virtual void async_receive(const openvpn_io::mutable_buffer& buf, + Function&& callback) override + { + socket.async_receive(buf, std::move(callback)); + } + + virtual std::string remote_endpoint_str() const override + { + return "LOCAL"; + } + + virtual bool remote_ip_port(IP::Addr&, unsigned int&) const override + { + return false; + } + + virtual void non_blocking(const bool state) override + { + socket.non_blocking(state); + } + + virtual bool peercreds(SockOpt::Creds& cr) override + { + return SockOpt::peercreds(socket.native_handle(), cr); + } + + virtual void set_cloexec() override + { + const int fd = socket.native_handle(); + if (fd >= 0) + SockOpt::set_cloexec(fd); + } + +#if !defined(OPENVPN_PLATFORM_MAC) + // shutdown() throws "socket is not connected" exception + // on macos if another side has called close() - this behavior + // breaks communication with agent, and hence disabled + virtual void shutdown(const unsigned int flags) override + { + if (flags & SHUTDOWN_SEND) + socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send); + else if (flags & SHUTDOWN_RECV) + socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive); + } +#endif + + virtual void close() override + { + socket.close(); + } + + virtual bool is_open() const override + { + return socket.is_open(); + } + + virtual bool is_local() const override + { + return true; + } + + virtual int native_handle() override + { + return socket.native_handle(); + } + + openvpn_io::local::stream_protocol::socket socket; + }; +#endif + +#if defined(OPENVPN_PLATFORM_WIN) + struct NamedPipe : public Base + { + typedef RCPtr Ptr; + + NamedPipe(openvpn_io::windows::stream_handle&& handle_arg, + const size_t index) + : Base(index), + handle(std::move(handle_arg)) + { + } + + virtual void async_send(const openvpn_io::const_buffer& buf, + Function&& callback) override + { + handle.async_write_some(buf, std::move(callback)); + } + + virtual void async_receive(const openvpn_io::mutable_buffer& buf, + Function&& callback) override + { + handle.async_read_some(buf, std::move(callback)); + } + + virtual std::string remote_endpoint_str() const override + { + return "NAMED_PIPE"; + } + + virtual bool remote_ip_port(IP::Addr&, unsigned int&) const override + { + return false; + } + + virtual void non_blocking(const bool state) override + { + } + + virtual void close() override + { + handle.close(); + } + + virtual bool is_open() const override + { + return handle.is_open(); + } + + virtual bool is_local() const override + { + return true; + } + + openvpn_io::windows::stream_handle handle; + }; +#endif + } +} + +#endif diff --git a/openvpn/asio/asioresolverres.hpp b/openvpn/asio/asioresolverres.hpp new file mode 100644 index 0000000..627f1cf --- /dev/null +++ b/openvpn/asio/asioresolverres.hpp @@ -0,0 +1,49 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Technologies, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 in the COPYING file. +// If not, see . + +#pragma once + +#include + +#include + +namespace openvpn { + + template + inline std::string asio_resolver_results_to_string(const EPRANGE& endpoint_range) + { + std::string ret; + ret.reserve(64); + bool first = true; + for (const auto &i : endpoint_range) + { + if (!first) + ret += ' '; + ret += '['; + ret += openvpn::to_string(i.endpoint().address()); + ret += "]:"; + ret += openvpn::to_string(i.endpoint().port()); + first = false; + } + return ret; + } + +} diff --git a/openvpn/asio/asiosignal.hpp b/openvpn/asio/asiosignal.hpp new file mode 100644 index 0000000..022c0b9 --- /dev/null +++ b/openvpn/asio/asiosignal.hpp @@ -0,0 +1,104 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// A simple class that allows an arbitrary set of posix signals to be +// associated with an Asio handler. + +#ifndef OPENVPN_ASIO_ASIOSIGNAL_H +#define OPENVPN_ASIO_ASIOSIGNAL_H + +#include + +#include +#include + +namespace openvpn { + + class ASIOSignals : public RC + { + public: + typedef RCPtr Ptr; + + ASIOSignals(openvpn_io::io_context& io_context) + : halt(false), signals_(io_context) {} + + enum { + S_SIGINT = (1<<0), + S_SIGTERM = (1<<1), +#ifndef OPENVPN_PLATFORM_WIN + S_SIGQUIT = (1<<2), + S_SIGHUP = (1<<3), + S_SIGUSR1 = (1<<4), + S_SIGUSR2 = (1<<5), +#endif + }; + + template + void register_signals(SignalHandler stop_handler, unsigned int sigmask = (S_SIGINT|S_SIGTERM)) + { + if (sigmask & S_SIGINT) + signals_.add(SIGINT); + if (sigmask & S_SIGTERM) + signals_.add(SIGTERM); +#ifndef OPENVPN_PLATFORM_WIN + if (sigmask & S_SIGQUIT) + signals_.add(SIGQUIT); + if (sigmask & S_SIGHUP) + signals_.add(SIGHUP); + if (sigmask & S_SIGUSR1) + signals_.add(SIGUSR1); + if (sigmask & S_SIGUSR2) + signals_.add(SIGUSR2); +#endif + signals_.async_wait(stop_handler); + } + + template + void register_signals_all(SignalHandler stop_handler) + { + register_signals(stop_handler, + S_SIGINT + | S_SIGTERM +#ifndef OPENVPN_PLATFORM_WIN + | S_SIGHUP + | S_SIGUSR1 + | S_SIGUSR2 +#endif + ); + } + + void cancel() + { + if (!halt) + { + halt = true; + signals_.cancel(); + } + } + + private: + bool halt; + openvpn_io::signal_set signals_; + }; + +} + +#endif diff --git a/openvpn/asio/asiostop.hpp b/openvpn/asio/asiostop.hpp new file mode 100644 index 0000000..b251841 --- /dev/null +++ b/openvpn/asio/asiostop.hpp @@ -0,0 +1,52 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_ASIO_ASIOSTOP_H +#define OPENVPN_ASIO_ASIOSTOP_H + +#include + +#include + +namespace openvpn { + class AsioStopScope : public Stop::Scope + { + public: + AsioStopScope(openvpn_io::io_context& io_context, + Stop* stop, + std::function&& method) + : Stop::Scope(stop, post_method(io_context, std::move(method))) + { + } + + private: + static std::function post_method(openvpn_io::io_context& io_context, std::function&& method) + { + return [&io_context, method=std::move(method)]() + { + openvpn_io::post(io_context, std::move(method)); + }; + } + }; + +} + +#endif diff --git a/openvpn/asio/asiowork.hpp b/openvpn/asio/asiowork.hpp new file mode 100644 index 0000000..a505b38 --- /dev/null +++ b/openvpn/asio/asiowork.hpp @@ -0,0 +1,44 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// A null Asio unit of work, that prevents the Asio event loop from +// exiting. + +#ifndef OPENVPN_ASIO_ASIOWORK_H +#define OPENVPN_ASIO_ASIOWORK_H + +#include + +namespace openvpn { + class AsioWork + { + public: + AsioWork(openvpn_io::io_context& io_context) + : work(openvpn_io::make_work_guard(io_context)) + { + } + + private: + openvpn_io::executor_work_guard work; + }; +} + +#endif diff --git a/openvpn/asio/scoped_asio_stream.hpp b/openvpn/asio/scoped_asio_stream.hpp new file mode 100644 index 0000000..20f381a --- /dev/null +++ b/openvpn/asio/scoped_asio_stream.hpp @@ -0,0 +1,108 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// A scoped Asio stream that is automatically closed by its destructor. + +#ifndef OPENVPN_ASIO_SCOPED_ASIO_STREAM_H +#define OPENVPN_ASIO_SCOPED_ASIO_STREAM_H + +#include + +namespace openvpn { + + template + class ScopedAsioStream + { + ScopedAsioStream(const ScopedAsioStream&) = delete; + ScopedAsioStream& operator=(const ScopedAsioStream&) = delete; + + public: + typedef STREAM* base_type; + + ScopedAsioStream() : obj_(undefined()) {} + + explicit ScopedAsioStream(STREAM *obj) + : obj_(obj) {} + + static STREAM* undefined() { return nullptr; } + + STREAM* release() + { + STREAM* ret = obj_; + obj_ = nullptr; + //OPENVPN_LOG("**** SAS RELEASE=" << ret); + return ret; + } + + static bool defined_static(STREAM* obj) + { + return obj != nullptr; + } + + bool defined() const + { + return defined_static(obj_); + } + + STREAM* operator()() const + { + return obj_; + } + + void reset(STREAM* obj) + { + close(); + obj_ = obj; + //OPENVPN_LOG("**** SAS RESET=" << obj_); + } + + // unusual semantics: replace obj without closing it first + void replace(STREAM* obj) + { + //OPENVPN_LOG("**** SAS REPLACE " << obj_ << " -> " << obj); + obj_ = obj; + } + + // return false if close error + bool close() + { + if (defined()) + { + //OPENVPN_LOG("**** SAS CLOSE obj=" << obj_); + delete obj_; + obj_ = nullptr; + } + return true; + } + + ~ScopedAsioStream() + { + //OPENVPN_LOG("**** SAS DESTRUCTOR"); + close(); + } + + private: + STREAM* obj_; + }; + +} // namespace openvpn + +#endif diff --git a/openvpn/auth/authcert.hpp b/openvpn/auth/authcert.hpp new file mode 100644 index 0000000..f22021a --- /dev/null +++ b/openvpn/auth/authcert.hpp @@ -0,0 +1,284 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_AUTH_AUTHCERT_H +#define OPENVPN_AUTH_AUTHCERT_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + + class OpenSSLContext; + class MbedTLSContext; + + class AuthCert : public RC + { + public: + // AuthCert needs to friend SSL implementation classes + friend class OpenSSLContext; + friend class MbedTLSContext; + + typedef RCPtr Ptr; + + class Fail + { + public: + // Ordered by severity. If many errors are present, the + // most severe error will be returned by get_code(). + enum Type { + OK=0, // OK MUST be 0 + EXPIRED, // less severe... + BAD_CERT_TYPE, + CERT_FAIL, + SNI_ERROR, // more severe... + N + }; + + void add_fail(const size_t depth, const Type new_code, std::string reason) + { + if (new_code > code) + code = new_code; + while (errors.size() <= depth) + errors.emplace_back(); + std::string& err = errors[depth]; + if (err.empty()) + err = std::move(reason); + else if (err.find(reason) == std::string::npos) + { + err += ", "; + err += reason; + } + } + + bool is_fail() const + { + return code != OK; + } + + Type get_code() const + { + return code; + } + + std::string to_string(const bool use_prefix) const + { + std::string ret; + if (use_prefix) + { + ret += render_code(code); + ret += ": "; + } + bool notfirst = false; + for (size_t i = 0; i < errors.size(); ++i) + { + if (errors[i].empty()) + continue; + if (notfirst) + ret += ", "; + notfirst = true; + ret += errors[i]; + ret += " ["; + ret += openvpn::to_string(i); + ret += ']'; + } + return ret; + } + + static std::string render_code(const Type code) + { + switch (code) + { + case OK: + return "OK"; + case CERT_FAIL: + default: + return "CERT_FAIL"; + case BAD_CERT_TYPE: + return "BAD_CERT_TYPE"; + case EXPIRED: + return "EXPIRED"; + case SNI_ERROR: + return "SNI_ERROR"; + } + } + + private: + Type code{OK}; // highest-valued cert fail code + std::vector errors; // human-readable cert errors by depth + }; + + AuthCert() + { + std::memset(issuer_fp, 0, sizeof(issuer_fp)); + sn = -1; + } + + bool defined() const + { + return sn >= 0; + } + + bool sni_defined() const + { + return !sni.empty(); + } + + bool cn_defined() const + { + return !cn.empty(); + } + + bool is_uninitialized() const + { + return cn.empty() && sn < 0 && !fail; + } + + template + T issuer_fp_prefix() const + { + return bin_prefix(issuer_fp); + } + + bool operator==(const AuthCert& other) const + { + return sni == other.sni && cn == other.cn && sn == other.sn && !std::memcmp(issuer_fp, other.issuer_fp, sizeof(issuer_fp)); + } + + bool operator!=(const AuthCert& other) const + { + return !operator==(other); + } + + std::string to_string() const + { + std::ostringstream os; + if (!sni.empty()) + os << "SNI=" << sni << ' '; + if (sni_metadata) + os << "SNI_CN=" << sni_metadata->sni_client_name(*this) << ' '; + os << "CN=" << cn + << " SN=" << sn + << " ISSUER_FP=" << issuer_fp_str(false); + return os.str(); + } + + std::string issuer_fp_str(const bool openssl_fmt) const + { + if (openssl_fmt) + return render_hex_sep(issuer_fp, sizeof(issuer_fp), ':', true); + else + return render_hex(issuer_fp, sizeof(issuer_fp), false); + } + + std::string normalize_cn() const // remove trailing "_AUTOLOGIN" from AS certs + { + if (string::ends_with(cn, "_AUTOLOGIN")) + return cn.substr(0, cn.length() - 10); + else + return cn; + } + + // Allow sni_metadata object, if it exists, to generate the client name. + // Otherwise fall back to normalize_cn(). + std::string sni_client_name() const + { + if (sni_metadata) + return sni_metadata->sni_client_name(*this); + else + return normalize_cn(); + } + + const std::string& get_sni() const + { + return sni; + } + + const std::string& get_cn() const + { + return cn; + } + + long get_sn() const + { + return sn; + } + + const X509Track::Set* x509_track_get() const + { + return x509_track.get(); + } + + std::unique_ptr x509_track_take_ownership() + { + return std::move(x509_track); + } + + void add_fail(const size_t depth, const Fail::Type new_code, std::string reason) + { + if (!fail) + fail.reset(new Fail()); + fail->add_fail(depth, new_code, std::move(reason)); + } + + bool is_fail() const + { + return fail && fail->is_fail(); + } + + const Fail* get_fail() const + { + return fail.get(); + } + + std::string fail_str() const + { + if (fail) + return fail->to_string(true); + else + return "OK"; + } + + private: + std::string sni; // SNI (server name indication) + std::string cn; // common name + long sn; // serial number + unsigned char issuer_fp[20]; // issuer cert fingerprint + + std::unique_ptr fail; + std::unique_ptr x509_track; + SNI::Metadata::UPtr sni_metadata; + }; +} + +#endif diff --git a/openvpn/auth/authcreds.hpp b/openvpn/auth/authcreds.hpp new file mode 100644 index 0000000..fcc3a4a --- /dev/null +++ b/openvpn/auth/authcreds.hpp @@ -0,0 +1,92 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_AUTH_AUTHCREDS +#define OPENVPN_AUTH_AUTHCREDS + +#include // for std::move +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + + class AuthCreds : public RC + { + public: + typedef RCPtr Ptr; + + AuthCreds(std::string&& username_arg, + SafeString&& password_arg, + const std::string& peer_info_str) + : username(std::move(username_arg)), + password(std::move(password_arg)) + { + peer_info.parse_from_peer_info(peer_info_str, nullptr); + peer_info.update_map(); + } + + bool defined() const + { + return !username.empty(); + } + + bool is_valid_user_pass(const bool strict) const + { + return ValidateCreds::is_valid(ValidateCreds::USERNAME, username, strict) + && ValidateCreds::is_valid(ValidateCreds::PASSWORD, password, strict); + } + + bool is_valid(const bool strict) const + { + return defined() && is_valid_user_pass(strict); + } + + void wipe_password() + { + password.wipe(); + } + + std::string to_string() const + { + std::ostringstream os; + os << "*** AuthCreds ***" << std::endl; + os << "user: '" << username << "'" << std::endl; + os << "pass: (" << password.length() << " chars)" << std::endl; + os << "peer info:" << std::endl; + os << peer_info.render(Option::RENDER_BRACKET|Option::RENDER_NUMBER); + return os.str(); + } + + std::string username; + SafeString password; + OptionList peer_info; + }; + +} + +#endif diff --git a/openvpn/auth/cr.hpp b/openvpn/auth/cr.hpp new file mode 100644 index 0000000..f94bc7d --- /dev/null +++ b/openvpn/auth/cr.hpp @@ -0,0 +1,228 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// Encapsulate the state of a static or dynamic authentication challenge. + +#ifndef OPENVPN_AUTH_CR_H +#define OPENVPN_AUTH_CR_H + +#include +#include +#include + +#include +#include +#include +#include +#include + +// Static Challenge response: +// SCRV1:: +// +// Dynamic Challenge: +// CRV1:::: +// FLAGS is a comma-separated list of options: +// E -- echo +// R -- response required +// +// Dynamic Challenge response: +// Username: [username decoded from username_base64] +// Password: CRV1:::: + +namespace openvpn { + class ChallengeResponse : public RC { + public: + typedef RCPtr Ptr; + + OPENVPN_SIMPLE_EXCEPTION(dynamic_challenge_parse_error); + OPENVPN_SIMPLE_EXCEPTION(static_challenge_parse_error); + + ChallengeResponse() + : echo(false), response_required(false) + { + } + + explicit ChallengeResponse(const std::string& cookie) + : echo(false), response_required(false) + { + init(cookie); + } + + ChallengeResponse(const std::string& cookie, const std::string& user) + : echo(false), response_required(false) + { + if (!is_dynamic(cookie) && cookie.find_first_of(':') == std::string::npos) + { + state_id = cookie; + username = user; + } + else + init(cookie); + } + + void init(const std::string& cookie) + { + typedef std::vector StringList; + StringList sl; + sl.reserve(5); + Split::by_char_void(sl, cookie, ':', 0, 4); + if (sl.size() != 5) + throw dynamic_challenge_parse_error(); + if (sl[0] != "CRV1") + throw dynamic_challenge_parse_error(); + + // parse options + { + StringList opt; + opt.reserve(2); + Split::by_char_void(opt, sl[1], ','); + for (StringList::const_iterator i = opt.begin(); i != opt.end(); ++i) + { + if (*i == "E") + echo = true; + else if (*i == "R") + response_required = true; + } + } + + // save state ID + state_id = sl[2]; + + // save username + try { + username = base64->decode(sl[3]); + } + catch (const Base64::base64_decode_error&) + { + throw dynamic_challenge_parse_error(); + } + + // save challenge + challenge_text = sl[4]; + } + + static bool is_dynamic(const std::string& s) + { + return string::starts_with(s, "CRV1:"); + } + + static bool is_static(const std::string& s) + { + return string::starts_with(s, "SCRV1:"); + } + + static void validate_dynamic(const std::string& cookie) + { + ChallengeResponse cr(cookie); + } + + std::string construct_dynamic_password(const std::string& response) const + { + std::ostringstream os; + os << "CRV1::" << state_id << "::" << response; + return os.str(); + } + + static std::string construct_static_password(const std::string& password, + const std::string& response) + { + std::ostringstream os; + os << "SCRV1:" << base64->encode(password) << ':' << base64->encode(response); + return os.str(); + } + + static void parse_static_cookie(const std::string& cookie, + std::string& password, + std::string& response) + { + typedef std::vector StringList; + StringList sl; + sl.reserve(3); + Split::by_char_void(sl, cookie, ':'); + if (sl.size() != 3) + throw static_challenge_parse_error(); + if (sl[0] != "SCRV1") + throw static_challenge_parse_error(); + + // get password + try { + password = base64->decode(sl[1]); + } + catch (const Base64::base64_decode_error&) + { + throw static_challenge_parse_error(); + } + + // get response + try { + response = base64->decode(sl[2]); + } + catch (const Base64::base64_decode_error&) + { + throw static_challenge_parse_error(); + } + } + + static std::string generate_dynamic_challenge(const std::string& session_token, + const std::string& username, + const std::string& challenge, + const bool echo, + const bool response_required) + { + std::ostringstream os; + bool comma = false; + os << "CRV1:"; + if (echo) + { + if (comma) + os << ","; + os << "E"; + comma = true; + } + if (response_required) + { + if (comma) + os << ","; + os << "R"; + comma = true; + } + os << ':' << session_token; + os << ':' << base64->encode(username); + os << ':' << challenge; + return os.str(); + } + + const std::string& get_state_id() const { return state_id; } + const std::string& get_username() const { return username; } + bool get_echo() const { return echo; } + bool get_response_required() const { return response_required; } + const std::string& get_challenge_text() const { return challenge_text; } + + private: + bool echo; + bool response_required; + std::string state_id; + std::string username; + std::string challenge_text; + }; +} + +#endif diff --git a/openvpn/auth/validatecreds.hpp b/openvpn/auth/validatecreds.hpp new file mode 100644 index 0000000..8a71afc --- /dev/null +++ b/openvpn/auth/validatecreds.hpp @@ -0,0 +1,71 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_AUTH_VALIDATE_CREDS_H +#define OPENVPN_AUTH_VALIDATE_CREDS_H + +#include + +namespace openvpn { + // Validate authentication credential. + // Must be UTF-8. + // Other checks on size and content below. + // We don't check that the credential is non-empty. + namespace ValidateCreds { + + enum Type { + USERNAME, + PASSWORD, + RESPONSE + }; + + template + static bool is_valid(const Type type, const STRING& cred, const bool strict) + { + size_t max_len_flags; + if (strict) + { + // length <= 512 unicode chars, no control chars allowed + max_len_flags = 512 | Unicode::UTF8_NO_CTRL; + } + else + { + switch (type) + { + case USERNAME: + // length <= 512 unicode chars, no control chars allowed + max_len_flags = 512 | Unicode::UTF8_NO_CTRL; + break; + case PASSWORD: + case RESPONSE: + // length <= 16384 unicode chars + max_len_flags = 16384; + break; + default: + return false; + } + } + return Unicode::is_valid_utf8(cred, max_len_flags); + } + } +} + +#endif diff --git a/openvpn/buffer/asiobuf.hpp b/openvpn/buffer/asiobuf.hpp new file mode 100644 index 0000000..10e199f --- /dev/null +++ b/openvpn/buffer/asiobuf.hpp @@ -0,0 +1,56 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_BUFFER_ASIOBUF_H +#define OPENVPN_BUFFER_ASIOBUF_H + +#include + +#include + +namespace openvpn { + class AsioConstBufferSeq2 + { + public: + AsioConstBufferSeq2(const Buffer& b1, const Buffer& b2) + : buf({{b1.c_data(), b1.size()}, + {b2.c_data(), b2.size()}}) + { + } + + // Implement the ConstBufferSequence requirements. + typedef openvpn_io::const_buffer value_type; + typedef const openvpn_io::const_buffer* const_iterator; + const openvpn_io::const_buffer* begin() const { return buf; } + const openvpn_io::const_buffer* end() const { return buf + 2; } + + const size_t size() const + { + return openvpn_io::buffer_size(buf[0]) + + openvpn_io::buffer_size(buf[1]); + } + + private: + const openvpn_io::const_buffer buf[2]; + }; +} + +#endif diff --git a/openvpn/buffer/bufclamp.hpp b/openvpn/buffer/bufclamp.hpp new file mode 100644 index 0000000..0965fbb --- /dev/null +++ b/openvpn/buffer/bufclamp.hpp @@ -0,0 +1,52 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// For debugging, reduce effective buffer size for I/O. +// Enable by defining OPENVPN_BUF_CLAMP_READ and/or OPENVPN_BUF_CLAMP_WRITE + +#ifndef OPENVPN_BUFFER_BUFCLAMP_H +#define OPENVPN_BUFFER_BUFCLAMP_H + +#include + +#include + +namespace openvpn { + inline size_t buf_clamp_read(const size_t size) + { +#ifdef OPENVPN_BUF_CLAMP_READ + return std::min(size, size_t(OPENVPN_BUF_CLAMP_READ)); +#else + return size; +#endif + } + + inline size_t buf_clamp_write(const size_t size) + { +#ifdef OPENVPN_BUF_CLAMP_WRITE + return std::min(size, size_t(OPENVPN_BUF_CLAMP_WRITE)); +#else + return size; +#endif + } +} + +#endif diff --git a/openvpn/buffer/bufcomplete.hpp b/openvpn/buffer/bufcomplete.hpp new file mode 100644 index 0000000..b1df2e8 --- /dev/null +++ b/openvpn/buffer/bufcomplete.hpp @@ -0,0 +1,112 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_BUFFER_BUFCOMPLETE_H +#define OPENVPN_BUFFER_BUFCOMPLETE_H + +#include // for std::uint32_t, uint16_t, uint8_t +#include // for std::min + +#include + +namespace openvpn { + + class BufferComplete + { + public: + /* each advance/get method returns false if message is incomplete */ + + bool advance(size_t size) + { + while (size) + { + if (!fetch_buffer()) + return false; + const size_t s = std::min(size, buf.size()); + buf.advance(s); + size -= s; + } + return true; + } + + // assumes embedded big-endian uint16_t length in the stream + bool advance_string() + { + std::uint8_t h, l; + if (!get(h)) + return false; + if (!get(l)) + return false; + return advance(size_t(h) << 8 | size_t(l)); + } + + bool advance_to_null() + { + std::uint8_t c; + while (get(c)) + { + if (!c) + return true; + } + return false; + } + + bool get(std::uint8_t& c) + { + if (!fetch_buffer()) + return false; + c = buf.pop_front(); + return true; + } + + bool defined() const + { + return buf.defined(); + } + + protected: + void reset_buf(const Buffer& buf_arg) + { + buf = buf_arg; + } + + void reset_buf() + { + buf.reset_content(); + } + + private: + virtual void next_buffer() = 0; + + bool fetch_buffer() + { + if (buf.defined()) + return true; + next_buffer(); + return buf.defined(); + } + + Buffer buf; + }; + +} + +#endif diff --git a/openvpn/buffer/bufcomposed.hpp b/openvpn/buffer/bufcomposed.hpp new file mode 100644 index 0000000..fe93ab7 --- /dev/null +++ b/openvpn/buffer/bufcomposed.hpp @@ -0,0 +1,94 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_BUFFER_BUFCOMPOSED_H +#define OPENVPN_BUFFER_BUFCOMPOSED_H + +#include +#include +#include + +namespace openvpn { + class BufferComposed + { + public: + class Complete : public BufferComplete + { + public: + BufferPtr get() + { +#if 0 // don't include for production + if (iter_defined()) + throw Exception("BufferComposed::Complete: residual data"); +#endif + BufferPtr ret = bc.bv.join(); + bc.bv.clear(); + return ret; + } + + private: + friend class BufferComposed; + + Complete(BufferComposed& bc_arg) + : bc(bc_arg), + iter(bc.bv.cbegin()) + { + next_buffer(); + } + + bool iter_defined() + { + return iter != bc.bv.end(); + } + + virtual void next_buffer() override + { + if (iter_defined()) + reset_buf(**iter++); + else + reset_buf(); + } + + BufferComposed& bc; + BufferVector::const_iterator iter; + }; + + size_t size() const + { + return bv.join_size(); + } + + void put(BufferPtr bp) + { + bv.push_back(std::move(bp)); + } + + Complete complete() + { + return Complete(*this); + } + + private: + BufferVector bv; + }; +} + +#endif diff --git a/openvpn/buffer/buffer.hpp b/openvpn/buffer/buffer.hpp new file mode 100644 index 0000000..30c35b3 --- /dev/null +++ b/openvpn/buffer/buffer.hpp @@ -0,0 +1,911 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +// These templates define the fundamental data buffer classes used by the +// OpenVPN core. Normally OpenVPN uses buffers of unsigned chars, but the +// templatization of the classes would allow buffers of other types to +// be defined. +// +// Fundamentally a buffer is an object with 4 fields: +// +// 1. a pointer to underlying data array +// 2. the capacity of the underlying data array +// 3. an offset into the data array +// 4. the size of the referenced data within the array +// +// The BufferType template is the lowest-level buffer class template. It refers +// to a buffer but without any notion of ownership of the underlying data. +// +// The BufferAllocatedType template is a higher-level template that inherits +// from BufferType but which asserts ownership over the resources of the buffer -- +// for example, it will free the underlying buffer in its destructor. +// +// Since most of the time, we want our buffers to be made out of unsigned chars, +// some typedefs at the end of the file define common instantations for the +// BufferType and BufferAllocatedType templates. +// +// Buffer : a simple buffer of unsigned char without ownership semantics +// ConstBuffer : like buffer but where the data pointed to by the buffer is const +// BufferAllocated : an allocated Buffer with ownership semantics +// BufferPtr : a smart, reference-counted pointer to a BufferAllocated + +#ifndef OPENVPN_BUFFER_BUFFER_H +#define OPENVPN_BUFFER_BUFFER_H + +#include +#include +#include +#include // for std::is_nothrow_move_constructible, std::remove_const + +#ifndef OPENVPN_NO_IO +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef OPENVPN_BUFFER_ABORT +#define OPENVPN_BUFFER_THROW(exc) { std::abort(); } +#else +#define OPENVPN_BUFFER_THROW(exc) { throw BufferException(BufferException::exc); } +#endif + +namespace openvpn { + + // special-purpose exception class for Buffer classes + class BufferException : public std::exception + { + public: + enum Status { + buffer_full, + buffer_headroom, + buffer_underflow, + buffer_overflow, + buffer_offset, + buffer_index, + buffer_const_index, + buffer_push_front_headroom, + buffer_no_reset_impl, + buffer_pop_back, + buffer_set_size, + buffer_range, + }; + + BufferException(Status status) + : status_(status) {} + + Status status() const { return status_; } + + const char *status_string() const + { + switch (status_) + { + case buffer_full: + return "buffer_full"; + case buffer_headroom: + return "buffer_headroom"; + case buffer_underflow: + return "buffer_underflow"; + case buffer_overflow: + return "buffer_overflow"; + case buffer_offset: + return "buffer_offset"; + case buffer_index: + return "buffer_index"; + case buffer_const_index: + return "buffer_const_index"; + case buffer_push_front_headroom: + return "buffer_push_front_headroom"; + case buffer_no_reset_impl: + return "buffer_no_reset_impl"; + case buffer_pop_back: + return "buffer_pop_back"; + case buffer_set_size: + return "buffer_set_size"; + case buffer_range: + return "buffer_range"; + default: + return "buffer_???"; + } + } + + virtual const char* what() const throw() { + return status_string(); + } + virtual ~BufferException() throw() {} + + private: + Status status_; + }; + + template + class BufferAllocatedType; + + template + class BufferType { + template friend class BufferAllocatedType; + + public: + typedef T value_type; + typedef T* type; + typedef const T* const_type; + typedef typename std::remove_const::type NCT; // non-const type + + BufferType() + { + static_assert(std::is_nothrow_move_constructible::value, "class BufferType not noexcept move constructable"); + data_ = nullptr; + offset_ = size_ = capacity_ = 0; + } + + BufferType(T* data, const size_t size, const bool filled) + { + data_ = data; + offset_ = 0; + capacity_ = size; + size_ = filled ? size : 0; + } + + void reserve(const size_t n) + { + if (n > capacity_) + resize(n); + } + + void init_headroom(const size_t headroom) + { + if (headroom > capacity_) + OPENVPN_BUFFER_THROW(buffer_headroom); + offset_ = headroom; + size_ = 0; + } + + void reset_offset(const size_t offset) + { + const size_t size = size_ + offset_ - offset; + if (offset > capacity_ || size > capacity_ || offset + size > capacity_) + OPENVPN_BUFFER_THROW(buffer_offset); + offset_ = offset; + size_ = size; + } + + void reset_size() + { + size_ = 0; + } + + void reset_content() + { + offset_ = size_ = 0; + } + + // std::string compatible methods + const T* c_str() const { return c_data(); } + size_t length() const { return size(); } + + // return a const pointer to start of array + const T* c_data() const { return data_ + offset_; } + + // return a mutable pointer to start of array + T* data() { return data_ + offset_; } + + // return a const pointer to end of array + const T* c_data_end() const { return data_ + offset_ + size_; } + + // return a mutable pointer to end of array + T* data_end() { return data_ + offset_ + size_; } + + // return a const pointer to start of raw data + const T* c_data_raw() const { return data_; } + + // return a mutable pointer to start of raw data + T* data_raw() { return data_; } + + // return size of array in T objects + size_t size() const { return size_; } + + // return raw size of allocated buffer in T objects + size_t capacity() const { return capacity_; } + + // return current offset (headroom) into buffer + size_t offset() const { return offset_; } + + // return true if array is not empty + bool defined() const { return size_ > 0; } + + // return true if data memory is defined + bool allocated() const { return data_ != nullptr; } + + // return true if array is empty + bool empty() const { return !size_; } + + // return the number of additional T objects that can be added before capacity is reached (without considering resize) + size_t remaining(const size_t tailroom = 0) const { + const size_t r = capacity_ - (offset_ + size_ + tailroom); + return r <= capacity_ ? r : 0; + } + + // return the maximum allowable size value in T objects given the current offset (without considering resize) + size_t max_size() const { + const size_t r = capacity_ - offset_; + return r <= capacity_ ? r : 0; + } + + // like max_size, but take tailroom into account + size_t max_size_tailroom(const size_t tailroom) const { + const size_t r = capacity_ - (offset_ + tailroom); + return r <= capacity_ ? r : 0; + } + + // After an external method, operating on the array as + // a mutable unsigned char buffer, has written data to the + // array, use this method to set the array length in terms + // of T objects. + void set_size(const size_t size) + { + if (size > max_size()) + OPENVPN_BUFFER_THROW(buffer_set_size); + size_ = size; + } + + // Increment size (usually used in a similar context + // to set_size such as after mutable_buffer_append). + void inc_size(const size_t delta) + { + set_size(size_ + delta); + } + + // append a T object to array, with possible resize + void push_back(const T& value) + { + if (!remaining()) + resize(offset_ + size_ + 1); + *(data()+size_++) = value; + } + + // append a T object to array, with possible resize + void push_front(const T& value) + { + if (!offset_) + OPENVPN_BUFFER_THROW(buffer_push_front_headroom); + --offset_; + ++size_; + *data() = value; + } + + T pop_back() + { + if (!size_) + OPENVPN_BUFFER_THROW(buffer_pop_back); + return *(data()+(--size_)); + } + + T pop_front() + { + T ret = (*this)[0]; + ++offset_; + --size_; + return ret; + } + + T front() + { + return (*this)[0]; + } + + T back() + { + return (*this)[size_-1]; + } + + // Place a T object after the last object in the + // array, with possible resize to contain it, + // however don't actually change the size of the + // array to reflect the added object. Useful + // for maintaining null-terminated strings. + void set_trailer(const T& value) + { + if (!remaining()) + resize(offset_ + size_ + 1); + *(data()+size_) = value; + } + + void null_terminate() + { + if (empty() || back()) + push_back(0); + } + + void advance(const size_t delta) + { + if (delta > size_) + OPENVPN_BUFFER_THROW(buffer_overflow); + offset_ += delta; + size_ -= delta; + } + + bool contains_null() const + { + const T* end = c_data_end(); + for (const T* p = c_data(); p < end; ++p) + { + if (!*p) + return true; + } + return false; + } + + bool is_zeroed() const + { + const T* end = c_data_end(); + for (const T* p = c_data(); p < end; ++p) + { + if (*p) + return false; + } + return true; + } + + // mutable index into array + T& operator[](const size_t index) + { + if (index >= size_) + OPENVPN_BUFFER_THROW(buffer_index); + return data()[index]; + } + + // const index into array + const T& operator[](const size_t index) const + { + if (index >= size_) + OPENVPN_BUFFER_THROW(buffer_const_index); + return c_data()[index]; + } + + // mutable index into array + T* index(const size_t index) + { + if (index >= size_) + OPENVPN_BUFFER_THROW(buffer_index); + return &data()[index]; + } + + // const index into array + const T* c_index(const size_t index) const + { + if (index >= size_) + OPENVPN_BUFFER_THROW(buffer_const_index); + return &c_data()[index]; + } + + bool operator==(const BufferType& other) const + { + if (size_ != other.size_) + return false; + return std::memcmp(c_data(), other.c_data(), size_) == 0; + } + + bool operator!=(const BufferType& other) const + { + return !(*this == other); + } + +#ifndef OPENVPN_NO_IO + // return a openvpn_io::mutable_buffer object used by + // asio read methods, starting from data() + openvpn_io::mutable_buffer mutable_buffer(const size_t tailroom = 0) + { + return openvpn_io::mutable_buffer(data(), max_size_tailroom(tailroom)); + } + + // return a openvpn_io::mutable_buffer object used by + // asio read methods, starting from data_end() + openvpn_io::mutable_buffer mutable_buffer_append(const size_t tailroom = 0) + { + return openvpn_io::mutable_buffer(data_end(), remaining(tailroom)); + } + + // return a openvpn_io::const_buffer object used by + // asio write methods. + openvpn_io::const_buffer const_buffer() const + { + return openvpn_io::const_buffer(c_data(), size()); + } + + // clamped versions of mutable_buffer(), mutable_buffer_append(), + // and const_buffer() + + openvpn_io::mutable_buffer mutable_buffer_clamp(const size_t tailroom = 0) + { + return openvpn_io::mutable_buffer(data(), buf_clamp_read(max_size_tailroom(tailroom))); + } + + openvpn_io::mutable_buffer mutable_buffer_append_clamp(const size_t tailroom = 0) + { + return openvpn_io::mutable_buffer(data_end(), buf_clamp_read(remaining(tailroom))); + } + + openvpn_io::const_buffer const_buffer_clamp() const + { + return openvpn_io::const_buffer(c_data(), buf_clamp_write(size())); + } + + openvpn_io::const_buffer const_buffer_limit(const size_t limit) const + { + return openvpn_io::const_buffer(c_data(), std::min(buf_clamp_write(size()), limit)); + } +#endif + + void realign(size_t headroom) + { + if (headroom != offset_) + { + if (headroom + size_ > capacity_) + OPENVPN_BUFFER_THROW(buffer_headroom); + std::memmove(data_ + headroom, data_ + offset_, size_); + offset_ = headroom; + } + } + + void write(const T* data, const size_t size) + { + std::memcpy(write_alloc(size), data, size * sizeof(T)); + } + + void write(const void* data, const size_t size) + { + write((const T*)data, size); + } + + void prepend(const T* data, const size_t size) + { + std::memcpy(prepend_alloc(size), data, size * sizeof(T)); + } + + void prepend(const void* data, const size_t size) + { + prepend((const T*)data, size); + } + + void read(NCT* data, const size_t size) + { + std::memcpy(data, read_alloc(size), size * sizeof(T)); + } + + void read(void* data, const size_t size) + { + read((NCT*)data, size); + } + + T* write_alloc(const size_t size) + { + if (size > remaining()) + resize(offset_ + size_ + size); + T* ret = data() + size_; + size_ += size; + return ret; + } + + T* prepend_alloc(const size_t size) + { + if (size <= offset_) + { + offset_ -= size; + size_ += size; + return data(); + } + else + OPENVPN_BUFFER_THROW(buffer_headroom); + } + + T* read_alloc(const size_t size) + { + if (size <= size_) + { + T* ret = data(); + offset_ += size; + size_ -= size; + return ret; + } + else + OPENVPN_BUFFER_THROW(buffer_underflow); + } + + BufferType read_alloc_buf(const size_t size) + { + if (size <= size_) + { + BufferType ret(data_, offset_, size, capacity_); + offset_ += size; + size_ -= size; + return ret; + } + else + OPENVPN_BUFFER_THROW(buffer_underflow); + } + + void reset(const size_t min_capacity, const unsigned int flags) + { + if (min_capacity > capacity_) + reset_impl(min_capacity, flags); + } + + void reset(const size_t headroom, const size_t min_capacity, const unsigned int flags) + { + reset(min_capacity, flags); + init_headroom(headroom); + } + + template + void append(const B& other) + { + write(other.c_data(), other.size()); + } + + BufferType range(size_t offset, size_t len) const + { + if (offset + len > size()) + { + if (offset < size()) + len = size() - offset; + else + len = 0; + } + return BufferType(datac(), offset, len, len); + } + + protected: + BufferType(T* data, const size_t offset, const size_t size, const size_t capacity) + : data_(data), offset_(offset), size_(size), capacity_(capacity) + { + } + + // return a mutable pointer to start of array but + // remain const with respect to *this. + T* datac() const { return data_ + offset_; } + + // Called when reset method needs to expand the buffer size + virtual void reset_impl(const size_t min_capacity, const unsigned int flags) + { + OPENVPN_BUFFER_THROW(buffer_no_reset_impl); + } + + // Derived classes can implement buffer growing semantics + // by overloading this method. In the default implementation, + // buffers are non-growable, so we throw an exception. + virtual void resize(const size_t new_capacity) + { + if (new_capacity > capacity_) + { + OPENVPN_BUFFER_THROW(buffer_full); + } + } + + T* data_; // pointer to data + size_t offset_; // offset from data_ of beginning of T array (to allow for headroom) + size_t size_; // number of T objects in array starting at data_ + offset_ + size_t capacity_; // maximum number of array objects of type T for which memory is allocated, starting at data_ + }; + + template + class BufferAllocatedType : public BufferType, public RC + { + using BufferType::data_; + using BufferType::offset_; + using BufferType::size_; + using BufferType::capacity_; + + template friend class BufferAllocatedType; + + public: + enum { + CONSTRUCT_ZERO = (1<<0), // if enabled, constructors/init will zero allocated space + DESTRUCT_ZERO = (1<<1), // if enabled, destructor will zero data before deletion + GROW = (1<<2), // if enabled, buffer will grow (otherwise buffer_full exception will be thrown) + ARRAY = (1<<3), // if enabled, use as array + }; + + BufferAllocatedType() + { + static_assert(std::is_nothrow_move_constructible::value, "class BufferAllocatedType not noexcept move constructable"); + flags_ = 0; + } + + BufferAllocatedType(const size_t capacity, const unsigned int flags) + { + flags_ = flags; + capacity_ = capacity; + if (capacity) + { + data_ = new T[capacity]; + if (flags & CONSTRUCT_ZERO) + std::memset(data_, 0, capacity * sizeof(T)); + if (flags & ARRAY) + size_ = capacity; + } + } + + BufferAllocatedType(const T* data, const size_t size, const unsigned int flags) + { + flags_ = flags; + size_ = capacity_ = size; + if (size) + { + data_ = new T[size]; + std::memcpy(data_, data, size * sizeof(T)); + } + } + + BufferAllocatedType(const BufferAllocatedType& other) + { + offset_ = other.offset_; + size_ = other.size_; + capacity_ = other.capacity_; + flags_ = other.flags_; + if (capacity_) + { + data_ = new T[capacity_]; + if (size_) + std::memcpy(data_ + offset_, other.data_ + offset_, size_ * sizeof(T)); + } + } + + template + BufferAllocatedType(const BufferType& other, const unsigned int flags) + { + static_assert(sizeof(T) == sizeof(T_), "size inconsistency"); + offset_ = other.offset_; + size_ = other.size_; + capacity_ = other.capacity_; + flags_ = flags; + if (capacity_) + { + data_ = new T[capacity_]; + if (size_) + std::memcpy(data_ + offset_, other.data_ + offset_, size_ * sizeof(T)); + } + } + + void operator=(const BufferAllocatedType& other) + { + if (this != &other) + { + offset_ = size_ = 0; + if (capacity_ != other.capacity_) + { + erase_(); + if (other.capacity_) + data_ = new T[other.capacity_]; + capacity_ = other.capacity_; + } + offset_ = other.offset_; + size_ = other.size_; + flags_ = other.flags_; + if (size_) + std::memcpy(data_ + offset_, other.data_ + offset_, size_ * sizeof(T)); + } + } + + void init(const size_t capacity, const unsigned int flags) + { + offset_ = size_ = 0; + flags_ = flags; + if (capacity_ != capacity) + { + erase_(); + if (capacity) + { + data_ = new T[capacity]; + } + capacity_ = capacity; + } + if ((flags & CONSTRUCT_ZERO) && capacity) + std::memset(data_, 0, capacity * sizeof(T)); + if (flags & ARRAY) + size_ = capacity; + } + + void init(const T* data, const size_t size, const unsigned int flags) + { + offset_ = size_ = 0; + flags_ = flags; + if (size != capacity_) + { + erase_(); + if (size) + data_ = new T[size]; + capacity_ = size; + } + size_ = size; + std::memcpy(data_, data, size * sizeof(T)); + } + + void realloc(const size_t newcap) + { + if (newcap > capacity_) + realloc_(newcap); + } + + void reset(const size_t min_capacity, const unsigned int flags) + { + if (min_capacity > capacity_) + init (min_capacity, flags); + } + + void reset(const size_t headroom, const size_t min_capacity, const unsigned int flags) + { + reset(min_capacity, flags); + BufferType::init_headroom(headroom); + } + + template + void move(BufferAllocatedType& other) + { + if (data_) + delete_(data_, capacity_, flags_); + move_(other); + } + + RCPtr> move_to_ptr() + { + RCPtr> bp = new BufferAllocatedType(); + bp->move(*this); + return bp; + } + + void swap(BufferAllocatedType& other) + { + std::swap(data_, other.data_); + std::swap(offset_, other.offset_); + std::swap(size_, other.size_); + std::swap(capacity_, other.capacity_); + std::swap(flags_, other.flags_); + } + + template + BufferAllocatedType(BufferAllocatedType&& other) noexcept + { + move_(other); + } + + BufferAllocatedType& operator=(BufferAllocatedType&& other) noexcept + { + move(other); + return *this; + } + + void clear() + { + erase_(); + flags_ = 0; + size_ = offset_ = 0; + } + + void or_flags(const unsigned int flags) + { + flags_ |= flags; + } + + void and_flags(const unsigned int flags) + { + flags_ &= flags; + } + + ~BufferAllocatedType() + { + if (data_) + delete_(data_, capacity_, flags_); + } + + protected: + // Called when reset method needs to expand the buffer size + virtual void reset_impl(const size_t min_capacity, const unsigned int flags) + { + init(min_capacity, flags); + } + + // Set current capacity to at least new_capacity. + virtual void resize(const size_t new_capacity) + { + const size_t newcap = std::max(new_capacity, capacity_ * 2); + if (newcap > capacity_) + { + if (flags_ & GROW) + realloc_(newcap); + else + OPENVPN_BUFFER_THROW(buffer_full); + } + } + + void realloc_(const size_t newcap) + { + T* data = new T[newcap]; + if (size_) + std::memcpy(data + offset_, data_ + offset_, size_ * sizeof(T)); + delete_(data_, capacity_, flags_); + data_ = data; + //std::cout << "*** RESIZE " << capacity_ << " -> " << newcap << std::endl; // fixme + capacity_ = newcap; + } + + template + void move_(BufferAllocatedType& other) + { + data_ = other.data_; + offset_ = other.offset_; + size_ = other.size_; + capacity_ = other.capacity_; + flags_ = other.flags_; + + other.data_ = nullptr; + other.offset_ = other.size_ = other.capacity_ = 0; + } + + void erase_() + { + if (data_) + { + delete_(data_, capacity_, flags_); + data_ = nullptr; + } + capacity_ = 0; + } + + static void delete_(T* data, const size_t size, const unsigned int flags) + { + if (size && (flags & DESTRUCT_ZERO)) + std::memset(data, 0, size * sizeof(T)); + delete [] data; + } + + unsigned int flags_; + }; + + // specializations of BufferType for unsigned char + typedef BufferType Buffer; + typedef BufferType ConstBuffer; + typedef BufferAllocatedType BufferAllocated; + typedef RCPtr BufferPtr; + + // BufferAllocated with thread-safe refcount + typedef BufferAllocatedType BufferAllocatedTS; + typedef RCPtr BufferPtrTS; + + // cast BufferType to BufferType + + template + inline BufferType& const_buffer_ref(BufferType& src) + { + return (BufferType&)src; + } + + template + inline const BufferType& const_buffer_ref(const BufferType& src) + { + return (const BufferType&)src; + } + +} // namespace openvpn + +#endif // OPENVPN_BUFFER_BUFFER_H diff --git a/openvpn/buffer/bufhex.hpp b/openvpn/buffer/bufhex.hpp new file mode 100644 index 0000000..9f1c60b --- /dev/null +++ b/openvpn/buffer/bufhex.hpp @@ -0,0 +1,61 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_BUFFER_BUFHEX_H +#define OPENVPN_BUFFER_BUFHEX_H + +#include +#include +#include + +namespace openvpn { + namespace BufHex { + + OPENVPN_EXCEPTION(buf_hex); + + template + inline std::string render(const T obj) + { + const ConstBuffer buf((const unsigned char *)&obj, sizeof(obj), true); + return render_hex_generic(buf); + } + + template + inline T parse(const std::string& hex, const std::string& title) + { + T obj; + Buffer buf((unsigned char *)&obj, sizeof(obj), false); + try { + parse_hex(buf, hex); + } + catch (const BufferException& e) + { + OPENVPN_THROW(buf_hex, title << ": buffer issue: " << e.what()); + } + if (buf.size() != sizeof(obj)) + OPENVPN_THROW(buf_hex, title << ": unexpected size"); + return obj; + } + + } +} + +#endif diff --git a/openvpn/buffer/buflimit.hpp b/openvpn/buffer/buflimit.hpp new file mode 100644 index 0000000..51dce84 --- /dev/null +++ b/openvpn/buffer/buflimit.hpp @@ -0,0 +1,92 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_BUFFER_BUFLIMIT_H +#define OPENVPN_BUFFER_BUFLIMIT_H + +#include + +namespace openvpn { + + template + class BufferLimit + { + public: + BufferLimit() + { + set_max(0, 0); + reset(); + } + + BufferLimit(const T max_lines_arg, + const T max_bytes_arg) + { + set_max(max_lines_arg, max_bytes_arg); + reset(); + } + + void set_max(const T max_lines_arg, + const T max_bytes_arg) + { + max_lines = max_lines_arg; + max_bytes = max_bytes_arg; + } + + void reset() + { + n_bytes = n_lines = 0; + } + + void add(const Buffer& buf) + { + T size = (T)buf.size(); + n_bytes += size; + if (max_bytes && n_bytes > max_bytes) + bytes_exceeded(); + if (max_lines) + { + const unsigned char *p = buf.c_data(); + while (size--) + { + const unsigned char c = *p++; + if (c == '\n') + { + ++n_lines; + if (n_lines > max_lines) + lines_exceeded(); + } + } + } + } + + virtual void bytes_exceeded() = 0; + virtual void lines_exceeded() = 0; + + protected: + T max_lines; + T max_bytes; + T n_bytes; + T n_lines; + }; + +} + +#endif diff --git a/openvpn/buffer/buflineiter.hpp b/openvpn/buffer/buflineiter.hpp new file mode 100644 index 0000000..5fa6d13 --- /dev/null +++ b/openvpn/buffer/buflineiter.hpp @@ -0,0 +1,58 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include + +namespace openvpn { + + // Iterate over the lines in a buffer by returning + // a sub-buffer for each line. Zero-copy. + class BufferLineIterator + { + public: + BufferLineIterator(const ConstBuffer& buf) + : src(buf) + { + } + + // Returns a zero-length buffer at end of iteration + ConstBuffer next() + { + return src.read_alloc_buf(line_len()); + } + + private: + size_t line_len() const + { + const unsigned char *const data = src.c_data(); + size_t i = 0; + while (i < src.size()) + if (data[i++] == '\n') + break; + return i; + } + + ConstBuffer src; + }; + +} diff --git a/openvpn/buffer/buflist.hpp b/openvpn/buffer/buflist.hpp new file mode 100644 index 0000000..6a1fe07 --- /dev/null +++ b/openvpn/buffer/buflist.hpp @@ -0,0 +1,122 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#ifndef OPENVPN_BUFFER_BUFLIST_H +#define OPENVPN_BUFFER_BUFLIST_H + +#include +#include + +#include +#include + +namespace openvpn { + + template