├── .clang-format ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .gitignore ├── .pre-commit-config.yaml ├── 3rd_party_deps.yml ├── AUTHOR.adoc ├── CODE_OF_CONDUCT.adoc ├── CONTRIBUTING.adoc ├── Doxyfile ├── DoxygenLayout.xml ├── EXPRESSVPN_CLA.adoc ├── Earthfile ├── LICENSE ├── README.adoc ├── SECURITY.adoc ├── android.yml ├── android └── android_env.sh ├── cmake └── apple.cmake ├── customdoxygen.css ├── docs ├── antora.yml └── modules │ └── ROOT │ └── pages │ ├── design_overview.adoc │ ├── faq.adoc │ ├── intro.adoc │ └── life_packet.adoc ├── include ├── he.h └── he_plugin.h ├── ios.yml ├── ios ├── Lightway │ ├── Lightway.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Lightway.xcscheme │ ├── Lightway │ │ ├── Info.plist │ │ └── Lightway.h │ └── build-xcframework.sh └── autotools-ios-helper.sh ├── linux.yml ├── linux_386.yml ├── linux_arm.yml ├── linux_arm64.yml ├── linux_arm_no_pqc.yml ├── linux_multithread.yml ├── linux_riscv64.yml ├── macos.yml ├── macos_arm64.yml ├── project.yml ├── public ├── he.h ├── he_plugin.h └── stats_plugin.h ├── python ├── .gitignore ├── README.md ├── c-header.tx ├── make_header.py ├── make_public_header.sh └── test │ ├── fixture_public_test.h │ └── test.h ├── src └── he │ ├── client.c │ ├── client.h │ ├── config.c │ ├── config.h │ ├── conn.c │ ├── conn.h │ ├── conn_internal.h │ ├── core.c │ ├── core.h │ ├── flow.c │ ├── flow.h │ ├── frag.c │ ├── frag.h │ ├── he_internal.h │ ├── memory.c │ ├── memory.h │ ├── msg_handlers.c │ ├── msg_handlers.h │ ├── mss.c │ ├── mss.h │ ├── network.c │ ├── network.h │ ├── plugin_chain.c │ ├── plugin_chain.h │ ├── plugin_stats.c │ ├── plugin_stats.h │ ├── pmtud.c │ ├── pmtud.h │ ├── ssl_ctx.c │ ├── ssl_ctx.h │ ├── utils.c │ ├── utils.h │ ├── wolf.c │ └── wolf.h ├── test ├── he │ ├── test_client.c │ ├── test_config.c │ ├── test_conn.c │ ├── test_conn_connect.c │ ├── test_core.c │ ├── test_flow.c │ ├── test_frag.c │ ├── test_memory.c │ ├── test_msg_handlers.c │ ├── test_mss.c │ ├── test_network.c │ ├── test_plugin_chain.c │ ├── test_plugin_stats.c │ ├── test_pmtud.c │ ├── test_ssl_ctx.c │ ├── test_utils.c │ └── test_wolf.c └── support │ ├── .gitkeep │ ├── fake_dispatch.h │ ├── fake_rng.h │ ├── test_defs.h │ └── wolfssl_testable_types.h ├── tvos.yml ├── unix.yml ├── windows.yml ├── windows ├── ceedling32.bat ├── ceedling64.bat ├── ceedlingarm64.bat ├── wolfssl-user_settings-32.h ├── wolfssl-user_settings-64.h ├── wolfssl-user_settings-arm-64.h ├── wolfssl-user_settings-common.h ├── wolfssl-user_settings-multithread.h └── wolfssl.vcxproj ├── windows_32.yml ├── windows_64.yml ├── windows_64_multithread.yml ├── windows_arm64.yml └── wolfssl ├── .gitkeep ├── 0001-CVPN-1945-Lower-max-mtu-for-DTLS-1.3-handshake-message.patch ├── 0002-fix-apple-native-cert-validation.patch ├── 0003-use-proper-warnings-on-MSVC.patch ├── 0004-mlkem-codepoint-backward-compatible.patch └── 0005-fix-dn-check-apple-native-cert-validation.patch /.clang-format: -------------------------------------------------------------------------------- 1 | # Google was the closest style to what was currently being used 2 | BasedOnStyle: Google 3 | # SortIncludes can be re-enabled after tidying up various includes 4 | # but to avoid breaking stuff, leaving it disabled for now 5 | SortIncludes: false 6 | # Because 80 characters just doesn't make sense on a 4K screen and 7 | # the Linux kernel uses 100 8 | ColumnLimit: 100 9 | # Personal preference 10 | DerivePointerAlignment: false 11 | PointerAlignment: Right 12 | SpaceBeforeParens: Never 13 | # Be consistent in all function definitions 14 | AllowShortFunctionsOnASingleLine: false 15 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Global rule: 2 | * @expressvpn/expressvpn-lightway-codeowners 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Expected Behavior 4 | 5 | 6 | 7 | ## Current Behavior 8 | 9 | 10 | 11 | ## Possible Solution 12 | 13 | 14 | 15 | ## Steps to Reproduce (for bugs) 16 | 17 | 18 | 1. 19 | 2. 20 | 3. 21 | 4. 22 | 23 | ## Context 24 | 25 | 26 | 27 | ## Your Environment 28 | 29 | * Version used: 30 | * Operating System and version: 31 | * Link to your project: -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Motivation and Context 7 | 8 | 9 | 10 | ## How Has This Been Tested? 11 | 12 | 13 | 14 | 15 | ## Types of changes 16 | 17 | - [ ] Bug fix (non-breaking change which fixes an issue) 18 | - [ ] New feature (non-breaking change which adds functionality) 19 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 20 | 21 | ## Checklist: 22 | 23 | 24 | - [ ] My code follows the code style of this project. 25 | - [ ] My change requires a change to the documentation. 26 | - [ ] I have updated the documentation accordingly. 27 | - [ ] All active GitHub checks are passing 28 | - [ ] The correct base branch is being used, if not `main` -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | third_party/ 3 | .clangd/ 4 | 5 | # macOS 6 | .DS_Store 7 | /.build 8 | /Packages 9 | /*.xcodeproj 10 | xcuserdata/ 11 | 12 | # The following are created by Doxygen 13 | html/ 14 | latex/ 15 | 16 | # Python files 17 | __pycache__ 18 | .tox/ 19 | .coverage 20 | .hypothesis/ 21 | .mypy_cache/ 22 | .pytest_cache/ 23 | test-results/ 24 | .pybuild/ 25 | .hypothesis/ 26 | .vagrant/ 27 | *.egg-info/ 28 | *.pyc 29 | venv 30 | .python-version 31 | # 32 | 33 | # Artifacts created by Earthly 34 | artifacts/ 35 | 36 | # vscode files 37 | .vscode/ 38 | 39 | .ruby-version 40 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: local 3 | hooks: 4 | - id: clang-format 5 | name: clang-format 6 | entry: clang-format -i 7 | language: system 8 | exclude: test/mocks 9 | types_or: ["c", "c++"] 10 | -------------------------------------------------------------------------------- /3rd_party_deps.yml: -------------------------------------------------------------------------------- 1 | :environment: 2 | - :HE_WOLFSSL_SOURCE: https://github.com/wolfSSL/wolfssl 3 | - :HE_WOLFSSL_TAG: v5.8.0-stable 4 | - :HE_WOLFSSL_CONF_FLAGS: >- 5 | --disable-benchmark 6 | --disable-dh 7 | --disable-examples 8 | --disable-oldtls 9 | --disable-shared 10 | --enable-sys-ca-certs 11 | --disable-dilithium 12 | --enable-aes-bitsliced 13 | --enable-curve25519 14 | --enable-dtls 15 | --enable-dtls13 16 | --enable-dtls-frag-ch 17 | --enable-dtls-mtu 18 | --enable-secure-renegotiation 19 | --enable-singlethreaded 20 | --enable-sni 21 | --enable-sp=yes,4096 22 | --enable-static 23 | --enable-tls13 24 | --enable-experimental 25 | --enable-sha3 26 | --enable-kyber=all,original,ml-kem 27 | -------------------------------------------------------------------------------- /AUTHOR.adoc: -------------------------------------------------------------------------------- 1 | Designed and created by Peter Membrey at ExpressVPN 2 | 3 | *Core Team* 4 | 5 | * David WF (Lead engineer) 6 | * Pete M (Architect and engineer) 7 | 8 | *Core Team Alumni* 9 | 10 | * Blake L (Engineer) 11 | 12 | *Engineers* 13 | 14 | * Tom L 15 | * Raihaan M 16 | * Shaun S 17 | 18 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.adoc: -------------------------------------------------------------------------------- 1 | = Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. 6 | 7 | Examples of unacceptable behavior by participants include: 8 | 9 | * The use of sexualized language or imagery 10 | * Personal attacks 11 | * Trolling or insulting/derogatory comments 12 | * Public or private harassment 13 | * Publishing others' private information, such as physical or electronic addresses, without explicit permission 14 | * Other unethical or unprofessional conduct. 15 | 16 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. 17 | 18 | This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior in ExpressVPN may be reported by contacting ExpressVPN via opensource-conduct@expressvpn.com. 21 | 22 | This Code of Conduct is adapted from the Contributor Covenant (http://contributor-covenant.org), version 1.2.0, available at http://contributor-covenant.org/version/1/2/0/ 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.adoc: -------------------------------------------------------------------------------- 1 | = Contributing 2 | 3 | Contributions are made to this repo via Issues and Pull Requests (PRs). A few general guidelines that cover both: 4 | 5 | - To report security vulnerabilities, please see section on link:SECURITY.adoc#reporting-a-vulnerability[Reporting a vulnerability] 6 | - Search for existing Issues and PRs before creating your own. 7 | - We work hard to makes sure issues are handled in a timely manner but, depending on the impact, it could take a while to investigate the root cause. A friendly ping in the comment thread to the submitter or a contributor can help draw attention if your issue is blocking. 8 | 9 | == Code of Conduct 10 | 11 | Please refer to link:CODE_OF_CONDUCT.adoc[Code of Conduct] for details. 12 | 13 | == Issues 14 | 15 | Issues should be used to report problems with the library, request a new feature, or to discuss potential changes before a PR is created. When you create a new Issue, you will see a template that will guide you to provide the information we need to investigate. 16 | 17 | If you find an Issue that addresses the problem you're having, please add your own reproduction information to the existing issue rather than creating a new one. Adding a https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/[reaction] can also help indicate to our maintainers that a particular problem is affecting more than just the reporter. 18 | 19 | == Pull Requests 20 | 21 | PRs to our libraries are always welcome and can be a quick way to get your fix or improvement slated for the next release. In general, PRs should: 22 | 23 | - Only fix/add the functionality in question **OR** address wide-spread whitespace/style issues, not both 24 | - Add unit or integration tests for fixed or changed functionality (if a test suite already exists) 25 | - Address a single concern in the least number of changed lines as possible 26 | - Include documentation in the repo 27 | - Be accompanied by a complete Pull Request template (loaded automatically when a PR is created) 28 | 29 | For changes that address core functionality or would require breaking changes (e.g. a major release), we recommend opening an Issue to discuss your proposal first. This is not required but can save time creating and reviewing changes. 30 | 31 | In general, we follow the https://github.com/susam/gitpr["fork-and-pull" Git workflow] 32 | 33 | . Fork the repository to your own Github account 34 | . Clone the project to your machine 35 | . Create a branch locally with a succinct but descriptive name 36 | . Commit changes to the branch 37 | . Following any formatting and testing guidelines specific to this repo 38 | . Push changes to your fork 39 | . Open a PR in our repository and follow the PR template so that we can efficiently review the changes. 40 | 41 | 42 | == CLA 43 | 44 | === Individual 45 | 46 | All contributions must indicate agreement to the link:EXPRESSVPN_CLA.adoc[ExpressVPN Individual Contributor License Agreement] by logging into GitHub via the CLA assistant and signing the provided CLA. The CLA assistant will automatically notify the PRs that require CLA signing. 47 | -------------------------------------------------------------------------------- /EXPRESSVPN_CLA.adoc: -------------------------------------------------------------------------------- 1 | = ExpressVPN Individual Contributor License Agreement 2 | 3 | _2021-08-06_ 4 | 5 | Express VPN International Ltd. Software Grant and Contributor License Agreement (“*Agreement*”) 6 | 7 | Thank you for your interest in contributing to an Express VPN International Ltd. (“*ExpressVPN*”) project. To clarify the intellectual property rights in the project and any Contributions, ExpressVPN requires that You accept this Contributor License Agreement. This license is for Your protection as a contributor as well as the protection of ExpressVPN, recipients of software distributed or made available by ExpressVPN, and other contributors; it does not change your rights to use your own Contributions for any other purpose. 8 | 9 | You accept and agree to the following terms and conditions for Your present, and future Contributions submitted to ExpressVPN. Except for the licenses granted herein to ExpressVPN and the recipients of software distributed or made available by ExpressVPN, You reserve all right, title, and interest in and to Your Contributions. 10 | 11 | 1. Definitions. 12 | + 13 | "*You*" (or "*Your*") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with ExpressVPN. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "*control*" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | + 15 | "*Contribution*" shall mean the code, documentation or other original works of authorship, invention or improvement, including any modifications or additions to an existing work, that is intentionally submitted by You to ExpressVPN for inclusion in, or documentation of, any of the projects owned or managed by ExpressVPN (the "*Work*"). For the purposes of this definition, "*submitted*" means any form of electronic, verbal, or written communication sent to ExpressVPN or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, ExpressVPN for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 16 | + 17 | 2. *Grant of Copyright License*. Subject to the terms and conditions of this Agreement, You hereby grant to ExpressVPN and the recipients of software distributed or made available by ExpressVPN a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, make available, and distribute Your Contributions and such derivative works, as well as the right to sublicense and have sublicensed, through multiple tiers of sublicensees, all of the foregoing rights. 18 | 19 | 3. *Grant of Patent License*. Subject to the terms and conditions of this Agreement, You hereby grant to ExpressVPN and the recipients of software distributed or made available by ExpressVPN a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work and Your Contributions, as well as the right to sublicense and have sublicensed, through multiple tiers of sublicensees, all of the foregoing rights where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contributions alone or by combination of Your Contributions with the Work to which such Contributions were submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that any of Your Contributions, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed (“Defensive Patent Termination”), provided that the terms under which such instituting entity obtained any such patent license provide notice of this Defensive Patent Termination. 20 | 21 | 4. You represent that You are legally entitled to grant the above license. If any third party (such as your employer(s)) has rights to any portion of any of Your Contributions, you represent that such third party has authorized your submission of such Contributions or that such third party has waived such rights for such Contributions. 22 | 23 | 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions of work that is not Your original creation). 24 | 25 | 6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, and except for the representations and warranties elsewhere in this Agreement, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. 26 | 27 | 7. Should You wish to submit, along with any of Your Contributions, work that is not Your original creation (“Third Party Work”), You represent that You have sufficient rights in such Third Party Work to make the submission and may submit it to ExpressVPN separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) and conspicuously marking the work as "Submitted on behalf of a third-party: [named here] and licensed pursuant to: [license name]" (substituting the bracketed text with the applicable information). 28 | 29 | 8. You agree to notify ExpressVPN of any facts or circumstances of which you become aware that would make the representations contained herein inaccurate in any respect. 30 | 31 | 9. Your Contribution and any personal information contained therein and otherwise provided to ExpressVPN may be maintained indefinitely and may be redistributed or made available consistent with this Agreement. The personal information you provide will be maintained in accordance with ExpressVPN’s privacy policy. 32 | -------------------------------------------------------------------------------- /Earthfile: -------------------------------------------------------------------------------- 1 | VERSION 0.8 2 | ARG distro=bullseye 3 | FROM --platform=linux/amd64 debian:$distro-slim 4 | WORKDIR /libhelium 5 | 6 | debian-deps: 7 | RUN apt-get update 8 | RUN apt-get -y install --no-install-recommends build-essential git automake m4 libtool-bin cmake ruby-full python3-pip 9 | # Not including colrm seems to give an error when configuring wolfssl 10 | RUN apt-get -y install --no-install-recommends bsdmainutils 11 | RUN gem install ceedling -v 0.31.1 --no-user-install 12 | RUN apt-get -y install --no-install-recommends gcovr 13 | 14 | libhelium-deps: 15 | FROM +debian-deps 16 | # Copy in the build configs 17 | COPY *.yml . 18 | # Make the directory structure so that the config can be parsed 19 | # To improve caching we want to separate this out as the WolfSSL dependency 20 | # fetch and build are the slowest parts of the process. 21 | RUN mkdir -p src include test/support third_party/wolfssl 22 | # Copy the patch files 23 | COPY --dir wolfssl ./ 24 | # Build and fetch the dependencies 25 | RUN ceedling dependencies:make project:linux 26 | 27 | build: 28 | FROM +libhelium-deps 29 | # Copy in the source and include files 30 | COPY --dir src include ./ 31 | # Generate the release 32 | RUN ceedling release project:linux 33 | # Store the artifacts 34 | SAVE ARTIFACT build/release/libhelium.a ./libhelium.a AS LOCAL ./artifacts/libhelium.a 35 | SAVE ARTIFACT build/artifacts/compile_commands.json AS LOCAL ./artifacts/compile_commands.json 36 | 37 | test-copy: 38 | FROM +build 39 | COPY --dir test ./ 40 | 41 | test: 42 | FROM +test-copy 43 | # Run the tests 44 | RUN ceedling test project:linux 45 | SAVE ARTIFACT build/artifacts/compile_commands.json AS LOCAL ./artifacts/compile_commands.json 46 | 47 | coverage: 48 | FROM +test-copy 49 | # Generate code coverage 50 | RUN ceedling gcov:all utils:gcov project:linux 51 | SAVE ARTIFACT build/artifacts/gcov/*.html AS LOCAL ./artifacts/code_coverage/html/ 52 | SAVE ARTIFACT build/artifacts/gcov/*.xml AS LOCAL ./artifacts/code_coverage/xml/ 53 | 54 | compile-commands: 55 | FROM +build 56 | # Copy and write out the compile_commands.json for IDE code completion support 57 | COPY +build/compile_commands.json . 58 | SAVE ARTIFACT compile_commands.json AS LOCAL compile_commands.json 59 | 60 | all: 61 | BUILD +test 62 | BUILD +coverage 63 | BUILD +build 64 | 65 | clean: 66 | LOCALLY 67 | RUN echo "Deleting build directories..." 68 | RUN rm -rf build third_party/builds 69 | 70 | install-precommit: 71 | LOCALLY 72 | RUN echo "Installing pre-commit configs..." 73 | RUN python3 -m venv venv 74 | RUN venv/bin/python -m pip install pre-commit 75 | RUN venv/bin/pre-commit install 76 | 77 | format: 78 | LOCALLY 79 | RUN git ls-files '**/*.c' '**/*.h' | grep -v -E '/mock_.*\.[ch]$$' | xargs clang-format -i -style=file 80 | 81 | public-header: 82 | LOCALLY 83 | RUN echo "Generating public header..." 84 | RUN python3 -m venv venv 85 | RUN venv/bin/python -m pip install textx 86 | RUN cd python && PATH=../venv/bin:/usr/bin:$PATH ./make_public_header.sh && mv he.h ../public/he.h 87 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Lightway Core 2 | 3 | Lightway Core is a modern VPN protocol by ExpressVPN, to deliver a VPN experience that’s faster, more secure, and more reliable. 4 | 5 | == ExpressVPN 6 | 7 | One of the world’s largest providers of VPN services, ExpressVPN enables users 8 | to protect their privacy and security online with just a few clicks. The 9 | company’s award-winning apps for Windows, Mac, iOS, Android, Linux, routers, 10 | and browsers secure user information and identities with best-in-class 11 | encryption and leak-proofing. 12 | 13 | For more information please visit https://www.expressvpn.com. 14 | 15 | == About Lightway Core 16 | 17 | Lightway Core is a small, multi-platform C library that provides the 18 | foundational components of a virtual private network (VPN). 19 | 20 | Lightway Core is the technology that powers Lightway, ExpressVPN’s pioneering 21 | new VPN protocol, built for an always-on world. It makes your VPN experience 22 | speedier, more secure, and more reliable than ever. Designed to be light on its 23 | feet, Lightway runs faster, uses less battery, and is easier to audit and 24 | maintain. 25 | 26 | Note: Lightway Core may be referred to by the internal project name, libhelium, 27 | in the source code. 28 | 29 | == Development Environment 30 | 31 | This project uses https://pre-commit.com/[pre-commit] to enforce code standards. 32 | 33 | To install pre-commit, run: `earthly +install-precommit`. 34 | 35 | == Build and Run (Earthly) 36 | 37 | The simplest way to build the static library for Linux, and run all tests is to use Earthly, which runs the build in a containerised environment. 38 | 39 | [source,bash] 40 | earthly +all 41 | 42 | == Build and Run (Ceedling) 43 | 44 | . Install ceedling gem somewhere on your path. We only support ceedling v0.31.1 as v1.0.0 has some breaking changes. 45 | + 46 | [source,bash] 47 | gem install ceedling -v 0.31.1 48 | 49 | . Windows only: Start git-bash (or similar) via a `Developer Command Prompt for VS 2019` for all subsequent commands 50 | 51 | . Build and run tests, $PLATFORM is `[linux|macos|windows]` 52 | + 53 | [source,bash] 54 | ceedling test project:$PLATFORM 55 | 56 | . Build lib for release 57 | + 58 | [source,bash] 59 | ceedling release project:$PLATFORM 60 | 61 | == Documentation 62 | 63 | Documentation for Lightway Core can be found at https://lightway.com/docs. We use https://antora.org/[Antora] to generate this documentation. The source code can be found in this repository at `+docs/modules/ROOT/pages+`. 64 | 65 | API documentation, generated by https://doxygen.nl[Doxygen], can be found at https://lightway.com/doxygen/annotated.html. 66 | 67 | == Contributing 68 | 69 | We appreciate feedback and contribution to this repository! Before you get started, please see link:CONTRIBUTING.adoc[CONTRIBUTING] 70 | 71 | 72 | == Reporting a vulnerability 73 | 74 | To report security vulnerabilities, please see section on link:SECURITY.adoc#reporting-a-vulnerability[Reporting a vulnerability] 75 | 76 | == Acknowledgments 77 | 78 | We rely on the following projects to build Lightway Core: 79 | 80 | * Ceedling - https://github.com/ThrowTheSwitch/Ceedling 81 | * Earthly - https://github.com/earthly/earthly 82 | * WolfSSL - https://github.com/wolfSSL/wolfssl 83 | 84 | === Preferred Languages 85 | 86 | We prefer all communications to be in English. 87 | 88 | == License 89 | This project is licensed under the 90 | https://www.gnu.org/licenses/gpl-2.0.html[GNU General Public License, version 2.] 91 | -------------------------------------------------------------------------------- /SECURITY.adoc: -------------------------------------------------------------------------------- 1 | = Security 2 | 3 | == Reporting a vulnerability 4 | 5 | ExpressVPN takes the security of its applications and services seriously. 6 | We encourage you to submit any security-related issues to our bug bounty 7 | program. 8 | 9 | === How to Submit a Report 10 | 11 | Researchers should submit their reports through 12 | https://bugcrowd.com/expressvpn[Bugcrowd]. Alternatively, we also accept 13 | submissions by email to security@expressvpn.com. 14 | 15 | *Please note:* ExpressVPN uses Bugcrowd to manage all bug bounty programs. 16 | Submitting via email means that we will share your email address and share 17 | content with Bugcrowd for the purposes of triage, even if you aren’t a member 18 | of the platform. 19 | -------------------------------------------------------------------------------- /android.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for android 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_build 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :environment: 19 | - C_EXTRA_FLAGS= -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DFP_MAX_BITS=8192 -fomit-frame-pointer -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -DWOLFSSL_ML_KEM_USE_OLD_IDS 20 | - LIBS=-llog -landroid 21 | :build: 22 | - git apply ../../wolfssl/*.patch 23 | - autoreconf -i 24 | - ./configure $CROSS_OPTS C_EXTRA_FLAGS="$C_EXTRA_FLAGS" --prefix=$(pwd)/../builds/wolfssl_build $HE_WOLFSSL_CONF_FLAGS --disable-crypttests 25 | - make 26 | - make install 27 | :artifacts: 28 | :includes: 29 | - include 30 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 31 | :static_libraries: 32 | - lib/libwolfssl.a 33 | -------------------------------------------------------------------------------- /android/android_env.sh: -------------------------------------------------------------------------------- 1 | export APILEVEL=21 2 | export ANDROID_NDK_VERSION=${ANDROID_NDK_VERSION:-"23.2.8568313"} 3 | export ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT:-"${HOME}/Library/Android/sdk"} 4 | export ANDROID_NDK_HOME=${ANDROID_NDK_HOME:-"${ANDROID_SDK_ROOT}/ndk/${ANDROID_NDK_VERSION}"} 5 | export DEFAULT_CPP_FLAGS="-DANDROID -D_ANDROID -D__ANDROID__" 6 | export DEFAULT_FLAGS="-fPIC" 7 | 8 | case $OSTYPE in 9 | darwin*) 10 | export TOOLCHAIN="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/darwin-x86_64/bin/" 11 | ;; 12 | linux*) 13 | export TOOLCHAIN="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/" 14 | ;; 15 | esac 16 | 17 | if [ -z "$1" ]; then 18 | echo "Android arch not provided!" 19 | exit 1 20 | fi 21 | 22 | case $1 in 23 | armeabi-v7a ) 24 | export CHOST=armv7a-linux-androideabi 25 | export ARCH_FLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -O3" 26 | export ARCH=armeabi-v7a 27 | export CONFIGURE_PLATFORM="android-arm" 28 | ARCH_OPTS="--enable-sp-asm" 29 | ;; 30 | arm64-v8a ) 31 | export CHOST=aarch64-linux-android 32 | export ARCH_FLAGS="-march=armv8-a+crypto -O3" 33 | export ARCH=arm64-v8a 34 | export CONFIGURE_PLATFORM="android-arm64" 35 | ARCH_OPTS="--enable-armasm" 36 | ;; 37 | x86 ) 38 | export CHOST=i686-linux-android 39 | export ARCH_FLAGS="-march=i686 -msse3 -m32 -O3" 40 | export ARCH=x86 41 | export CONFIGURE_PLATFORM="android-x86" 42 | ARCH_OPTS="" 43 | ;; 44 | x86_64 ) 45 | export CHOST=x86_64-linux-android 46 | export ARCH_FLAGS="-march=x86-64 -msse4.2 -mpopcnt -m64 -O3" 47 | export ARCH=x86_64 48 | export CONFIGURE_PLATFORM="android64-x86_64" 49 | ARCH_OPTS="--enable-sp-asm" 50 | ;; 51 | esac 52 | 53 | export API_PREFIX=${TOOLCHAIN}${CHOST}${APILEVEL} 54 | export SYSROOT="${ANDROID_NDK_HOME}/sysroot/" 55 | 56 | export CFLAGS="-isystem ${SYSROOT} ${ARCH_FLAGS} ${DEFAULT_FLAGS}" 57 | export CXXFLAGS="-isystem ${SYSROOT} ${ARCH_FLAGS} ${DEFAULT_FLAGS}" 58 | export CPPFLAGS="${DEFAULT_CPP_FLAGS}" 59 | 60 | export CPP="${API_PREFIX}-clang -E" 61 | export CC="${API_PREFIX}-clang" 62 | export CXX="${API_PREFIX}-clang++" 63 | export LD="${TOOLCHAIN}ld" 64 | export AS="${API_PREFIX}-as" 65 | export AR="${TOOLCHAIN}llvm-ar" 66 | export RANLIB="${TOOLCHAIN}llvm-ranlib" 67 | export STRIP="${TOOLCHAIN}llvm-strip" 68 | export OBJDUMP="${TOOLCHAIN}llvm-objdump" 69 | 70 | CONFIG_OPTS=() 71 | CONFIG_OPTS+=("--host=${CHOST}") 72 | CONFIG_OPTS+=($ARCH_OPTS) 73 | 74 | export CROSS_OPTS=${CONFIG_OPTS[@]} 75 | -------------------------------------------------------------------------------- /docs/antora.yml: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # Lightway Core 4 | # Copyright (C) 2021 Express VPN International Ltd. 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | # 20 | name: lightway-core 21 | title: Lightway Core 22 | version: 1.0.0 23 | start_page: intro.adoc 24 | -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/design_overview.adoc: -------------------------------------------------------------------------------- 1 | //// 2 | Lightway Core 3 | Copyright (C) 2021 Express VPN International Ltd. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | //// 19 | = Design Overview 20 | 21 | lightway-core is a small, multi-platform, pure C library that encapsulates the 22 | encryption and processing of IP packets. 23 | 24 | On its own, lightway-core is not an executable application. Instead, it is a 25 | *purposefully* simple library. Intentionally, lightway-core is opinionated 26 | about how it works and the scope it controls, and very agnostic about 27 | everything else. The core use case of this library is as part of a 28 | high-performance, always-on VPN application, which necessarily entails 29 | deferring items like "how do I actually send UDP packets?" to the host 30 | application, which can use the best API for the platform, be it a Windows 31 | desktop or an iPhone. 32 | 33 | == Terminology 34 | 35 | Some people may prefer to see these terms in context, see <> 36 | 37 | Inside:: 38 | Refers to data that will be wrapped or has already been unwrapped by lightway-core. 39 | Outside:: 40 | Refers to data wrapped by lightway-core 41 | SSL Context:: 42 | lightway-core attributes that may be shared across multiple connections 43 | Connection:: 44 | lightway-core attributes that reflect a single wrapped data path between a client and server. 45 | 46 | == What does it actually do? 47 | 48 | At a very high-level, once a connection is established, lightway-core provides a bidirectional pathway for wrapping data in a way that can be securely sent over the internet. 49 | 50 | One direction is the "inside path". The host application passes data to lightway-core for wrapping, and then lightway-core will call the host application's ``outside_write_cb`` one or more times with the appropriately encrypted data, which the host is then responsible for transmitting appropriately.footnote:[Where "appropriately" normally means "send these packets over the internet, client->server or server->client depending on which side of the connection we are on."] 51 | 52 | The other direction is the "outside path". The host application passes data wrapped by lightway-core to the appropriate library function; lightway-core will then call the host application's ``inside_write_cb`` one or more times with the appropriately unwrapped data, which the host can then deliver appropriately. 53 | 54 | Of course, the devil is in the details, and there are a lot of details here. 55 | 56 | == Where to next? 57 | 58 | * xref:life_packet.adoc[] 59 | * lightway-core Wire Protocol (Coming Soon) 60 | * lightway-core Msg Protocol (Coming Soon) 61 | * lightway-core Connection Lifecycle (Coming Soon) 62 | -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/intro.adoc: -------------------------------------------------------------------------------- 1 | //// 2 | Lightway Core 3 | Copyright (C) 2021 Express VPN International Ltd. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | //// 19 | = {page-component-title} 20 | 21 | == Overview 22 | 23 | lightway-core is a small, multi-platform C library that provides the 24 | foundational components of a virtual private network (VPN). 25 | 26 | lightway-core is the technology that powers Lightway, ExpressVPN's pioneering 27 | new VPN protocol, built for an always-on world. It makes your VPN experience 28 | speedier, more secure, and more reliable than ever. Designed to be light on its 29 | feet, Lightway runs faster, uses less battery, and is easier to audit and 30 | maintain. 31 | 32 | == Documentation 33 | 34 | * xref:faq.adoc[] 35 | * xref:design_overview.adoc[] 36 | * User Guide (Coming Soon) 37 | * https://lightway.com/doxygen/annotated.html[API Documentation (Doxygen)] 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/modules/ROOT/pages/life_packet.adoc: -------------------------------------------------------------------------------- 1 | //// 2 | Lightway Core 3 | Copyright (C) 2021 Express VPN International Ltd. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | //// 19 | = Life of a Packet 20 | 21 | Here we are going to consider the lifecycle of a single request-response cycle for a simple ping, and the layers it flows through logically. Then, we will show the function call flow for lightway-core specifically. 22 | 23 | For the purposes of clarity, we are going to presume the common use case of a "tun device" created on the client and server that takes all packets placed on that device and sends them to the listening client. This is an extremely common VPN setup but "tun devices" are not part of lightway-core and all lightway-core is responsible for is wrapping packets. 24 | 25 | == Life of a Packet 26 | 27 | .Client->Server 28 | [mermaid,life-packet,svg] 29 | ---- 30 | sequenceDiagram 31 | ping->>tun: ping 32 | tun->>Client: New packet 33 | Client->>lightway-core: wrap inside packet 34 | lightway-core->>wolfSSL: encrypt message 35 | wolfSSL->>lightway-core: encrypted message 36 | lightway-core->>Client: wrapped packet 37 | Client->>Server: lightway packet 38 | Note left of Server: across the internet 39 | Server->>Client: lightway packet 40 | Client->>lightway-core: unwrap outside packet 41 | lightway-core->>wolfSSL: decrypt message 42 | wolfSSL->lightway-core: decrypted message 43 | lightway-core->>Client: unwrapped packet 44 | Client->>tun: New packet 45 | tun->>ping: pong 46 | ---- 47 | 48 | .Server->External 49 | [mermaid,life-packet,svg] 50 | ---- 51 | sequenceDiagram 52 | Client->>Server: lightway packet 53 | Server->>lightway-core: unwrap outside packet 54 | lightway-core->>wolfSSL: decrypt message 55 | wolfSSL->lightway-core: decrypted message 56 | lightway-core->>Server: unwrapped packet 57 | Server->>tun: New packet 58 | tun->>External: ping 59 | External->>tun: pong 60 | tun->>Server: New packet 61 | Server->>lightway-core: wrap inside packet 62 | lightway-core->>wolfSSL: encrypt message 63 | wolfSSL->>lightway-core: encrypted message 64 | lightway-core->>Server: wrapped packet 65 | Server->>Client: lightway packet 66 | ---- 67 | 68 | -------------------------------------------------------------------------------- /include/he_plugin.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file he_plugin.h 22 | * @brief The internal plugin API definitions. 23 | * 24 | * This file is separated out to clearly indicate that a plugin implementation only needs to care 25 | * about this API, not the full set of types and functions included. 26 | */ 27 | 28 | #ifndef HE_PLUGIN_H 29 | #define HE_PLUGIN_H 30 | 31 | #include 32 | #include 33 | 34 | /** 35 | * All possible return code for a helium plugin 36 | */ 37 | typedef enum he_plugin_return_code { 38 | HE_PLUGIN_SUCCESS = 0, 39 | HE_PLUGIN_FAIL = -1, 40 | HE_PLUGIN_DROP = -2, 41 | } he_plugin_return_code_t; 42 | 43 | /** 44 | * @brief The prototype for the ingress function of a helium plugin 45 | * @param packet A pointer to the packet data 46 | * @param length A pointer to the length of the packet data. If the packet size changed after 47 | * processed by this function, the `length` will be set to the new length of the packet data. 48 | * @param capacity The length of the underlying buffer for packet 49 | * @param data A pointer to the context data of the helium plugin 50 | * @return HE_SUCCESS All plugins executed successfully 51 | * @return HE_ERR_PLUGIN_DROP A plugin marked this packet for a drop 52 | * @return HE_ERR_FAILED An error occurred processing this packet 53 | * @note The content of packet may be modified, grow or shrunk, depending on the registered plugins 54 | */ 55 | typedef he_plugin_return_code_t (*plugin_do_ingress)(uint8_t *packet, size_t *length, 56 | size_t capacity, void *data); 57 | 58 | /** 59 | * @brief The prototype for the egress function of a helium plugin 60 | * @param packet A pointer to the packet data 61 | * @param length A pointer to the length of the packet data. If the packet size changed after 62 | * processed by this function, the `length` will be set to the new length of the packet data. 63 | * @param capacity The length of the underlying buffer for packet 64 | * @param data A pointer to the context data of the helium plugin 65 | * @return HE_SUCCESS All plugins executed successfully 66 | * @return HE_ERR_PLUGIN_DROP A plugin marked this packet for a drop 67 | * @return HE_ERR_FAILED An error occurred processing this packet 68 | * @note The content of packet may be modified, grow or shrunk, depending on the registered plugins 69 | */ 70 | typedef he_plugin_return_code_t (*plugin_do_egress)(uint8_t *packet, size_t *length, 71 | size_t capacity, void *data); 72 | 73 | /** 74 | * @brief Data structure of a helium plugin 75 | */ 76 | typedef struct plugin_struct { 77 | plugin_do_ingress do_ingress; 78 | plugin_do_egress do_egress; 79 | void *data; 80 | } plugin_struct_t; 81 | 82 | #endif // HE_PLUGIN_H 83 | -------------------------------------------------------------------------------- /ios.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for iOS 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_ios 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :build: 19 | - git apply ../../wolfssl/*.patch 20 | - autoreconf -i 21 | - "cp ../../ios/autotools-ios-helper.sh ./autotools-ios-helper.sh" 22 | - "./autotools-ios-helper.sh -iphoneuniversal" 23 | :artifacts: 24 | :includes: 25 | - include/** 26 | :static_libraries: 27 | - universal/libwolfssl.a 28 | 29 | :environment: 30 | - MACOSX_DEPLOYMENT_TARGET: "12.0" 31 | -------------------------------------------------------------------------------- /ios/Lightway/Lightway.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Lightway/Lightway.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Lightway/Lightway.xcodeproj/xcshareddata/xcschemes/Lightway.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /ios/Lightway/Lightway/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /ios/Lightway/Lightway/Lightway.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for Lightway. 4 | FOUNDATION_EXPORT double LightwayVersionNumber; 5 | 6 | //! Project version string for Lightway. 7 | FOUNDATION_EXPORT const unsigned char LightwayVersionString[]; 8 | 9 | /// Includes of libhelium public headers 10 | #import "he.h" 11 | -------------------------------------------------------------------------------- /ios/Lightway/build-xcframework.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Build Platform specific Frameworks 4 | # iOS Device 5 | xcodebuild archive \ 6 | -scheme Lightway \ 7 | -archivePath "./Build/ios.xcarchive" \ 8 | -sdk iphoneos \ 9 | SKIP_INSTALL=NO CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO PLATFORM=universal 10 | 11 | # iOS Sim 12 | xcodebuild archive \ 13 | -scheme Lightway \ 14 | -archivePath "./Build/ios_sim.xcarchive" \ 15 | -sdk iphonesimulator \ 16 | SKIP_INSTALL=NO CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO PLATFORM=universal 17 | 18 | # Package XC Framework 19 | xcodebuild -create-xcframework \ 20 | -framework "./Build/ios.xcarchive/Products/Library/Frameworks/Lightway.framework" \ 21 | -framework "./Build/ios_sim.xcarchive/Products/Library/Frameworks/Lightway.framework" \ 22 | -output "./Build/Lightway.xcframework" 23 | -------------------------------------------------------------------------------- /ios/autotools-ios-helper.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | set -e 4 | 5 | # 6 | # Build for iOS device (arm64) and simulator (x86_64 only) 7 | # - macOS 10.15.4 8 | # - iOS 15.4 9 | # - Xcode 13.2.1 10 | # 11 | # Build for tvOS device (arm64) and simulator (x86_64 only) 12 | # - macOS 12.0 13 | # - tvOS 17.0 14 | # - Xcode 15.0 beta 15 | # 16 | # Usage: 17 | # - Place/copy the script at wolfSSL root 18 | # - Customize MIN_IOS_VERSION and other flags as needed 19 | # 20 | export MIN_IOS_VERSION=12.0 21 | export MIN_TVOS_VERSION=17.0 22 | 23 | build() { 24 | # Compiler options 25 | export OPT_FLAGS="-O3" 26 | export MAKE_JOBS="$(/usr/sbin/sysctl -n hw.ncpu)" 27 | 28 | # WolfSSL + Helium 29 | export WOLF_FLAGS="-fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -DWOLFSSL_APPLE_NATIVE_CERT_VALIDATION -DWOLFSSL_ML_KEM_USE_OLD_IDS" 30 | 31 | # Get the correct toolchain for target platforms 32 | export CC="$(xcrun --find --sdk ${SDK} clang)" 33 | export CXX="$(xcrun --find --sdk ${SDK} clang++)" 34 | export CPP="$(xcrun --find --sdk ${SDK} cpp)" 35 | export CFLAGS="${HOST_FLAGS} ${OPT_FLAGS}" 36 | export CXXFLAGS="${HOST_FLAGS} ${OPT_FLAGS}" 37 | export LDFLAGS="${HOST_FLAGS}" 38 | 39 | echo "Debug C_EXTRA_FLAGS=${WOLF_FLAGS}" 40 | 41 | export EXEC_PREFIX="${PREFIX}/${CONFIG}-${PLATFORM}" 42 | echo "PLATFORM: ${PLATFORM}" 43 | echo "EXEC_PREFIX: ${EXEC_PREFIX}" 44 | ./configure $ARCH_OPTS \ 45 | C_EXTRA_FLAGS="$WOLF_FLAGS" \ 46 | --host="${CHOST}" \ 47 | --exec-prefix="${EXEC_PREFIX}" \ 48 | --enable-static \ 49 | --enable-tls13 \ 50 | --disable-oldtls \ 51 | --prefix="${PREFIX}" \ 52 | --enable-singlethreaded \ 53 | --enable-dtls \ 54 | --enable-dtls13 \ 55 | --enable-dtls-mtu \ 56 | --enable-dtls-frag-ch \ 57 | --enable-sp=yes,4096 \ 58 | --disable-dh \ 59 | --enable-curve25519 \ 60 | --enable-secure-renegotiation \ 61 | --disable-shared \ 62 | --disable-examples \ 63 | --enable-sys-ca-certs \ 64 | --enable-sni \ 65 | --disable-crypttests \ 66 | --enable-aes-bitsliced \ 67 | --enable-experimental \ 68 | --enable-sha3 \ 69 | --enable-kyber=all,original,ml-kem 70 | make clean 71 | mkdir -p "${EXEC_PREFIX}" 72 | make V=1 -j"${MAKE_JOBS}" --debug=j 73 | make install 74 | } 75 | 76 | build_iphoneos() { 77 | export SDK="iphoneos" 78 | export PLATFORM="iphoneos" 79 | export EFFECTIVE_PLATFORM_NAME="-iphoneos" 80 | export ARCH_OPTS="--enable-armasm --enable-sp-asm" 81 | export ARCH_FLAGS="-arch arm64" 82 | export HOST_FLAGS="${ARCH_FLAGS} -miphoneos-version-min=${MIN_IOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)" 83 | export CHOST="arm64-apple-ios" 84 | build 85 | } 86 | 87 | build_iphonesimulator() { 88 | export SDK="iphonesimulator" 89 | export PLATFORM="iphonesimulator" 90 | export EFFECTIVE_PLATFORM_NAME="-iphonesimulator" 91 | export ARCH_OPTS="" 92 | export ARCH_FLAGS="-arch x86_64" 93 | export HOST_FLAGS="${ARCH_FLAGS} -mios-simulator-version-min=${MIN_IOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)" 94 | export CHOST="x86_64-apple-darwin" 95 | build 96 | } 97 | 98 | build_tvos() { 99 | export SDK="appletvos" 100 | export PLATFORM="appletvos" 101 | export EFFECTIVE_PLATFORM_NAME="-appletvos" 102 | export ARCH_OPTS="--enable-armasm --enable-sp-asm" 103 | export ARCH_FLAGS="-arch arm64" 104 | export HOST_FLAGS="${ARCH_FLAGS} -mtvos-version-min=${MIN_TVOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)" 105 | export CHOST="arm64-apple-ios" 106 | build 107 | } 108 | 109 | build_tvsimulator() { 110 | export SDK="appletvsimulator" 111 | export PLATFORM="appletvsimulator" 112 | export EFFECTIVE_PLATFORM_NAME="-appletvsimulator" 113 | export ARCH_OPTS="" 114 | export ARCH_FLAGS="-arch x86_64" 115 | export HOST_FLAGS="${ARCH_FLAGS} -mtvos-simulator-version-min=${MIN_TVOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)" 116 | export CHOST="x86_64-apple-darwin" 117 | build 118 | } 119 | 120 | build_ios_universal_binary() { 121 | # Create ios universal binary 122 | LIB_NAME="libwolfssl.a" 123 | mkdir -p "${PREFIX}/${CONFIG}-ios-universal/lib" 124 | lipo -create -output "${PREFIX}/${CONFIG}-ios-universal/lib/${LIB_NAME}" \ 125 | "${PREFIX}/${CONFIG}-iphoneos/lib/${LIB_NAME}" \ 126 | "${PREFIX}/${CONFIG}-iphonesimulator/lib/${LIB_NAME}" 127 | } 128 | 129 | build_tvos_universal_binary() { 130 | # Create ios universal binary 131 | LIB_NAME="libwolfssl.a" 132 | mkdir -p "${PREFIX}/${CONFIG}-tvos-universal/lib" 133 | lipo -create -output "${PREFIX}/${CONFIG}-tvos-universal/lib/${LIB_NAME}" \ 134 | "${PREFIX}/${CONFIG}-appletvos/lib/${LIB_NAME}" \ 135 | "${PREFIX}/${CONFIG}-appletvsimulator/lib/${LIB_NAME}" 136 | } 137 | # Locations 138 | PREFIX=${PREFIX:-"$(pwd)/../builds/wolfssl_ios"} 139 | CONFIG=${CONFIG:-"Release"} 140 | PLATFORMS="${PREFIX}"/platforms 141 | UNIVERSAL="${PREFIX}"/universal 142 | 143 | mkdir -p "${PLATFORMS}" 144 | mkdir -p "${UNIVERSAL}" 145 | 146 | TARGET=${1:-"-all"} 147 | echo "Building wolfSSL for ${TARGET}..." 148 | 149 | case "${TARGET}" in 150 | -iphoneos) 151 | build_iphoneos 152 | ;; 153 | -iphonesimulator) 154 | build_iphonesimulator 155 | ;; 156 | -iphoneuniversal) 157 | build_iphoneos 158 | build_iphonesimulator 159 | build_ios_universal_binary 160 | ;; 161 | -appletvos) 162 | build_tvos 163 | ;; 164 | -appletvsimulator) 165 | build_tvsimulator 166 | ;; 167 | -appletvuniversal) 168 | build_tvos 169 | build_tvsimulator 170 | build_tvos_universal_binary 171 | ;; 172 | -all) 173 | build_iphoneos 174 | build_iphonesimulator 175 | build_ios_universal_binary 176 | build_tvos 177 | build_tvsimulator 178 | build_tvos_universal_binary 179 | ;; 180 | *) 181 | echo "Unsupport target: ${TARGET}" 182 | exit 64 183 | ;; 184 | esac 185 | 186 | echo "Building wolfSSL for ${TARGET}... Done." 187 | -------------------------------------------------------------------------------- /linux.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Linux 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_build 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :environment: 19 | - CFLAGS=-O3 -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DUSE_CERT_BUFFERS_4096 -DUSE_CERT_BUFFERS_256 -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -DWOLFSSL_ML_KEM_USE_OLD_IDS -Wno-error=stringop-overflow 20 | :build: 21 | - git apply ../../wolfssl/*.patch 22 | - "autoreconf -i" 23 | - "./configure $HE_WOLFSSL_CONF_FLAGS $HE_WOLFSSL_ADDL_CONF_FLAGS --prefix=$(pwd)/../builds/wolfssl_build --enable-aesni --enable-sp-asm --enable-intelasm" 24 | - "make" 25 | - "make install" 26 | :artifacts: 27 | :includes: 28 | - include 29 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 30 | :static_libraries: 31 | - lib/libwolfssl.a 32 | -------------------------------------------------------------------------------- /linux_386.yml: -------------------------------------------------------------------------------- 1 | --- 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_build 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :environment: 19 | - CFLAGS=-O3 -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -m32 -DUSE_CERT_BUFFERS_4096 -DUSE_CERT_BUFFERS_256 -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -DWOLFSSL_ML_KEM_USE_OLD_IDS 20 | - LDFLAGS= -m32 21 | :build: 22 | - git apply ../../wolfssl/*.patch 23 | - "autoreconf -i" 24 | - "./configure $HE_WOLFSSL_CONF_FLAGS --prefix=$(pwd)/../builds/wolfssl_build --disable-asm --disable-sp-asm --disable-intelasm" 25 | - "make" 26 | - "make install" 27 | :artifacts: 28 | :includes: 29 | - include 30 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 31 | :static_libraries: 32 | - lib/libwolfssl.a 33 | 34 | :environment: 35 | - CC: clang -m32 36 | 37 | :flags: 38 | :release: 39 | :compile: 40 | :*: 41 | - -m32 42 | :test: 43 | :compile: 44 | :*: 45 | - -m32 46 | :link: 47 | :*: 48 | - -m32 49 | -------------------------------------------------------------------------------- /linux_arm.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Linux 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_build 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :environment: 19 | - CFLAGS=-O3 -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DUSE_CERT_BUFFERS_4096 -DUSE_CERT_BUFFERS_256 -DWOLFSSL_NO_ATOMICS -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -DWOLFSSL_ML_KEM_USE_OLD_IDS 20 | :build: 21 | - git apply ../../wolfssl/*.patch 22 | - "autoreconf -i" 23 | - "./configure --host=$CROSS_COMPILE $HE_WOLFSSL_CONF_FLAGS --prefix=$(pwd)/../builds/wolfssl_build" 24 | - "make" 25 | - "make install" 26 | :artifacts: 27 | :includes: 28 | - include 29 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 30 | :static_libraries: 31 | - lib/libwolfssl.a 32 | -------------------------------------------------------------------------------- /linux_arm64.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Linux 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_build 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :environment: 19 | - CFLAGS=-O3 -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DUSE_CERT_BUFFERS_4096 -DUSE_CERT_BUFFERS_256 -DWOLFSSL_NO_ATOMICS -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -DWOLFSSL_ML_KEM_USE_OLD_IDS 20 | :build: 21 | - git apply ../../wolfssl/*.patch 22 | - "autoreconf -i" 23 | - "./configure --host=$CROSS_COMPILE $HE_WOLFSSL_CONF_FLAGS --prefix=$(pwd)/../builds/wolfssl_build --enable-sp-asm --enable-armasm" 24 | - "make" 25 | - "make install" 26 | :artifacts: 27 | :includes: 28 | - include 29 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 30 | :static_libraries: 31 | - lib/libwolfssl.a 32 | -------------------------------------------------------------------------------- /linux_arm_no_pqc.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Linux 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :defines: 10 | :test: 11 | - HE_NO_PQC 12 | :test_preprocess: 13 | - HE_NO_PQC 14 | :release: 15 | - HE_NO_PQC 16 | 17 | :dependencies: 18 | :libraries: 19 | - :name: WolfSSL 20 | :source_path: third_party/wolfssl 21 | :artifact_path: third_party/builds/wolfssl_build 22 | :fetch: 23 | :method: :git 24 | :source: $HE_WOLFSSL_SOURCE 25 | :tag: $HE_WOLFSSL_TAG 26 | :environment: 27 | - CFLAGS=-O3 -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DUSE_CERT_BUFFERS_4096 -DUSE_CERT_BUFFERS_256 -DWOLFSSL_NO_ATOMICS -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -Werror -Wno-pragmas -Wall -Wextra -Wno-strict-aliasing 28 | :build: 29 | - git apply ../../wolfssl/*.patch 30 | - "autoreconf -i" 31 | - "./configure --host=$CROSS_COMPILE $HE_WOLFSSL_CONF_FLAGS --disable-kyber --disable-sha3 --prefix=$(pwd)/../builds/wolfssl_build" 32 | - "make" 33 | - "make install" 34 | :artifacts: 35 | :includes: 36 | - include 37 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 38 | :static_libraries: 39 | - lib/libwolfssl.a 40 | -------------------------------------------------------------------------------- /linux_multithread.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Linux 2 | :import: 3 | - linux.yml 4 | 5 | :defines: 6 | :test: 7 | - HE_ENABLE_MULTITHREADED 8 | 9 | :tools_test_linker: 10 | :arguments: 11 | - -latomic 12 | 13 | :environment: 14 | - :HE_WOLFSSL_ADDL_CONF_FLAGS: >- 15 | --disable-singlethreaded 16 | -------------------------------------------------------------------------------- /linux_riscv64.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Linux 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :defines: 10 | :test: 11 | - HE_NO_PQC 12 | :test_preprocess: 13 | - HE_NO_PQC 14 | :release: 15 | - HE_NO_PQC 16 | 17 | :dependencies: 18 | :libraries: 19 | - :name: WolfSSL 20 | :source_path: third_party/wolfssl 21 | :artifact_path: third_party/builds/wolfssl_build 22 | :fetch: 23 | :method: :git 24 | :source: $HE_WOLFSSL_SOURCE 25 | :tag: $HE_WOLFSSL_TAG 26 | :environment: 27 | - CFLAGS=-O3 -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DUSE_CERT_BUFFERS_4096 -DUSE_CERT_BUFFERS_256 -DWOLFSSL_NO_ATOMICS -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT 28 | :build: 29 | - git apply ../../wolfssl/*.patch || true 30 | - "autoreconf -i" 31 | - "./configure --host=$CROSS_COMPILE $HE_WOLFSSL_CONF_FLAGS --disable-kyber --disable-sha3 --prefix=$(pwd)/../builds/wolfssl_build" 32 | - "make" 33 | - "make install" 34 | :artifacts: 35 | :includes: 36 | - include 37 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 38 | :static_libraries: 39 | - lib/libwolfssl.a 40 | -------------------------------------------------------------------------------- /macos.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for macOS 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_build 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :environment: 19 | - CFLAGS=-O3 -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -target x86_64-apple-darwin -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -DWOLFSSL_ML_KEM_USE_OLD_IDS 20 | - CC=clang 21 | :build: 22 | - git apply ../../wolfssl/*.patch 23 | - "autoreconf -i" 24 | - "./configure --host=x86_64-apple-darwin $HE_WOLFSSL_CONF_FLAGS --prefix=$(pwd)/../builds/wolfssl_build --enable-aesni --enable-sp-asm --enable-intelasm" 25 | - "make" 26 | - "make install" 27 | :artifacts: 28 | :includes: 29 | - include 30 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 31 | :static_libraries: 32 | - lib/libwolfssl.a 33 | 34 | :flags: 35 | :release: 36 | :compile: 37 | :*: 38 | - -target x86_64-apple-darwin 39 | 40 | :environment: 41 | - MACOSX_DEPLOYMENT_TARGET: "10.12" 42 | -------------------------------------------------------------------------------- /macos_arm64.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for macOS 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_build 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :environment: 19 | - CFLAGS=-O3 -fPIC -D_FORTIFY_SOURCE=2 -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DFP_MAX_BITS=8192 -target arm64-apple-darwin -DWOLFSSL_NO_SPHINCS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT -DWOLFSSL_ML_KEM_USE_OLD_IDS 20 | - CC=clang 21 | :build: 22 | - git apply ../../wolfssl/*.patch 23 | - "autoreconf -i" 24 | - "./configure --host=aarch64-apple-darwin $HE_WOLFSSL_CONF_FLAGS --prefix=$(pwd)/../builds/wolfssl_build --enable-sp-asm --enable-armasm" 25 | - "make" 26 | - "make install" 27 | :artifacts: 28 | :includes: 29 | - include 30 | - include/wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 31 | :static_libraries: 32 | - lib/libwolfssl.a 33 | 34 | :flags: 35 | :release: 36 | :compile: 37 | :*: 38 | - -target arm64-apple-darwin 39 | 40 | :environment: 41 | - MACOSX_DEPLOYMENT_TARGET: "10.16" 42 | -------------------------------------------------------------------------------- /project.yml: -------------------------------------------------------------------------------- 1 | --- 2 | :project: 3 | :use_exceptions: FALSE 4 | :use_test_preprocessor: TRUE 5 | :use_auxiliary_dependencies: TRUE 6 | :build_root: build 7 | :release_build: TRUE 8 | :test_file_prefix: test_ 9 | :which_ceedling: gem 10 | :output: helium 11 | :default_tasks: 12 | - test:all 13 | 14 | :extension: 15 | :executable: .out 16 | 17 | :paths: 18 | :test: 19 | - +:test/** 20 | - -:test/support 21 | :include: 22 | - include/** 23 | :source: 24 | - src/** 25 | :support: 26 | - test/support 27 | 28 | :defines: 29 | :release: 30 | - _FORTIFY_SOURCE=2 31 | :test: 32 | - TEST 33 | 34 | :cmock: 35 | :mock_prefix: mock_ 36 | :when_no_prototypes: :warn 37 | :enforce_strict_ordering: TRUE 38 | :includes: 39 | - he.h 40 | - he_internal.h 41 | - wolfssl_testable_types.h 42 | :plugins: 43 | - :ignore 44 | - :callback 45 | - :ignore_arg 46 | - :expect_any_args 47 | :treat_as: 48 | uint8: HEX8 49 | uint16: HEX16 50 | uint32: UINT32 51 | int8: INT8 52 | bool: UINT8 53 | :treat_as_array: 54 | va_list: void 55 | :strippables: 56 | - WOLFSSL_API 57 | - WOLFSSL_LOCAL 58 | 59 | :plugins: 60 | :enabled: 61 | - stdout_pretty_tests_report 62 | - module_generator 63 | - raw_output_report 64 | - xml_tests_report 65 | - junit_tests_report 66 | - gcov 67 | - dependencies 68 | - compile_commands_json 69 | -------------------------------------------------------------------------------- /public/he_plugin.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file he_plugin.h 22 | * @brief The internal plugin API definitions. 23 | * 24 | * This file is separated out to clearly indicate that a plugin implementation only needs to care 25 | * about this API, not the full set of types and functions included. 26 | */ 27 | 28 | #ifndef HE_PLUGIN_H 29 | #define HE_PLUGIN_H 30 | 31 | #include 32 | #include 33 | 34 | /** 35 | * All possible return code for a helium plugin 36 | */ 37 | typedef enum he_plugin_return_code { 38 | HE_PLUGIN_SUCCESS = 0, 39 | HE_PLUGIN_FAIL = -1, 40 | HE_PLUGIN_DROP = -2, 41 | } he_plugin_return_code_t; 42 | 43 | /** 44 | * @brief The prototype for the ingress function of a helium plugin 45 | * @param packet A pointer to the packet data 46 | * @param length A pointer to the length of the packet data. If the packet size changed after 47 | * processed by this function, the `length` will be set to the new length of the packet data. 48 | * @param capacity The length of the underlying buffer for packet 49 | * @param data A pointer to the context data of the helium plugin 50 | * @return HE_SUCCESS All plugins executed successfully 51 | * @return HE_ERR_PLUGIN_DROP A plugin marked this packet for a drop 52 | * @return HE_ERR_FAILED An error occurred processing this packet 53 | * @note The content of packet may be modified, grow or shrunk, depending on the registered plugins 54 | */ 55 | typedef he_plugin_return_code_t (*plugin_do_ingress)(uint8_t *packet, size_t *length, 56 | size_t capacity, void *data); 57 | 58 | /** 59 | * @brief The prototype for the egress function of a helium plugin 60 | * @param packet A pointer to the packet data 61 | * @param length A pointer to the length of the packet data. If the packet size changed after 62 | * processed by this function, the `length` will be set to the new length of the packet data. 63 | * @param capacity The length of the underlying buffer for packet 64 | * @param data A pointer to the context data of the helium plugin 65 | * @return HE_SUCCESS All plugins executed successfully 66 | * @return HE_ERR_PLUGIN_DROP A plugin marked this packet for a drop 67 | * @return HE_ERR_FAILED An error occurred processing this packet 68 | * @note The content of packet may be modified, grow or shrunk, depending on the registered plugins 69 | */ 70 | typedef he_plugin_return_code_t (*plugin_do_egress)(uint8_t *packet, size_t *length, 71 | size_t capacity, void *data); 72 | 73 | /** 74 | * @brief Data structure of a helium plugin 75 | */ 76 | typedef struct plugin_struct { 77 | plugin_do_ingress do_ingress; 78 | plugin_do_egress do_egress; 79 | void *data; 80 | } plugin_struct_t; 81 | 82 | #endif // HE_PLUGIN_H 83 | -------------------------------------------------------------------------------- /public/stats_plugin.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file stats_plugin.h 22 | * @brief Public API for the example stats_plugin 23 | */ 24 | #ifndef HE_STATS_PLUGIN 25 | #define HE_STATS_PLUGIN 26 | #include 27 | 28 | he_return_code_t stats_plugin_create(plugin_struct_t *plugin_struct); 29 | void stats_plugin_destroy(plugin_struct_t *plugin_struct); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /python/.gitignore: -------------------------------------------------------------------------------- 1 | public_test.h 2 | he.h 3 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # Header Generator 2 | 3 | We use TextX to parse our header files and generate our public API document. 4 | 5 | Unfortunately tools like `pycparser` are unsuitable for this since they ignore 6 | comments, including our Doxygen comments. 7 | 8 | ## How does this work? 9 | 10 | If and only if you wish to re-generate the public header files, cd into this 11 | directory and run the following: 12 | 13 | ```bash 14 | python3 -m venv venv 15 | source venv/bin/activate 16 | pip install textx 17 | ./make_public_header.sh 18 | # Inspect generated he.h 19 | mv he.h ../public/he.h 20 | ``` 21 | 22 | ## Run Tests 23 | Currently, you can run the tests by doing: 24 | 25 | 26 | ```bash 27 | python3 -m venv venv 28 | source venv/bin/activate 29 | pip install textx 30 | python make_header.py /dev/null test/test.h > public_test.h 31 | diff --ignore-blank-lines public_test.h test/fixture_public_test.h 32 | # Expect no output 33 | ``` 34 | 35 | ## Wait I don't want to run python... 36 | 37 | Then don't! Unless you need to regenerate the public headers this code is inert. 38 | 39 | -------------------------------------------------------------------------------- /python/c-header.tx: -------------------------------------------------------------------------------- 1 | // A subset of C necessary to parse header files (with comments) 2 | // Note that in Python `.` does not match newlines in regex. 3 | 4 | Program: statements*=Statement; 5 | Statement: Declaration | PreProcessorDirective | DoubleSlashComment | StarComment; 6 | 7 | Declaration: TypeDef | FunDecl; 8 | 9 | FunDecl: doc=DocString? attr=DeprecationAttr type=TypeSpec name=ID '(' parms=Parms ');'; 10 | Parms: /[^\)]*/; 11 | TypeSpec: 'const '? ID '*'?; 12 | DeprecationAttr: /(HE_DEPRECATED\(.*\))?/; 13 | 14 | TypeDef: 'typedef' ID inner_name=ID? /\{(.|\n)*?\}/ name=ID ';'; 15 | 16 | DocString: /\/\*\*(.|\n)*?\*\//; 17 | 18 | PreProcessorDirective: doc=DocString? /#/ keyword=ID content=/.*/; 19 | DoubleSlashComment: /\/\/.*/; 20 | StarComment: /\/\*(.|\n)*?\*\//; 21 | -------------------------------------------------------------------------------- /python/make_header.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # Lightway Core 4 | # Copyright (C) 2021 Express VPN International Ltd. 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | 20 | import sys 21 | 22 | from textx import metamodel_from_file 23 | 24 | c_header = metamodel_from_file("c-header.tx") 25 | 26 | FunDecl = c_header["FunDecl"] 27 | PreProcessorDirective = c_header["PreProcessorDirective"] 28 | 29 | ENDIF_HE_H = "#endif // HE_H" 30 | 31 | 32 | def print_fundecl(fundecl): 33 | if "*" in fundecl.type: 34 | fundecl.type = fundecl.type[:-1] + " *" 35 | else: 36 | fundecl.type = fundecl.type + " " 37 | if fundecl.attr: 38 | fundecl.attr = fundecl.attr + "\n" 39 | else: 40 | fundecl.attr = "" 41 | 42 | if fundecl.doc: 43 | print( 44 | "%s\n%s%s%s(%s);\n" 45 | % (fundecl.doc, fundecl.attr, fundecl.type, fundecl.name, fundecl.parms) 46 | ) 47 | else: 48 | print( 49 | "%s%s%s(%s);\n" % (fundecl.attr, fundecl.type, fundecl.name, fundecl.parms) 50 | ) 51 | 52 | def print_preproc(preproc): 53 | if preproc.doc: 54 | print("%s\n#%s %s\n" 55 | % (preproc.doc, preproc.keyword, preproc.content) 56 | ) 57 | else: 58 | print("#%s %s\n" % (statement.keyword, statement.content)) 59 | 60 | include_header = sys.argv[1] 61 | print("Including header", include_header, file=sys.stderr) 62 | 63 | for line in open(include_header): 64 | if not line.startswith(ENDIF_HE_H): 65 | print(line, end="") 66 | 67 | for header in sys.argv[2:]: 68 | print("Processing header file", header, file=sys.stderr) 69 | program = c_header.model_from_file(header) 70 | for statement in program.statements: 71 | if isinstance(statement, PreProcessorDirective) and "include" not in statement.keyword and "_H" not in statement.content: 72 | print_preproc(statement) 73 | if isinstance(statement, FunDecl) and "internal" not in statement.name: 74 | print_fundecl(statement) 75 | 76 | print(ENDIF_HE_H, end="\n") 77 | -------------------------------------------------------------------------------- /python/make_public_header.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | # Lightway Core 5 | # Copyright (C) 2021 Express VPN International Ltd. 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | # 21 | 22 | # Generate 23 | python make_header.py \ 24 | ../include/he.h \ 25 | ../src/he/memory.h \ 26 | ../src/he/ssl_ctx.h \ 27 | ../src/he/conn.h \ 28 | ../src/he/flow.h \ 29 | ../src/he/plugin_chain.h \ 30 | ../src/he/client.h \ 31 | ../src/he/utils.h > he.h 32 | 33 | # Format 34 | clang-format -style=file -i he.h 35 | -------------------------------------------------------------------------------- /python/test/fixture_public_test.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @brief Get the username that Helium will authenticate with, previously set by 22 | * he_client_set_username 23 | * @param client A pointer to a valid client context 24 | * @return const char* A pointer to the username 25 | */ 26 | const char *he_client_get_username(const he_client_t *client); 27 | 28 | he_return_code_t he_client_register_plugin(he_client_t *client, plugin_struct_t *plugin); 29 | 30 | /** 31 | * @brief Internal lifecycle function for processing an outside UDP packet 32 | * @param client A valid client context 33 | * @param packet A pointer to the packet data 34 | * @param length The length of the packet 35 | * @return HE_SUCCESS The packet was processed normally. 36 | * @note Please see he_client_outside_data_received for other return values. 37 | */ 38 | he_return_code_t he_test_outside_packet_received(he_client_t *client, uint8_t *packet, 39 | size_t length); 40 | -------------------------------------------------------------------------------- /python/test/test.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "bob.h" 21 | 22 | // OK This is cool 23 | 24 | /* This is a bare-star comment */ 25 | 26 | /** And this is a multiline star 27 | * comment that will hopefully be ignored 28 | */ 29 | 30 | #define BOB 42 31 | 32 | /** 33 | * @brief Get the username that Helium will authenticate with, previously set by 34 | * he_client_set_username 35 | * @param client A pointer to a valid client context 36 | * @return const char* A pointer to the username 37 | */ 38 | const char *he_client_get_username(const he_client_t *client); 39 | 40 | bool he_internal_config_is_string_too_long(const char *string); 41 | 42 | /** 43 | * @brief Updates the timeout for a client context and triggers the timeout callback if set 44 | * @param client A pointer to a valid client context 45 | */ 46 | void he_internal_update_timeout(he_client_t *client); 47 | 48 | he_return_code_t he_client_register_plugin(he_client_t *client, plugin_struct_t *plugin); 49 | 50 | /** 51 | * Packet types the packet info method can infer. 52 | */ 53 | typedef enum he_packet_state { 54 | HE_BAD_PACKET = 0, 55 | HE_PACKET_IP4 = 1, 56 | HE_PACKET_IP6 = 2 57 | } he_packet_state_t; 58 | 59 | /** 60 | * @brief Internal lifecycle function for processing an outside UDP packet 61 | * @param client A valid client context 62 | * @param packet A pointer to the packet data 63 | * @param length The length of the packet 64 | * @return HE_SUCCESS The packet was processed normally. 65 | * @note Please see he_client_outside_data_received for other return values. 66 | */ 67 | he_return_code_t he_test_outside_packet_received(he_client_t *client, uint8_t *packet, 68 | size_t length); 69 | -------------------------------------------------------------------------------- /src/he/client.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "he.h" 21 | 22 | #include "client.h" 23 | #include "ssl_ctx.h" 24 | #include "conn.h" 25 | #include "plugin_chain.h" 26 | #include "memory.h" 27 | 28 | he_client_t *he_client_create() { 29 | he_client_t *client = he_calloc(1, sizeof(he_client_t)); 30 | if(!client) { 31 | return NULL; 32 | } 33 | client->ssl_ctx = he_ssl_ctx_create(); 34 | client->conn = he_conn_create(); 35 | client->inside_plugins = he_plugin_create_chain(); 36 | client->outside_plugins = he_plugin_create_chain(); 37 | 38 | if(client->ssl_ctx == NULL || client->conn == NULL || client->inside_plugins == NULL || 39 | client->outside_plugins == NULL) { 40 | he_client_destroy(client); 41 | return NULL; 42 | } 43 | return client; 44 | } 45 | 46 | he_return_code_t he_client_destroy(he_client_t *client) { 47 | if(client) { 48 | he_conn_destroy(client->conn); 49 | he_ssl_ctx_destroy(client->ssl_ctx); 50 | he_plugin_destroy_chain(client->inside_plugins); 51 | he_plugin_destroy_chain(client->outside_plugins); 52 | 53 | // Should be safe to free now 54 | he_free(client); 55 | } 56 | return HE_SUCCESS; 57 | } 58 | 59 | he_return_code_t he_client_connect(he_client_t *client) { 60 | if(client == NULL) { 61 | return HE_ERR_NULL_POINTER; 62 | } 63 | 64 | // Return holder 65 | int res = 0; 66 | 67 | // First we do the client->wolf_ctx setup 68 | res = he_ssl_ctx_start(client->ssl_ctx); 69 | 70 | if(res != HE_SUCCESS) { 71 | return res; 72 | } 73 | 74 | // Then we connect with the client 75 | res = he_conn_client_connect(client->conn, client->ssl_ctx, client->inside_plugins, 76 | client->outside_plugins); 77 | 78 | if(res != HE_SUCCESS) { 79 | return res; 80 | } 81 | 82 | return HE_SUCCESS; 83 | } 84 | 85 | he_return_code_t he_client_disconnect(he_client_t *client) { 86 | if(client == NULL) { 87 | return HE_ERR_NULL_POINTER; 88 | } 89 | int res = he_ssl_ctx_stop(client->ssl_ctx); 90 | 91 | if(res != HE_SUCCESS) { 92 | return res; 93 | } 94 | 95 | return he_conn_disconnect(client->conn); 96 | } 97 | 98 | he_return_code_t he_client_is_config_valid(he_client_t *client) { 99 | if(client == NULL) { 100 | return HE_ERR_NULL_POINTER; 101 | } 102 | 103 | he_return_code_t ret = he_ssl_ctx_is_valid_client(client->ssl_ctx); 104 | 105 | if(ret != HE_SUCCESS) { 106 | return ret; 107 | } 108 | 109 | return he_conn_is_valid_client(client->ssl_ctx, client->conn); 110 | } 111 | -------------------------------------------------------------------------------- /src/he/client.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file client.h 22 | * @brief Contains functions for dealing with the client convenience struct 23 | * 24 | */ 25 | 26 | #ifndef CLIENT_H 27 | #define CLIENT_H 28 | 29 | #include "he.h" 30 | 31 | /** 32 | * @brief Creates a Helium client 33 | * @return he_client_t* Returns a pointer to a valid Helium context 34 | * @note This function allocates memory 35 | * 36 | * This function must be called to create the initial Helium context for use 37 | * with other functions 38 | */ 39 | he_client_t *he_client_create(void); 40 | 41 | /** 42 | * @brief Releases all memory allocate by Helium including for the crypto layer 43 | * @param client A pointer to a valid client context 44 | * @return HE_SUCCESS This function cannot fail 45 | * @note The crypto layer initialises a limited amount of global state, which Helium does not free 46 | * because there could be multiple Helium instances. The memory used is minimal and will not impact 47 | * creating new Helium instances 48 | * 49 | * It will first remove all of the callbacks which means no Helium callbacks will be triggered after 50 | * calling this function. It is thus an error to call any Helium functions on this context after it 51 | * has been destroyed. 52 | */ 53 | he_return_code_t he_client_destroy(he_client_t *client); 54 | 55 | /** 56 | * @brief Tries to establish a connection with a Helium server 57 | * @param client A pointer to a valid client context 58 | * @return HE_ERR_NULL_POINTER The client pointer supplied is NULL 59 | * @return HE_ERR_CONF_USERNAME_NOT_SET The username has not been set 60 | * @return HE_ERR_CONF_PASSWORD_NOT_SET The password has not been set 61 | * @return HE_ERR_CONF_CA_NOT_SET The CA has not been set 62 | * @return HE_ERR_CONF_MTU_NOT_SET The external MTU has not been set 63 | * @return HE_ERR_CONF_OUTSIDE_WRITE_CB_NOT_SET The outside write callback has not been set 64 | * @return HE_ERR_INIT_FAILED Helium was unable to initialise itself 65 | * @return HE_ERR_SSL_BAD_FILETYPE The SSL certificate was not provided in PEM format 66 | * @return HE_ERR_SSL_BAD_FILE The SSL certificate is corrupt or damaged 67 | * @return HE_ERR_SSL_OUT_OF_MEMORY The crypto engine ran out of memory 68 | * @return HE_ERR_SSL_ASN_INPUT The certificate does not comply to ASN formatting 69 | * @return HE_ERR_SSL_BUFFER Ran out of memory trying to allocate buffers for the SSL layer 70 | * @return HE_ERR_SSL_CERT Generic failure in the SSL engine 71 | * @return HE_ERR_CONNECT_FAILED There was an I/O issue trying to connect to the server. 72 | * @return HE_SUCCESS Helium is in the process of connecting 73 | * @note This function triggers the initialisation and initial connection to a Helium server. 74 | * However it is asynchronous, Helium is *not* connected when this function returns, merely that the 75 | * connection is in progress. Use event and state change callbacks to determine the actual state of 76 | * Helium 77 | * 78 | * This function has a lot of return codes as it is where Helium tries to apply and configure the 79 | * crypto engine. All of the return codes except for HE_SUCCESS are effectively fatal errors. Trying 80 | * to call *he_client_connect* again without changing the configuration is unlikely to succeed. 81 | */ 82 | he_return_code_t he_client_connect(he_client_t *client); 83 | 84 | /** 85 | * @brief Try to cleanly disconnect from the remote server. 86 | * @param client A pointer to a valid client context 87 | * @return HE_ERR_NEVER_CONNECTED The client context has never been connected and so cannot be 88 | * disconnected. It is safe to destroy the client state here. 89 | * @return HE_ERR_INVALID_CLIENT_STATE This function should only be used when Helium is in the 90 | * online state. It is safe to destroy the client in other states. 91 | * @return HE_SUCCESS The disconnect process has started 92 | * @note Like he_client_connect, this is an asynchronous process. Watch state changes to determine 93 | * when Helium has actually disconnected 94 | * @note This function is not yet well described and is likely to change 95 | */ 96 | he_return_code_t he_client_disconnect(he_client_t *client); 97 | 98 | /** 99 | * @brief Checks whether the client context has the basic configuration to allow Helium to connect. 100 | * @param client A pointer to a valid client context 101 | * @return HE_ERR_NULL_POINTER The client pointer supplied is NULL 102 | * @return HE_ERR_CONF_USERNAME_NOT_SET The username has not been set 103 | * @return HE_ERR_CONF_PASSWORD_NOT_SET The password has not been set 104 | * @return HE_ERR_CONF_CA_NOT_SET The CA has not been set 105 | * @return HE_ERR_CONF_MTU_NOT_SET The external MTU has not been set 106 | * @return HE_ERR_CONF_OUTSIDE_WRITE_CB_NOT_SET The outside write callback has not been set 107 | * @return HE_SUCCESS The basic configuration options have been set 108 | * 109 | * @note These return codes are similar to `he_client_connect` because that function will call 110 | * this function before attempting to connect. 111 | */ 112 | he_return_code_t he_client_is_config_valid(he_client_t *client); 113 | 114 | #endif // CLIENT_H 115 | -------------------------------------------------------------------------------- /src/he/config.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "config.h" 21 | 22 | bool he_internal_config_is_string_length_okay(const char *string) { 23 | // This is used for checking strings passed internally to us and should be safe 24 | size_t len = strnlen(string, HE_CONFIG_TEXT_FIELD_LENGTH + 1); 25 | 26 | // Make sure the text will fit 27 | if(len > HE_CONFIG_TEXT_FIELD_LENGTH) { 28 | return false; 29 | } 30 | 31 | // Drop through 32 | return true; 33 | } 34 | 35 | bool he_internal_config_is_string_too_long(const char *string) { 36 | return !he_internal_config_is_string_length_okay(string); 37 | } 38 | 39 | bool he_internal_config_is_empty_string(const char *string) { 40 | // Check the first byte isn't a null byte 41 | if(string[0] == '\0') { 42 | return true; 43 | } 44 | 45 | // Drop through to okay 46 | return false; 47 | } 48 | 49 | he_return_code_t he_internal_set_config_string(char *field, const char *value) { 50 | // Check we didn't get passed any NULL pointers 51 | if(!field || !value) { 52 | return HE_ERR_NULL_POINTER; 53 | } 54 | 55 | // Check the string isn't empty 56 | if(he_internal_config_is_empty_string(value)) { 57 | return HE_ERR_EMPTY_STRING; 58 | } 59 | 60 | // Check it's not too big 61 | if(he_internal_config_is_string_too_long(value)) { 62 | return HE_ERR_STRING_TOO_LONG; 63 | } 64 | 65 | // Copy the string in and ensure it is always terminated 66 | strncpy(field, value, HE_CONFIG_TEXT_FIELD_LENGTH); 67 | field[HE_CONFIG_TEXT_FIELD_LENGTH - 1] = '\0'; 68 | 69 | return HE_SUCCESS; 70 | } 71 | -------------------------------------------------------------------------------- /src/he/config.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file config.h 22 | * @brief Internal configuration conenvience functions 23 | * 24 | */ 25 | 26 | #ifndef CONFIG_H 27 | #define CONFIG_H 28 | 29 | #include "he.h" 30 | 31 | // Helpers - internal only below this point 32 | 33 | /** 34 | * @brief Checks to make sure the string does not exceed the maximum 35 | * @param string The string to test 36 | * @return Whether the length is okay 37 | */ 38 | bool he_internal_config_is_string_length_okay(const char *string); 39 | 40 | bool he_internal_config_is_empty_string(const char *string); 41 | bool he_internal_config_is_string_too_long(const char *string); 42 | 43 | he_return_code_t he_internal_set_config_string(char *field, const char *value); 44 | 45 | #endif // CONFIG_H 46 | -------------------------------------------------------------------------------- /src/he/conn_internal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file conn_internal.h 22 | * @brief Internal functions for managing the connection 23 | * 24 | */ 25 | 26 | #ifndef CONN_INTERNAL_H 27 | #define CONN_INTERNAL_H 28 | 29 | #include "he_internal.h" 30 | 31 | he_return_code_t he_internal_conn_configure(he_conn_t *conn, he_ssl_ctx_t *ctx); 32 | 33 | void he_internal_change_conn_state(he_conn_t *conn, he_conn_state_t state); 34 | 35 | /** 36 | * @brief Sends a message over the secured tunnel 37 | * @param conn A pointer to a valid connection 38 | * @param message A pointer to the raw message to be sent 39 | * @param length The length of the message 40 | * @return he_conn_return_code_t HE_SUCCESS 41 | */ 42 | he_return_code_t he_internal_send_message(he_conn_t *conn, uint8_t *message, uint16_t length); 43 | he_return_code_t he_internal_send_goodbye(he_conn_t *conn); 44 | he_return_code_t he_internal_send_auth(he_conn_t *conn); 45 | 46 | bool he_internal_is_valid_state_for_server_config(he_conn_t *conn); 47 | 48 | he_return_code_t he_internal_renegotiate_ssl(he_conn_t *conn); 49 | 50 | /** 51 | * @brief Updates the timeout for a connection and triggers the timeout callback if set 52 | * @param conn A pointer to a valid connection 53 | */ 54 | void he_internal_update_timeout(he_conn_t *conn); 55 | 56 | void he_internal_generate_event(he_conn_t *conn, he_conn_event_t event); 57 | 58 | size_t he_internal_calculate_data_packet_length(he_conn_t *conn, size_t length); 59 | 60 | /** 61 | * @brief Generate a random session ID 62 | * @param conn A pointer to a valid server connection 63 | * @param session_id_out A pointer to a uint64_t, where we will write the session ID 64 | * @return HE_ERR_RNG_FAILURE An error occurred generating the session ID 65 | * @return HE_SUCCESS Random value generated correctly 66 | */ 67 | he_return_code_t he_internal_generate_session_id(he_conn_t *conn, uint64_t *session_id_out); 68 | 69 | #endif // CONN_INTERNAL_H 70 | -------------------------------------------------------------------------------- /src/he/core.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "core.h" 21 | #include "conn.h" 22 | 23 | he_return_code_t he_internal_setup_stream_state(he_conn_t *conn, uint8_t *data, size_t length) { 24 | if(conn->incoming_data_left_to_read != 0) { 25 | // Somehow this function was called without reading all data from a previous buffer 26 | // This is bad 27 | he_conn_set_ssl_error(conn, 0); 28 | return HE_ERR_SSL_ERROR; 29 | } 30 | // Set up the location of the buffer and its length 31 | conn->incoming_data = data; 32 | conn->incoming_data_length = length; 33 | 34 | // Initialise the offset pointer and data left counter 35 | conn->incoming_data_left_to_read = conn->incoming_data_length; 36 | conn->incoming_data_read_offset_ptr = conn->incoming_data; 37 | 38 | return HE_SUCCESS; 39 | } 40 | -------------------------------------------------------------------------------- /src/he/core.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file core.h 22 | * @brief Utility functions 23 | * 24 | */ 25 | 26 | #ifndef CORE_H 27 | #define CORE_H 28 | 29 | #include "he_internal.h" 30 | 31 | /** 32 | * @brief Setup the pointers and counters for reading from a TCP stream 33 | */ 34 | he_return_code_t he_internal_setup_stream_state(he_conn_t *conn, uint8_t *data, size_t length); 35 | 36 | /** 37 | * Out of the box, Unity doesn't allow us to mock intra-module function calls. 38 | * This is generally OK but is *very* annoying for the packet lifecycle functions, 39 | * where we pass control to a bunch of various functions in a pipeline, so 40 | * instead of artificially breaking these functions into different modules we 41 | * just mock the "handover" here with a dispatch macro. 42 | * 43 | * If TEST isn't defined this just compiles down to a function call, so there's 44 | * zero performance penalty AND we would get compile errors if the function is 45 | * called incorrectly. 46 | */ 47 | #ifdef TEST 48 | #include "fake_dispatch.h" // Never implemented, only used as a mock 49 | #define HE_DISPATCH(func, ...) dispatch("" #func "", ##__VA_ARGS__); 50 | #define HE_DISPATCH_CONN(func, conn) dispatch_conn("" #func "", conn); 51 | #else 52 | #define HE_DISPATCH(func, ...) func(__VA_ARGS__); 53 | #define HE_DISPATCH_CONN(func, ...) func(__VA_ARGS__); 54 | #endif // TEST 55 | 56 | #endif // CORE_H 57 | -------------------------------------------------------------------------------- /src/he/flow.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file flow.h 22 | * @brief Functions for the flow of packets through Helium 23 | * 24 | */ 25 | 26 | #ifndef FLOW_H 27 | #define FLOW_H 28 | 29 | #include "he.h" 30 | #include "he_internal.h" 31 | 32 | /** 33 | * @brief Called when the host application needs to deliver an inside packet to Helium. 34 | * @param conn A valid connection 35 | * @param packet A pointer to the packet data 36 | * @param length The length of the packet 37 | * @return HE_ERR_INVALID_CLIENT_STATE Helium will reject packets if it is not in the 38 | * HE_STATE_ONLINE state 39 | * @return HE_ERR_PACKET_TOO_SMALL The packet is too small to be a valid Helium packet 40 | * @return HE_ERR_UNSUPPORTED_PACKET_TYPE The packet is not an IPv4 packet 41 | * @return HE_ERR_FAILED The packet was rejected as it won't fit in internal buffers 42 | * @return HE_SUCCESS Packet was processed normally 43 | * @note It is expected that Helium will support IPv6 almost immediately, so it is worth keeping 44 | * this in mind. 45 | * @note These error codes may change before final release as new issues come to light. 46 | */ 47 | he_return_code_t he_conn_inside_packet_received(he_conn_t *conn, uint8_t *packet, size_t length); 48 | 49 | /** 50 | * @brief Called when the host application needs to deliver outside data to be processed by Helium 51 | * @param conn A valid Helium connection 52 | * @param buffer A pointer to the packet data 53 | * @param length The length of the packet 54 | * @return HE_ERR_NULL_POINTER The pointer provided is a NULL pointer 55 | * @return HE_ERR_PACKET_TOO_SMALL The packet is too small to be a valid Helium packet 56 | * @return HE_ERR_NOT_HE_PACKET The packet is not a Helium packet (it does not have the Helium 57 | * header) 58 | * @return HE_ERR_SSL_ERROR Something went wrong decrypting the packet - this is a FATAL error for 59 | * the connection 60 | * @return HE_ERR_SERVER_DN_MISMATCH The name in the server's cert did not match local configuration 61 | * @return HE_ERR_CANNOT_VERIFY_SERVER_CERT The server certificate couldn't be verified using the 62 | * configured CA Cert 63 | * @return HE_SUCCESS The packet was processed normally. 64 | * @note These error codes may change before final release as new issues come to light. 65 | * @note If the conn has registered plugins, they may arbitrarily change the packet data, 66 | * but are restricted here to not exceeding the provided length. Users 67 | * who wish to have more control over this should *not* register plugins upon connection, but 68 | * instead call the plugin API explicitly prior to invoking this function. 69 | */ 70 | he_return_code_t he_conn_outside_data_received(he_conn_t *conn, uint8_t *buffer, size_t length); 71 | 72 | he_return_code_t he_internal_flow_process_message(he_conn_t *conn, he_packet_buffer_t *read_packet); 73 | he_return_code_t he_internal_flow_fetch_message(he_conn_t *conn, he_packet_buffer_t *read_packet); 74 | he_return_code_t he_internal_update_session_incoming(he_conn_t *conn, he_wire_hdr_t *hdr); 75 | 76 | he_return_code_t he_internal_flow_outside_packet_received(he_conn_t *conn, uint8_t *packet, 77 | size_t length); 78 | he_return_code_t he_internal_flow_outside_stream_received(he_conn_t *conn, uint8_t *buffer, 79 | size_t length); 80 | he_return_code_t he_internal_flow_outside_data_verify_connection(he_conn_t *conn); 81 | he_return_code_t he_internal_flow_outside_data_handle_messages(he_conn_t *conn); 82 | 83 | bool he_internal_flow_should_fragment(he_conn_t *conn, uint16_t effective_pmtu, uint16_t length); 84 | 85 | #ifdef HE_ENABLE_MULTITHREADED 86 | extern HE_THREAD_LOCAL uint8_t *cur_packet; 87 | extern HE_THREAD_LOCAL size_t cur_packet_length; 88 | extern HE_THREAD_LOCAL bool packet_seen; 89 | 90 | static inline void he_internal_set_packet(he_conn_t *conn, uint8_t *packet, size_t len) { 91 | cur_packet_length = len; 92 | cur_packet = packet; 93 | } 94 | 95 | static inline void he_internal_set_packet_seen(he_conn_t *conn, bool value) { 96 | packet_seen = value; 97 | } 98 | 99 | static inline bool he_internal_is_packet_seen(he_conn_t *conn) { 100 | return packet_seen; 101 | } 102 | 103 | static inline bool he_internal_is_pkt_available(he_conn_t *conn) { 104 | return !packet_seen && cur_packet; 105 | } 106 | 107 | static inline size_t he_internal_copy_packet(he_conn_t *conn, char *buf) { 108 | memcpy(buf, cur_packet, cur_packet_length); 109 | return cur_packet_length; 110 | } 111 | 112 | static inline size_t he_internal_get_packet_length(he_conn_t *conn) { 113 | return cur_packet_length; 114 | } 115 | 116 | #else // HE_ENABLE_MULTITHREADED 117 | 118 | static inline void he_internal_set_packet(he_conn_t *conn, uint8_t *packet, size_t len) { 119 | conn->incoming_data_length = len; 120 | conn->incoming_data = packet; 121 | } 122 | 123 | static inline void he_internal_set_packet_seen(he_conn_t *conn, bool value) { 124 | conn->packet_seen = value; 125 | } 126 | 127 | static inline bool he_internal_is_packet_seen(he_conn_t *conn) { 128 | return conn->packet_seen; 129 | } 130 | 131 | static inline bool he_internal_is_pkt_available(he_conn_t *conn) { 132 | return !!conn->incoming_data; 133 | } 134 | 135 | static inline size_t he_internal_copy_packet(he_conn_t *conn, char *buf) { 136 | memcpy(buf, conn->incoming_data, conn->incoming_data_length); 137 | return conn->incoming_data_length; 138 | } 139 | 140 | static inline size_t he_internal_get_packet_length(he_conn_t *conn) { 141 | return conn->incoming_data_length; 142 | } 143 | #endif // HE_ENABLE_MULTITHREADED 144 | 145 | #endif // FLOW_H 146 | -------------------------------------------------------------------------------- /src/he/frag.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Lightway Core 3 | * Copyright (C) 2023 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file frag.h 22 | * @brief Internal header file for fragmentation support 23 | */ 24 | 25 | #ifndef FRAG_H 26 | #define FRAG_H 27 | 28 | #include 29 | #include 30 | 31 | #define MAX_FRAGMENT_ENTRIES 65536 32 | 33 | // Forward declarations 34 | typedef struct he_conn he_conn_t; 35 | typedef struct he_fragment_entry_node he_fragment_entry_node_t; 36 | 37 | // Information of a fragment 38 | typedef struct he_fragment_entry_node { 39 | uint16_t begin; 40 | uint16_t end; 41 | bool last_frag; 42 | he_fragment_entry_node_t *next; 43 | } he_fragment_entry_node_t; 44 | 45 | // An entry of the fragment table 46 | typedef struct he_fragment_entry { 47 | uint8_t data[HE_MAX_WIRE_MTU]; 48 | time_t timestamp; 49 | // Linked list contains infomation of received fragments 50 | he_fragment_entry_node_t *fragments; 51 | } he_fragment_entry_t; 52 | 53 | // Fragment table for reassembling fragments 54 | typedef struct he_fragment_table { 55 | he_fragment_entry_t **entries; 56 | size_t num_entries; 57 | } he_fragment_table_t; 58 | 59 | /** 60 | * @brief Fragment a packet and send it over the secured tunnel as multiple messages 61 | * @param conn A pointer to a valid connection 62 | * @param packet A pointer to the raw packet to be sent 63 | * @param length The length of the packet 64 | * @param frag_size Size of each fragment in bytes 65 | * @return HE_SUCCESS if the packet is fragmented and sent successfully 66 | */ 67 | he_return_code_t he_internal_frag_and_send_message(he_conn_t *conn, uint8_t *packet, 68 | uint16_t length, uint16_t frag_size); 69 | 70 | /** 71 | * @brief Reset the given fragment entry 72 | * @param entry A pointer to a valid fragment entry 73 | */ 74 | void he_fragment_entry_reset(he_fragment_entry_t *entry); 75 | 76 | /** 77 | * @brief Update the given fragment entry with a new fragment. 78 | * @param entry A pointer to a valid fragment entry 79 | * @param data A pointer to the fragment data 80 | * @param offset Offset of the fragment in the original packet in bytes 81 | * @param length Length of the fragment 82 | * @param mf More Fragment flag 83 | * @param assembled (out) Indicate if the packet has been fully reassembled. 84 | * @return Returns HE_SUCCESS if the fragment entry is updated without error. 85 | * @note This function may allocates or free memory. 86 | */ 87 | int he_fragment_entry_update(he_fragment_entry_t *entry, uint8_t *data, uint16_t offset, 88 | size_t length, uint8_t mf, bool *assembled); 89 | 90 | /** 91 | * @brief Create and initialize a new fragment table. 92 | * @param num_entries Number of fragment entries can be used in the fragment table. If it's 0, the 93 | * default value MAX_FRAGMENT_ENTRIES will be used. 94 | * @return Pointer to a he_fragment_table_t struct. 95 | * @note This function allocates memory, the caller must call `he_internal_fragment_table_destroy` 96 | * after use. 97 | */ 98 | he_fragment_table_t *he_internal_fragment_table_create(size_t num_entries); 99 | 100 | /** 101 | * @brief Find entry for the given fragment id. 102 | * @param tbl Pointer to a valid he_fragment_table_t struct. 103 | * @param frag_id Fragment Identifier 104 | * @return Pointer to the fragment entry of the given id. It may return NULL if the function failed 105 | * to allocate memory for a new entry. 106 | * @note This function may allocate memory. 107 | */ 108 | he_fragment_entry_t *he_internal_fragment_table_find(he_fragment_table_t *tbl, uint16_t frag_id); 109 | 110 | /** 111 | * @brief Delete entry from the fragment table. 112 | * @param tbl Pointer to a valid he_fragment_table_t struct. 113 | * @param frag_id Fragment Identifier 114 | */ 115 | void he_internal_fragment_table_delete(he_fragment_table_t *tbl, uint16_t frag_id); 116 | 117 | /** 118 | * @brief Destroy the given `he_fragment_table` and free up all memory. 119 | * @param tbl A pointer to a valid he_fragment_table struct. 120 | */ 121 | void he_internal_fragment_table_destroy(he_fragment_table_t *tbl); 122 | 123 | #endif // FRAG_H 124 | -------------------------------------------------------------------------------- /src/he/memory.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "memory.h" 21 | 22 | static he_malloc_t internal_malloc = 0; 23 | static he_calloc_t internal_calloc = 0; 24 | static he_realloc_t internal_realloc = 0; 25 | static he_free_t internal_free = 0; 26 | 27 | he_return_code_t he_set_allocators(he_malloc_t new_malloc, he_calloc_t new_calloc, 28 | he_realloc_t new_realloc, he_free_t new_free) { 29 | int res = wolfSSL_SetAllocators(new_malloc, new_free, new_realloc); 30 | 31 | // Currently this function is hardcoded to return 0 but just-in-case :-) 32 | // https://github.com/wolfSSL/wolfssl/blob/f15450f63e440d5ef64ceac1a6fe79296e2cec7a/wolfcrypt/src/memory.c#L109 33 | if(res != 0) { 34 | return HE_ERR_INIT_FAILED; 35 | } 36 | 37 | internal_malloc = new_malloc; 38 | internal_calloc = new_calloc; 39 | internal_realloc = new_realloc; 40 | internal_free = new_free; 41 | 42 | return HE_SUCCESS; 43 | } 44 | 45 | void *he_malloc(size_t size) { 46 | if(internal_malloc) { 47 | return internal_malloc(size); 48 | } else { 49 | return malloc(size); 50 | } 51 | } 52 | void *he_calloc(size_t nmemb, size_t size) { 53 | if(internal_calloc) { 54 | return internal_calloc(nmemb, size); 55 | } else { 56 | return calloc(nmemb, size); 57 | } 58 | } 59 | 60 | void *he_realloc(void *ptr, size_t size) { 61 | if(internal_realloc) { 62 | return internal_realloc(ptr, size); 63 | } else { 64 | return realloc(ptr, size); 65 | } 66 | } 67 | 68 | void he_free(void *ptr) { 69 | if(internal_free) { 70 | internal_free(ptr); 71 | } else { 72 | free(ptr); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/he/memory.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file memory.h 22 | * @brief Customisation of allocators if desired 23 | * 24 | */ 25 | 26 | #ifndef MEMORY_H 27 | #define MEMORY_H 28 | 29 | #include "he.h" 30 | #include "he_internal.h" 31 | 32 | /** 33 | * @brief Set allocators for use by libhelium 34 | * @param malloc A function that conforms to the signature of malloc(3) 35 | * @param calloc A function that conforms to the signature of calloc(3) 36 | * @param realloc A function that conforms to the signature of realloc(3) 37 | * @param free A function that conforms to the signature of free(3) 38 | * 39 | * @return HE_SUCCESS Currently this function cannot fail 40 | * @note If this function is not called, Helium will use system allocators by default 41 | */ 42 | he_return_code_t he_set_allocators(he_malloc_t malloc, he_calloc_t calloc, he_realloc_t realloc, 43 | he_free_t free); 44 | 45 | /** 46 | * @brief Allocate memory using the internal malloc function set by he_set_allocators() 47 | * @note The caller must call he_free when the allocated memory is no longer used 48 | */ 49 | void *he_malloc(size_t size); 50 | 51 | /** 52 | * @brief Allocate memory using the internal calloc function set by he_set_allocators() 53 | * @note The caller must call he_free when the allocated memory is no longer used 54 | */ 55 | void *he_calloc(size_t nmemb, size_t size); 56 | 57 | /** 58 | * @brief Allocate memory using the internal realloc function set by he_set_allocators() 59 | * @note The caller must call he_free when the allocated memory is no longer used 60 | */ 61 | void *he_realloc(void *ptr, size_t size); 62 | 63 | /** 64 | * @brief Free memory using the internal free function set by he_set_allocators() 65 | */ 66 | void he_free(void *ptr); 67 | 68 | #endif // MEMORY_H 69 | -------------------------------------------------------------------------------- /src/he/msg_handlers.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file msg_handlers.h 22 | * @brief Functions to handle each message type, no public API 23 | */ 24 | 25 | #ifndef MSG_HANDLERS_H 26 | #define MSG_HANDLERS_H 27 | 28 | #include "he.h" 29 | #include "he_internal.h" 30 | 31 | he_return_code_t he_handle_msg_noop(he_conn_t *conn, uint8_t *packet, int length); 32 | he_return_code_t he_handle_msg_ping(he_conn_t *conn, uint8_t *packet, int length); 33 | he_return_code_t he_handle_msg_pong(he_conn_t *conn, uint8_t *packet, int length); 34 | he_return_code_t he_handle_msg_auth(he_conn_t *conn, uint8_t *packet, int length); 35 | he_return_code_t he_handle_msg_data(he_conn_t *conn, uint8_t *packet, int length); 36 | he_return_code_t he_handle_msg_data_with_frag(he_conn_t *conn, uint8_t *packet, int length); 37 | he_return_code_t he_handle_msg_config_ipv4(he_conn_t *conn, uint8_t *packet, int length); 38 | he_return_code_t he_handle_msg_auth_response(he_conn_t *conn, uint8_t *packet, int length); 39 | he_return_code_t he_handle_msg_auth_response_with_config(he_conn_t *conn, uint8_t *packet, 40 | int length); 41 | he_return_code_t he_handle_msg_deprecated_13(he_conn_t *conn, uint8_t *packet, int length); 42 | he_return_code_t he_handle_msg_goodbye(he_conn_t *conn, uint8_t *packet, int length); 43 | he_return_code_t he_handle_msg_server_config(he_conn_t *conn, uint8_t *packet, int length); 44 | 45 | #endif // MSG_HANDLERS_H 46 | -------------------------------------------------------------------------------- /src/he/mss.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2023 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "mss.h" 21 | #include "network.h" 22 | 23 | he_return_code_t he_internal_clamp_mss(uint8_t *packet, size_t length, uint16_t mss) { 24 | // If packet is null or length is zero return 25 | if(!packet) { 26 | return HE_ERR_NULL_POINTER; 27 | } 28 | 29 | if(!length) { 30 | return HE_ERR_ZERO_SIZE; 31 | } 32 | 33 | // Ensure that the mss is a valid value 34 | if(mss < MIN_PLPMTU || mss > HE_MAX_WIRE_MTU) { 35 | return HE_ERR_FAILED; 36 | } 37 | 38 | // We only handle IPv4 packets for now 39 | if(!he_internal_is_ipv4_packet_valid(packet, length)) { 40 | return HE_ERR_BAD_PACKET; 41 | } 42 | 43 | // Apply IPv4 header 44 | ipv4_header_t *ip = (ipv4_header_t *)packet; 45 | 46 | // Check to see if this is TCP, ignore non-TCP packets 47 | if(ip->protocol != HE_IP_TCP) { 48 | return HE_SUCCESS; 49 | } 50 | 51 | // Make sure it isn't a fragment with an offset other than zero (first packet) 52 | uint16_t temp_frag_flags = ntohs(ip->flags_fo); 53 | 54 | // Remove the option flags 55 | temp_frag_flags = temp_frag_flags & ~(HE_IP_DONT_FRAGMENT | HE_IP_MORE_FRAGMENTS); 56 | 57 | if(temp_frag_flags != HE_IP_NO_FRAG_OFFSET) { 58 | // It has an offset so does not contain the TCP header 59 | return HE_SUCCESS; 60 | } 61 | 62 | // Calculate IP header length 63 | int ip_header_len = 4 * (ip->ver_ihl & 0x0F); 64 | 65 | // Check there's enough space 66 | if(ip_header_len + sizeof(tcp_header_t) > length) { 67 | return HE_SUCCESS; 68 | } 69 | 70 | // Apply TCP header 71 | tcp_header_t *tcp = (tcp_header_t *)(packet + ip_header_len); 72 | 73 | // Skip if not a SYN packet 74 | if(!(tcp->flags & HE_TCP_SYN)) { 75 | return HE_SUCCESS; 76 | } 77 | 78 | // Determine if there are any options 79 | uint8_t tcp_offset = tcp->data_offset >> 4; 80 | int tcp_header_len = (tcp_offset * 4); 81 | int options_len = tcp_header_len - sizeof(tcp_header_t); 82 | 83 | // Check to make sure we're in bounds 84 | if(ip_header_len + tcp_header_len > length) { 85 | return HE_SUCCESS; 86 | } 87 | 88 | // Pointer to where the options start 89 | uint8_t *options = (uint8_t *)(packet + ip_header_len + sizeof(tcp_header_t)); 90 | 91 | // Look for MSS in tcp options 92 | while(options_len >= HE_TCP_MSS_OPT_SIZE) { 93 | tcp_option_t *opt = (tcp_option_t *)options; 94 | 95 | // This is the end of options separator 96 | if(opt->kind == HE_TCP_OPT_END) { 97 | break; 98 | } 99 | 100 | // NOP is just one byte, special handling 101 | if(opt->kind == HE_TCP_OPT_NOP) { 102 | options_len--; 103 | options++; 104 | continue; 105 | } 106 | 107 | // We found the MSS fix entry - let's change it 108 | if(opt->kind == HE_TCP_OPT_MSS) { 109 | // Check the mss option size 110 | if(opt->size != HE_TCP_MSS_OPT_SIZE) { 111 | break; 112 | } 113 | // Copy out the current MSS value from the packet 114 | uint16_t current_mss = 0; 115 | uint16_t current_mss_be = 0; 116 | memcpy(¤t_mss_be, (uint8_t *)opt + sizeof(tcp_option_t), sizeof(uint16_t)); 117 | 118 | // Convert it to host byte order 119 | current_mss = ntohs(current_mss_be); 120 | 121 | // Don't do anything if the mss is lower than our setting 122 | if(current_mss <= mss) { 123 | // Nothing to do 124 | return HE_SUCCESS; 125 | } 126 | 127 | // We're going to need the BE version of our MSS to copy into the packet 128 | uint16_t mss_be = htons(mss); 129 | 130 | // Copy in the new MSS value 131 | memcpy((uint8_t *)opt + sizeof(tcp_option_t), &mss_be, sizeof(uint16_t)); 132 | 133 | // Recompute the TCP checksum incrementally 134 | he_internal_calculate_differential_checksum(&tcp->checksum, &mss_be, ¤t_mss_be, 1); 135 | 136 | // Return as we don't care about other options 137 | return HE_SUCCESS; 138 | } 139 | 140 | // Skip over any other option types 141 | if(opt->size > 0 && opt->size <= options_len) { 142 | options_len -= opt->size; 143 | options += opt->size; 144 | } else { 145 | // Unexpected option size 146 | break; 147 | } 148 | } 149 | 150 | return HE_SUCCESS; 151 | } 152 | -------------------------------------------------------------------------------- /src/he/mss.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2023 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef HE_MSS_H 21 | #define HE_MSS_H 22 | 23 | #include "he.h" 24 | #include "he_internal.h" 25 | 26 | /** 27 | * @brief Clamps the Maximum Segment Size option of provided TCP connection 28 | * @param packet A pointer to the packet data 29 | * @param length The length of the packet 30 | * @param mss The maximum MSS a TCP connection can have 31 | * @return HE_ERR_NULL_POINTER A NULL pointer was specified as the packet 32 | * @return HE_ERR_FAILED An MSS of zero was specified 33 | * @return HE_ERR_ZERO_SIZE The packet has zero length 34 | * @return HE_SUCCESS Packet has been processed normally 35 | */ 36 | he_return_code_t he_internal_clamp_mss(uint8_t *packet, size_t length, uint16_t mss); 37 | 38 | #endif // HE_MSS_H 39 | -------------------------------------------------------------------------------- /src/he/network.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2023 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "network.h" 21 | 22 | void he_internal_calculate_differential_checksum(uint16_t *cksum, void *newp, void *oldp, size_t n) { 23 | size_t i; 24 | int32_t accumulate; 25 | uint16_t *newv = (uint16_t *)newp; 26 | uint16_t *oldv = (uint16_t *)oldp; 27 | 28 | accumulate = *cksum; 29 | for(i = 0; i < n; i++) { 30 | accumulate -= *newv; 31 | accumulate += *oldv; 32 | 33 | newv++; 34 | oldv++; 35 | } 36 | 37 | if(accumulate < 0) { 38 | accumulate = -accumulate; 39 | accumulate = (accumulate >> 16) + (accumulate & 0xffff); 40 | accumulate += accumulate >> 16; 41 | *cksum = (uint16_t)~accumulate; 42 | } else { 43 | accumulate = (accumulate >> 16) + (accumulate & 0xffff); 44 | accumulate += accumulate >> 16; 45 | *cksum = (uint16_t)accumulate; 46 | } 47 | } 48 | 49 | bool he_internal_is_ipv4_packet_valid(uint8_t *packet, size_t length) { 50 | if(packet == NULL || length < sizeof(ipv4_header_t)) { 51 | return false; 52 | } 53 | // for now just check that the packet is IPv4 54 | int proto = packet[0] >> 4; 55 | 56 | if(proto != 4) { 57 | return false; 58 | } 59 | 60 | // Assume it's good enough 61 | return true; 62 | } 63 | -------------------------------------------------------------------------------- /src/he/network.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2023 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef HE_NETWORK_H 21 | #define HE_NETWORK_H 22 | 23 | #include "he.h" 24 | #include "he_internal.h" 25 | 26 | #pragma pack(1) 27 | 28 | #define HE_IP_DONT_FRAGMENT (1 << 14) 29 | #define HE_IP_NO_FRAG_OFFSET 0 30 | #define HE_IP_MORE_FRAGMENTS (1 << 13) 31 | #define HE_IP_FRAGMENT_OFFSET_MULTIPLIER 8 32 | #define HE_IP_LENGTH_BITMASK 0x0F 33 | typedef struct { 34 | uint8_t ver_ihl; // 4 bits version and 4 bits internet header length 35 | uint8_t tos; 36 | uint16_t total_length; 37 | uint16_t id; 38 | uint16_t flags_fo; // 3 bits flags and 13 bits fragment-offset 39 | uint8_t ttl; 40 | uint8_t protocol; 41 | uint16_t checksum; 42 | uint32_t src_addr; 43 | uint32_t dst_addr; 44 | } ipv4_header_t; 45 | 46 | #define HE_IP_TCP 0x06 47 | #define HE_IP_UDP 0x11 48 | #define HE_TCP_SYN 0x02 49 | typedef struct { 50 | uint16_t src_port; 51 | uint16_t dst_port; 52 | uint32_t seq; 53 | uint32_t ack; 54 | uint8_t data_offset; // 4 bits 55 | uint8_t flags; 56 | uint16_t window_size; 57 | uint16_t checksum; 58 | uint16_t urgent_p; 59 | } tcp_header_t; 60 | 61 | // https://www.rfc-editor.org/rfc/rfc9293.html#Option-Definitions 62 | #define HE_TCP_OPT_END 0 63 | #define HE_TCP_OPT_NOP 1 64 | #define HE_TCP_OPT_MSS 2 65 | #define HE_TCP_MSS_OPT_SIZE 4 66 | 67 | typedef struct { 68 | uint8_t kind; 69 | uint8_t size; 70 | } tcp_option_t; 71 | 72 | typedef struct { 73 | uint16_t src_port; 74 | uint16_t dst_port; 75 | uint16_t length; 76 | uint16_t checksum; 77 | } udp_header_t; 78 | 79 | #pragma pack() 80 | 81 | void he_internal_calculate_differential_checksum(uint16_t *cksum, void *newp, void *oldp, size_t n); 82 | bool he_internal_is_ipv4_packet_valid(uint8_t *packet, size_t length); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/he/plugin_chain.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "plugin_chain.h" 21 | #include "memory.h" 22 | 23 | he_plugin_chain_t *he_plugin_create_chain(void) { 24 | return he_calloc(1, sizeof(he_plugin_chain_t)); 25 | } 26 | 27 | void he_plugin_destroy_chain(he_plugin_chain_t *chain) { 28 | if(chain) { 29 | he_plugin_destroy_chain(chain->next); 30 | he_free(chain); 31 | } 32 | } 33 | 34 | he_return_code_t he_plugin_register_plugin(he_plugin_chain_t *chain, plugin_struct_t *plugin) { 35 | if(chain == NULL || plugin == NULL) { 36 | return HE_ERR_NULL_POINTER; 37 | } 38 | 39 | // A bit odd, but we initialise the plugin AFTER walking the chain 40 | if(!chain->plugin) { 41 | chain->plugin = plugin; 42 | return HE_SUCCESS; 43 | } 44 | 45 | if(!chain->next) { 46 | chain->next = he_plugin_create_chain(); 47 | if(chain->next == NULL) { 48 | return HE_ERR_INIT_FAILED; 49 | } 50 | } 51 | 52 | // This does a null pointer check for us 53 | return he_plugin_register_plugin(chain->next, plugin); 54 | } 55 | 56 | he_return_code_t he_plugin_ingress(he_plugin_chain_t *chain, uint8_t *packet, size_t *length, 57 | size_t capacity) { 58 | // Expected! 59 | if(chain == NULL) { 60 | return HE_SUCCESS; 61 | } 62 | 63 | plugin_struct_t *plugin = chain->plugin; 64 | 65 | if(plugin && plugin->do_ingress != NULL) { 66 | int res = plugin->do_ingress(packet, length, capacity, plugin->data); 67 | if(res == HE_PLUGIN_FAIL) { 68 | return HE_ERR_FAILED; 69 | } 70 | 71 | if(res == HE_PLUGIN_DROP) { 72 | return HE_ERR_PLUGIN_DROP; 73 | } 74 | } 75 | 76 | return he_plugin_ingress(chain->next, packet, length, capacity); 77 | } 78 | 79 | he_return_code_t he_plugin_egress(he_plugin_chain_t *chain, uint8_t *packet, size_t *length, 80 | size_t capacity) { 81 | // Expected! 82 | if(chain == NULL) { 83 | return HE_SUCCESS; 84 | } 85 | 86 | int res = he_plugin_egress(chain->next, packet, length, capacity); 87 | if(res != HE_SUCCESS) { 88 | return res; 89 | } 90 | 91 | plugin_struct_t *plugin = chain->plugin; 92 | 93 | if(plugin && plugin->do_egress != NULL) { 94 | res = plugin->do_egress(packet, length, capacity, plugin->data); 95 | if(res == HE_PLUGIN_FAIL) { 96 | return HE_ERR_FAILED; 97 | } 98 | if(res == HE_PLUGIN_DROP) { 99 | return HE_ERR_PLUGIN_DROP; 100 | } 101 | } 102 | return HE_SUCCESS; 103 | } 104 | -------------------------------------------------------------------------------- /src/he/plugin_chain.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file plugin_chain.h 22 | * @brief Creation, destruction, registration, and execution for a plugin chain 23 | * 24 | */ 25 | 26 | #ifndef PLUGIN_CHAIN_H 27 | #define PLUGIN_CHAIN_H 28 | 29 | #include "he_internal.h" 30 | 31 | /** 32 | * @brief Creates a Helium plugin chain 33 | * @return he_plugin_chain_t* Returns a pointer to a valid plugin chain 34 | * @note This function allocates memory 35 | * 36 | * This function must be called to create the initial plugin chain for use 37 | * with other functions 38 | */ 39 | he_plugin_chain_t *he_plugin_create_chain(void); 40 | 41 | /** 42 | * @brief Releases all memory allocated by Helium for this plugin chain 43 | * @param chain A pointer to a valid plugin chain 44 | * @note he_plugin_destroy_chain does NOT free the `plugin` objects registered to the plugin 45 | * chain. 46 | */ 47 | void he_plugin_destroy_chain(he_plugin_chain_t *chain); 48 | 49 | /** 50 | * @brief Register the plugin to the plugin chain 51 | * @param chain A pointer to a valid plugin chain 52 | * @param plugin A pointer to the *initialised* plugin struct 53 | * @return HE_SUCCESS Plugin was successfully registered 54 | * @return HE_ERR_NULL_POINTER Either parameter was NULL 55 | * @return HE_ERR_INIT_FAILED Registering the plugin failed 56 | * @note The plugin chain only keeps a reference to the plugin object. The caller is still 57 | * responsible for freeing the memory used by the `plugin` object after use. 58 | */ 59 | he_return_code_t he_plugin_register_plugin(he_plugin_chain_t *chain, plugin_struct_t *plugin); 60 | 61 | /** 62 | * @brief Execute the ingress function of each registered plugin 63 | * @param chain A pointer to a valid plugin chain 64 | * @param packet A pointer to the packet data 65 | * @param length A pointer to the length of the packet data. If the packet size changed after 66 | * processed by this function, the `length` will be set to the new length of the packet data. 67 | * @param capacity The length of the underlying buffer for packet 68 | * @return HE_SUCCESS All plugins executed successfully 69 | * @return HE_ERR_PLUGIN_DROP A plugin marked this packet for a drop 70 | * @return HE_ERR_FAILED An error occurred processing this packet 71 | * @note The content of packet may be modified, grow or shrunk, depending on the registered plugins 72 | */ 73 | he_return_code_t he_plugin_ingress(he_plugin_chain_t *chain, uint8_t *packet, size_t *length, 74 | size_t capacity); 75 | 76 | /** 77 | * @brief Execute the egress function of each registered plugin 78 | * @param chain A pointer to a valid plugin chain 79 | * @param packet A pointer to the packet data 80 | * @param length A pointer to the length of the packet data. If the packet size changed after 81 | * processed by this function, the `length` will be set to the new length of the packet data. 82 | * @param capacity The length of the underlying buffer for packet 83 | * @return HE_SUCCESS All plugins executed successfully 84 | * @return HE_ERR_PLUGIN_DROP A plugin marked this packet for a drop 85 | * @return HE_ERR_FAILED An error occurred processing this packet 86 | * @note The content of packet may be modified, grow or shrunk, depending on the registered plugins 87 | */ 88 | he_return_code_t he_plugin_egress(he_plugin_chain_t *chain, uint8_t *packet, size_t *length, 89 | size_t capacity); 90 | 91 | #endif // PLUGIN_CHAIN_H 92 | -------------------------------------------------------------------------------- /src/he/plugin_stats.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include "plugin_stats.h" 24 | 25 | // With apologies to https://github.com/zedshaw/liblcthw/blob/master/src/lcthw/stats.c 26 | 27 | static double stats_mean(stats_t *st) { 28 | return st->sum / st->n; 29 | } 30 | 31 | static double stats_stddev(stats_t *st) { 32 | return sqrt((st->sumsq - (st->sum * st->sum / st->n)) / (st->n - 1)); 33 | } 34 | 35 | static void stats_sample(stats_t *st, double s) { 36 | st->sum += s; 37 | st->sumsq += s * s; 38 | 39 | if(st->n == 0) { 40 | st->min = s; 41 | st->max = s; 42 | } else { 43 | if(st->min > s) st->min = s; 44 | if(st->max < s) st->max = s; 45 | } 46 | 47 | st->n += 1; 48 | } 49 | 50 | static void stats_dump(stats_t *st) { 51 | fprintf(stderr, 52 | "sum: %f, sumsq: %f, n: %ld, " 53 | "min: %f, max: %f, mean: %f, stddev: %f\n", 54 | st->sum, st->sumsq, st->n, st->min, st->max, stats_mean(st), stats_stddev(st)); 55 | } 56 | 57 | he_plugin_return_code_t stats_plugin_do_ingress(uint8_t *packet, size_t *length, size_t capacity, 58 | packet_stats_t *data) { 59 | if(data == NULL) { 60 | return HE_PLUGIN_FAIL; 61 | } 62 | 63 | stats_t *incoming = &data->incoming; 64 | 65 | stats_sample(incoming, *length); 66 | 67 | if(incoming->n % PACKET_SAMPLE_N == 0) { 68 | fprintf(stderr, "Ingress: "); 69 | stats_dump(incoming); 70 | } 71 | return HE_PLUGIN_SUCCESS; 72 | } 73 | 74 | he_plugin_return_code_t stats_plugin_do_egress(uint8_t *packet, size_t *length, size_t capacity, 75 | packet_stats_t *data) { 76 | if(data == NULL) { 77 | return HE_PLUGIN_FAIL; 78 | } 79 | 80 | stats_t *outgoing = &data->outgoing; 81 | 82 | stats_sample(outgoing, *length); 83 | 84 | if(outgoing->n % PACKET_SAMPLE_N == 0) { 85 | fprintf(stderr, "Egress: "); 86 | stats_dump(outgoing); 87 | } 88 | return HE_PLUGIN_SUCCESS; 89 | } 90 | 91 | he_plugin_return_code_t stats_plugin_create(plugin_struct_t *plugin_struct) { 92 | packet_stats_t *stats = calloc(1, sizeof(packet_stats_t)); 93 | if(stats == NULL) { 94 | return HE_PLUGIN_FAIL; 95 | } 96 | 97 | plugin_struct->do_ingress = (plugin_do_ingress)stats_plugin_do_ingress; 98 | plugin_struct->do_egress = (plugin_do_egress)stats_plugin_do_egress; 99 | plugin_struct->data = stats; 100 | 101 | return HE_PLUGIN_SUCCESS; 102 | } 103 | 104 | void stats_plugin_destroy(plugin_struct_t *plugin_struct) { 105 | if(plugin_struct && plugin_struct->data) { 106 | free(plugin_struct->data); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/he/plugin_stats.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file plugin_stats.h 22 | * @brief Example plugin implementation 23 | * 24 | */ 25 | 26 | #ifndef PLUGIN_STATS 27 | #define PLUGIN_STATS 28 | 29 | #include 30 | #include 31 | 32 | // This is the only "public" API 33 | he_plugin_return_code_t stats_plugin_create(plugin_struct_t *plugin_struct); 34 | void stats_plugin_destroy(plugin_struct_t *plugin_struct); 35 | 36 | // Everything else here is for testing 37 | 38 | #define PACKET_SAMPLE_N 100000 39 | 40 | typedef struct stats { 41 | double sum; 42 | double sumsq; 43 | unsigned long n; 44 | double min; 45 | double max; 46 | } stats_t; 47 | 48 | typedef struct packet_stats { 49 | stats_t incoming; 50 | stats_t outgoing; 51 | } packet_stats_t; 52 | 53 | he_plugin_return_code_t stats_plugin_do_ingress(uint8_t *packet, size_t *length, size_t capacity, 54 | packet_stats_t *data); 55 | he_plugin_return_code_t stats_plugin_do_egress(uint8_t *packet, size_t *length, size_t capacity, 56 | packet_stats_t *data); 57 | 58 | #endif // PLUGIN_STATS 59 | -------------------------------------------------------------------------------- /src/he/utils.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | #include 3 | 4 | #define DEFCASE(X) \ 5 | case X: \ 6 | return #X 7 | 8 | const char *he_return_code_name(he_return_code_t rc) { 9 | switch(rc) { 10 | DEFCASE(HE_SUCCESS); 11 | DEFCASE(HE_ERR_STRING_TOO_LONG); 12 | DEFCASE(HE_ERR_EMPTY_STRING); 13 | DEFCASE(HE_ERR_INVALID_CONN_STATE); 14 | DEFCASE(HE_ERR_NULL_POINTER); 15 | DEFCASE(HE_ERR_EMPTY_PACKET); 16 | DEFCASE(HE_ERR_PACKET_TOO_SMALL); 17 | DEFCASE(HE_ERR_ZERO_SIZE); 18 | DEFCASE(HE_ERR_NEGATIVE_NUMBER); 19 | DEFCASE(HE_ERR_INIT_FAILED); 20 | DEFCASE(HE_ERR_NO_MEMORY); 21 | DEFCASE(HE_ERR_NOT_HE_PACKET); 22 | DEFCASE(HE_ERR_SSL_BAD_FILETYPE); 23 | DEFCASE(HE_ERR_SSL_BAD_FILE); 24 | DEFCASE(HE_ERR_SSL_OUT_OF_MEMORY); 25 | DEFCASE(HE_ERR_SSL_ASN_INPUT); 26 | DEFCASE(HE_ERR_SSL_BUFFER); 27 | DEFCASE(HE_ERR_SSL_CERT); 28 | DEFCASE(HE_ERR_SSL_ERROR); 29 | DEFCASE(HE_ERR_CONF_USERNAME_NOT_SET); 30 | DEFCASE(HE_ERR_CONF_PASSWORD_NOT_SET); 31 | DEFCASE(HE_ERR_CONF_CA_NOT_SET); 32 | DEFCASE(HE_ERR_CONF_MTU_NOT_SET); 33 | DEFCASE(HE_WANT_READ); 34 | DEFCASE(HE_WANT_WRITE); 35 | DEFCASE(HE_ERR_CONF_OUTSIDE_WRITE_CB_NOT_SET); 36 | DEFCASE(HE_ERR_CONNECT_FAILED); 37 | DEFCASE(HE_CONNECTION_TIMED_OUT); 38 | DEFCASE(HE_ERR_NOT_CONNECTED); 39 | DEFCASE(HE_ERR_UNSUPPORTED_PACKET_TYPE); 40 | DEFCASE(HE_ERR_CONNECTION_WAS_CLOSED); 41 | DEFCASE(HE_ERR_BAD_PACKET); 42 | DEFCASE(HE_ERR_CALLBACK_FAILED); 43 | DEFCASE(HE_ERR_FAILED); 44 | DEFCASE(HE_ERR_SERVER_DN_MISMATCH); 45 | DEFCASE(HE_ERR_CANNOT_VERIFY_SERVER_CERT); 46 | DEFCASE(HE_ERR_NEVER_CONNECTED); 47 | DEFCASE(HE_ERR_INVALID_MTU_SIZE); 48 | DEFCASE(HE_ERR_CLEANUP_FAILED); 49 | DEFCASE(HE_ERR_REJECTED_SESSION); 50 | DEFCASE(HE_ERR_ACCESS_DENIED); 51 | DEFCASE(HE_ERR_PACKET_TOO_LARGE); 52 | DEFCASE(HE_ERR_INACTIVITY_TIMEOUT); 53 | DEFCASE(HE_ERR_POINTER_WOULD_OVERFLOW); 54 | DEFCASE(HE_ERR_INVALID_CONNECTION_TYPE); 55 | DEFCASE(HE_ERR_RNG_FAILURE); 56 | DEFCASE(HE_ERR_CONF_AUTH_CB_NOT_SET); 57 | DEFCASE(HE_ERR_PLUGIN_DROP); 58 | DEFCASE(HE_ERR_UNKNOWN_SESSION); 59 | DEFCASE(HE_ERR_SSL_ERROR_NONFATAL); 60 | DEFCASE(HE_ERR_INCORRECT_PROTOCOL_VERSION); 61 | DEFCASE(HE_ERR_CONF_CONFLICTING_AUTH_METHODS); 62 | DEFCASE(HE_ERR_ACCESS_DENIED_NO_AUTH_USERPASS_HANDLER); 63 | DEFCASE(HE_ERR_ACCESS_DENIED_NO_AUTH_BUF_HANDLER); 64 | DEFCASE(HE_ERR_SERVER_GOODBYE); 65 | DEFCASE(HE_ERR_INVALID_AUTH_TYPE); 66 | DEFCASE(HE_ERR_ACCESS_DENIED_NO_AUTH_TOKEN_HANDLER); 67 | DEFCASE(HE_ERR_PMTUD_CALLBACKS_NOT_SET); 68 | DEFCASE(HE_ERR_BAD_FRAGMENT); 69 | DEFCASE(HE_ERR_SECURE_RENEGOTIATION_ERROR); 70 | } 71 | return "HE_ERR_UNKNOWN"; 72 | } 73 | 74 | const char *he_client_state_name(he_conn_state_t st) { 75 | switch(st) { 76 | DEFCASE(HE_STATE_NONE); 77 | DEFCASE(HE_STATE_DISCONNECTED); 78 | DEFCASE(HE_STATE_CONNECTING); 79 | DEFCASE(HE_STATE_DISCONNECTING); 80 | DEFCASE(HE_STATE_AUTHENTICATING); 81 | DEFCASE(HE_STATE_LINK_UP); 82 | DEFCASE(HE_STATE_ONLINE); 83 | DEFCASE(HE_STATE_CONFIGURING); 84 | } 85 | return "HE_STATE_UNKNOWN"; 86 | } 87 | 88 | const char *he_client_event_name(he_conn_event_t ev) { 89 | switch(ev) { 90 | DEFCASE(HE_EVENT_FIRST_MESSAGE_RECEIVED); 91 | DEFCASE(HE_EVENT_PONG); 92 | DEFCASE(HE_EVENT_REJECTED_FRAGMENTED_PACKETS_SENT_BY_HOST); 93 | DEFCASE(HE_EVENT_SECURE_RENEGOTIATION_STARTED); 94 | DEFCASE(HE_EVENT_SECURE_RENEGOTIATION_COMPLETED); 95 | DEFCASE(HE_EVENT_PENDING_SESSION_ACKNOWLEDGED); 96 | } 97 | return "HE_EVENT_UNKNOWN"; 98 | } 99 | 100 | const char *he_connection_protocol_name(he_connection_protocol_t protocol) { 101 | switch(protocol) { 102 | DEFCASE(HE_CONNECTION_PROTOCOL_NONE); 103 | DEFCASE(HE_CONNECTION_PROTOCOL_TLS_1_3); 104 | DEFCASE(HE_CONNECTION_PROTOCOL_DTLS_1_2); 105 | DEFCASE(HE_CONNECTION_PROTOCOL_DTLS_1_3); 106 | } 107 | return "HE_CONNECTION_PROTOCOL_UNKNOWN"; 108 | } 109 | 110 | const char *he_pmtud_state_name(he_pmtud_state_t state) { 111 | switch(state) { 112 | DEFCASE(HE_PMTUD_STATE_DISABLED); 113 | DEFCASE(HE_PMTUD_STATE_BASE); 114 | DEFCASE(HE_PMTUD_STATE_SEARCHING); 115 | DEFCASE(HE_PMTUD_STATE_SEARCH_COMPLETE); 116 | DEFCASE(HE_PMTUD_STATE_ERROR); 117 | } 118 | return "HE_STATE_UNKNOWN"; 119 | } 120 | 121 | #undef DEFCASE 122 | 123 | char *he_safe_strncpy(char *dst, const char *src, size_t dst_size) { 124 | assert(NULL != dst && NULL != src && 0 != dst_size); 125 | 126 | char *res = strncpy(dst, src, dst_size - 1); 127 | dst[dst_size - 1] = '\0'; 128 | return res; 129 | } 130 | -------------------------------------------------------------------------------- /src/he/utils.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2022 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file utils.h 22 | * @brief Utility functions for ease of use 23 | * 24 | */ 25 | 26 | #ifndef UTILS_H 27 | #define UTILS_H 28 | 29 | #include "he.h" 30 | 31 | /** 32 | * Returns stringified version of an he_return_code_t. 33 | * @return The stringified name of the return code `rc` or `"HE_ERR_UNKNOWN"`. 34 | */ 35 | const char *he_return_code_name(he_return_code_t rc); 36 | 37 | /** 38 | * Returns stringified version of an he_conn_state_t. 39 | * @return The stringified name of the state `st` or `"HE_STATE_UNKNOWN"`. 40 | */ 41 | const char *he_client_state_name(he_conn_state_t st); 42 | 43 | /** 44 | * Returns stringified version of an he_conn_event_t. 45 | * @return The stringified name of the event `ev` or `"HE_EVENT_UNKNOWN"`. 46 | */ 47 | const char *he_client_event_name(he_conn_event_t ev); 48 | 49 | /** 50 | * Returns stringified version of an he_connection_protocol_t. 51 | * @return The stringified name of the protocol `protocol` or `"HE_CONNECTION_PROTOCOL_UNKNOWN"`. 52 | */ 53 | const char *he_connection_protocol_name(he_connection_protocol_t protocol); 54 | 55 | /** 56 | * Returns stringified version of an he_pmtud_state_t. 57 | */ 58 | const char *he_pmtud_state_name(he_pmtud_state_t state); 59 | 60 | /** 61 | * @brief Safe version of strncpy 62 | * strncpy has a pitfall that `dst` will not be null terminated if there is no null byte 63 | * in the first `dst_size` bytes of the array pointed to by `src` 64 | * This function is a wrapper over strncpy which adds null byte as the last byte 65 | * @param dst Pointer to the destination char array 66 | * @param src Pointer to the source char array 67 | * @param dst_size size of the destination char array 68 | */ 69 | char *he_safe_strncpy(char *dst, const char *src, size_t dst_size); 70 | 71 | #endif // UTILS_H 72 | -------------------------------------------------------------------------------- /src/he/wolf.h: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | /** 21 | * @file wolf.h 22 | * @brief Functions for interfacing with WolfSSL 23 | * 24 | */ 25 | 26 | #ifndef WOLF_H 27 | #define WOLF_H 28 | 29 | #ifndef WOLFSSL_USER_SETTINGS 30 | #include 31 | #endif 32 | #include 33 | #include 34 | #include "conn_internal.h" 35 | 36 | /** 37 | * @brief Callback function to handle WolfSSL read requests 38 | * @param ssl A pointer to the WolfSSL session that this callback relates to 39 | * @param buf A pointer to the buffer the callback writes data to 40 | * @param sz The maximum size that can be written to the buffer 41 | * @param ctx A pointer to the Helium context that this callback relates to 42 | * @return int The length of the data copied to the buffer 43 | * @return WOLFSSL_CBIO_ERR_WANT_READ Tells WolfSSL that there's no more data available 44 | * 45 | * Helium does not know about sockets and as such, neither can WolfSSL. Helium 46 | * overrides the standard socket calls with its own callback functions. 47 | * 48 | * This function simply copies data to WolfSSL's buffer and returns 49 | * 50 | * @note This function will be called twice per packet. This function will return 51 | * WOLFSSL_CBIO_ERR_WANT_READ on the second call. 52 | * 53 | */ 54 | 55 | int he_wolf_dtls_read(WOLFSSL *ssl, char *buf, int sz, void *ctx); 56 | 57 | /** 58 | * @brief Callback function to handle WolfSSL write requests 59 | * @param ssl A pointer to the WolfSSL session that this callback relates to 60 | * @param buf A pointer to the buffer the callback reads data from 61 | * @param sz The size of the data to be read 62 | * @param ctx A pointer to the Helium context that this callback relates to 63 | * @return int The length of the data copied to the buffer 64 | * 65 | * Helium does not know about sockets and as such, neither can WolfSSL. Helium 66 | * overrides the standard socket calls with its own callback functions. 67 | * 68 | * This function simply calls the user provided write callback 69 | * 70 | * @note The buffer is only valid until this function returns. As such the user provided write 71 | * callback must copy the data from the buffer if it needs it to persist after that time. 72 | */ 73 | 74 | int he_wolf_dtls_write(WOLFSSL *ssl, char *buf, int sz, void *ctx); 75 | 76 | /** 77 | * @brief Write the packet header into the header buffer 78 | * @param conn A pointer to a valid conn context 79 | * @param hdr A pointer to the header buffer to initialise 80 | * @return HE_SUCCESS Header has been initialised 81 | * @return HE_ERR_NULL_POINTER Either the conn or header pointers were NULL 82 | */ 83 | int he_internal_write_packet_header(he_conn_t *conn, he_wire_hdr_t *hdr); 84 | 85 | /** 86 | * @brief Callback function to handle TLS WolfSSL read requests 87 | * @param ssl A pointer to the WolfSSL session that this callback relates to 88 | * @param buf A pointer to the buffer the callback writes data to 89 | * @param sz The maximum size that can be written to the buffer 90 | * @param ctx A pointer to the Helium context that this callback relates to 91 | * @return int The length of the data copied to the buffer 92 | * @return WOLFSSL_CBIO_ERR_WANT_READ Tells WolfSSL that there's no more data available 93 | * 94 | * Helium does not know about sockets and as such, neither can WolfSSL. Helium 95 | * overrides the standard socket calls with its own callback functions. 96 | * 97 | * This function simply copies data to WolfSSL's buffer and returns 98 | * 99 | * @note This function will be called twice per packet. This function will return 100 | * WOLFSSL_CBIO_ERR_WANT_READ on the second call. 101 | * 102 | */ 103 | int he_wolf_tls_read(WOLFSSL *ssl, char *buf, int sz, void *ctx); 104 | 105 | // Todo document this 106 | int he_wolf_tls_write(WOLFSSL *ssl, char *buf, int sz, void *ctx); 107 | 108 | typedef struct he_internal_write_buf_ { 109 | uint8_t buf[HE_MAX_WIRE_MTU]; 110 | } he_internal_write_buf_t; 111 | 112 | int he_wolf_dtls_write_internal(WOLFSSL *ssl, char *buf, int sz, void *ctx, he_internal_write_buf_t *write_buffer); 113 | int he_wolf_tls_write_internal(WOLFSSL *ssl, char *buf, int sz, void *ctx, he_internal_write_buf_t *write_buffer); 114 | 115 | #endif // WOLF_H 116 | -------------------------------------------------------------------------------- /test/he/test_client.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "he.h" 21 | #include "he_internal.h" 22 | 23 | #include 24 | #include "test_defs.h" 25 | 26 | #include "client.h" 27 | 28 | #include "mock_ssl_ctx.h" 29 | #include "mock_conn.h" 30 | #include "mock_plugin_chain.h" 31 | 32 | #include "mock_memory.h" 33 | 34 | he_ssl_ctx_t ssl_ctx = {0}; 35 | he_conn_t conn = {0}; 36 | he_plugin_chain_t inside_plugins = {0}; 37 | he_plugin_chain_t outside_plugins = {0}; 38 | he_client_t *client = {0}; 39 | 40 | void setUp(void) { 41 | client = calloc(1, sizeof(he_client_t)); 42 | } 43 | 44 | void tearDown(void) { 45 | free(client); 46 | } 47 | 48 | void test_client_create_fails_initial_calloc(void) { 49 | he_calloc_ExpectAnyArgsAndReturn(NULL); 50 | he_client_t *test_client = he_client_create(); 51 | 52 | TEST_ASSERT_NULL(test_client); 53 | } 54 | 55 | void setup_create_expectations(he_ssl_ctx_t *ctx1, he_conn_t *conn1, 56 | he_plugin_chain_t *inside_plugins1, 57 | he_plugin_chain_t *outside_plugins1) { 58 | he_calloc_ExpectAnyArgsAndReturn(client); 59 | 60 | he_ssl_ctx_create_ExpectAndReturn(ctx1); 61 | he_conn_create_ExpectAndReturn(conn1); 62 | he_plugin_create_chain_ExpectAndReturn(inside_plugins1); 63 | he_plugin_create_chain_ExpectAndReturn(outside_plugins1); 64 | 65 | if(ctx1 == NULL || conn1 == NULL || inside_plugins1 == NULL || outside_plugins1 == NULL) { 66 | he_conn_destroy_ExpectAnyArgs(); 67 | he_ssl_ctx_destroy_ExpectAnyArgs(); 68 | he_plugin_destroy_chain_ExpectAnyArgs(); 69 | he_plugin_destroy_chain_ExpectAnyArgs(); 70 | he_free_ExpectAnyArgs(); 71 | } 72 | } 73 | 74 | void test_client_create_failures(void) { 75 | setup_create_expectations(NULL, &conn, &inside_plugins, &outside_plugins); 76 | he_client_t *test_client = he_client_create(); 77 | TEST_ASSERT_EQUAL(NULL, test_client); 78 | 79 | setup_create_expectations(&ssl_ctx, NULL, &inside_plugins, &outside_plugins); 80 | test_client = he_client_create(); 81 | TEST_ASSERT_EQUAL(NULL, test_client); 82 | 83 | setup_create_expectations(&ssl_ctx, &conn, NULL, &outside_plugins); 84 | test_client = he_client_create(); 85 | TEST_ASSERT_EQUAL(NULL, test_client); 86 | 87 | setup_create_expectations(&ssl_ctx, &conn, &inside_plugins, NULL); 88 | test_client = he_client_create(); 89 | TEST_ASSERT_EQUAL(NULL, test_client); 90 | } 91 | 92 | void test_client_create_succeeds(void) { 93 | setup_create_expectations(&ssl_ctx, &conn, &inside_plugins, &outside_plugins); 94 | 95 | he_client_t *test_client = he_client_create(); 96 | 97 | TEST_ASSERT_EQUAL(client, test_client); 98 | } 99 | 100 | void test_client_destroy_nullsafe(void) { 101 | he_client_destroy(NULL); 102 | } 103 | 104 | void test_client_destroy_destroys_it_all(void) { 105 | he_client_t *client = calloc(1, sizeof(he_client_t)); 106 | client->ssl_ctx = &ssl_ctx; 107 | client->conn = &conn; 108 | client->inside_plugins = &inside_plugins; 109 | client->outside_plugins = &outside_plugins; 110 | 111 | he_conn_destroy_Expect(&conn); 112 | he_ssl_ctx_destroy_Expect(&ssl_ctx); 113 | he_plugin_destroy_chain_Expect(&inside_plugins); 114 | he_plugin_destroy_chain_Expect(&outside_plugins); 115 | he_free_Expect(client); 116 | 117 | he_client_destroy(client); 118 | } 119 | 120 | void test_connect_disconnect_valid_nulls(void) { 121 | TEST_ASSERT_EQUAL(HE_ERR_NULL_POINTER, he_client_connect(NULL)); 122 | TEST_ASSERT_EQUAL(HE_ERR_NULL_POINTER, he_client_disconnect(NULL)); 123 | TEST_ASSERT_EQUAL(HE_ERR_NULL_POINTER, he_client_is_config_valid(NULL)); 124 | } 125 | 126 | void test_connect_bad_ssl_ctx(void) { 127 | he_ssl_ctx_start_ExpectAnyArgsAndReturn(HE_ERR_FAILED); 128 | 129 | int res = he_client_connect(client); 130 | 131 | TEST_ASSERT_EQUAL(HE_ERR_FAILED, res); 132 | } 133 | 134 | void test_connect_bad_conn(void) { 135 | he_ssl_ctx_start_ExpectAnyArgsAndReturn(HE_SUCCESS); 136 | he_conn_client_connect_ExpectAnyArgsAndReturn(HE_ERR_FAILED); 137 | 138 | int res = he_client_connect(client); 139 | 140 | TEST_ASSERT_EQUAL(HE_ERR_FAILED, res); 141 | } 142 | 143 | void test_connect_succeeds(void) { 144 | he_ssl_ctx_start_ExpectAnyArgsAndReturn(HE_SUCCESS); 145 | he_conn_client_connect_ExpectAnyArgsAndReturn(HE_SUCCESS); 146 | 147 | int res = he_client_connect(client); 148 | 149 | TEST_ASSERT_EQUAL(HE_SUCCESS, res); 150 | } 151 | 152 | void test_disconnect_bad_ssl_ctx(void) { 153 | he_ssl_ctx_stop_ExpectAnyArgsAndReturn(HE_ERR_FAILED); 154 | 155 | int res = he_client_disconnect(client); 156 | 157 | TEST_ASSERT_EQUAL(HE_ERR_FAILED, res); 158 | } 159 | 160 | void test_disconnect_bad_conn(void) { 161 | he_ssl_ctx_stop_ExpectAnyArgsAndReturn(HE_SUCCESS); 162 | he_conn_disconnect_ExpectAnyArgsAndReturn(HE_ERR_FAILED); 163 | 164 | int res = he_client_disconnect(client); 165 | 166 | TEST_ASSERT_EQUAL(HE_ERR_FAILED, res); 167 | } 168 | 169 | void test_disconnect_succeeds(void) { 170 | he_ssl_ctx_stop_ExpectAnyArgsAndReturn(HE_SUCCESS); 171 | he_conn_disconnect_ExpectAnyArgsAndReturn(HE_SUCCESS); 172 | 173 | int res = he_client_disconnect(client); 174 | 175 | TEST_ASSERT_EQUAL(HE_SUCCESS, res); 176 | } 177 | 178 | void test_is_valid_bad_ssl_ctx(void) { 179 | he_ssl_ctx_is_valid_client_ExpectAnyArgsAndReturn(HE_ERR_CONF_CA_NOT_SET); 180 | 181 | int res = he_client_is_config_valid(client); 182 | 183 | TEST_ASSERT_EQUAL(HE_ERR_CONF_CA_NOT_SET, res); 184 | } 185 | 186 | void test_is_valid_bad_conn(void) { 187 | he_ssl_ctx_is_valid_client_ExpectAnyArgsAndReturn(HE_SUCCESS); 188 | he_conn_is_valid_client_ExpectAnyArgsAndReturn(HE_ERR_CONF_USERNAME_NOT_SET); 189 | 190 | int res = he_client_is_config_valid(client); 191 | 192 | TEST_ASSERT_EQUAL(HE_ERR_CONF_USERNAME_NOT_SET, res); 193 | } 194 | 195 | void test_is_valid_succeeds(void) { 196 | he_ssl_ctx_is_valid_client_ExpectAnyArgsAndReturn(HE_SUCCESS); 197 | he_conn_is_valid_client_ExpectAnyArgsAndReturn(HE_SUCCESS); 198 | 199 | int res = he_client_is_config_valid(client); 200 | 201 | TEST_ASSERT_EQUAL(HE_SUCCESS, res); 202 | } 203 | -------------------------------------------------------------------------------- /test/he/test_config.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "he.h" 21 | #include "he_internal.h" 22 | 23 | #include 24 | #include "test_defs.h" 25 | 26 | // Unit under test 27 | #include "config.h" 28 | 29 | he_conn_t *conn; 30 | 31 | // 50 32 | char *max_string = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 33 | 34 | void setUp(void) { 35 | conn = calloc(1, sizeof(he_conn_t)); 36 | } 37 | 38 | void tearDown(void) { 39 | free(conn); 40 | } 41 | 42 | void test_he_config_set_string_okay(void) { 43 | TEST_ASSERT_EQUAL_STRING("", conn->username); 44 | 45 | int res1 = he_internal_set_config_string(conn->username, good_username); 46 | 47 | TEST_ASSERT_EQUAL_STRING(good_username, conn->username); 48 | TEST_ASSERT_EQUAL(HE_SUCCESS, res1); 49 | } 50 | 51 | void test_he_config_set_string_too_long(void) { 52 | TEST_ASSERT_EQUAL_STRING("", conn->username); 53 | 54 | int res1 = he_internal_set_config_string(conn->username, bad_string_too_long); 55 | 56 | TEST_ASSERT_EQUAL_STRING("", conn->username); 57 | TEST_ASSERT_EQUAL(HE_ERR_STRING_TOO_LONG, res1); 58 | } 59 | 60 | void test_he_config_set_string_empty(void) { 61 | TEST_ASSERT_EQUAL_STRING("", conn->username); 62 | 63 | int res1 = he_internal_set_config_string(conn->username, ""); 64 | 65 | TEST_ASSERT_EQUAL_STRING("", conn->username); 66 | TEST_ASSERT_EQUAL(HE_ERR_EMPTY_STRING, res1); 67 | } 68 | 69 | void test_config_string_too_long(void) { 70 | bool res = he_internal_config_is_string_length_okay(bad_string_too_long); 71 | TEST_ASSERT_FALSE(res); 72 | } 73 | 74 | void test_config_string_okay_length(void) { 75 | bool res = he_internal_config_is_string_length_okay(max_string); 76 | TEST_ASSERT_TRUE(res); 77 | } 78 | 79 | void test_config_string_is_empty(void) { 80 | bool res = he_internal_config_is_empty_string(""); 81 | TEST_ASSERT_TRUE(res); 82 | } 83 | 84 | void test_config_string_is_not_empty(void) { 85 | bool res = he_internal_config_is_empty_string("123"); 86 | TEST_ASSERT_FALSE(res); 87 | } 88 | 89 | void test_config_string_field_is_not_null(void) { 90 | int res = he_internal_set_config_string(NULL, good_username); 91 | TEST_ASSERT_EQUAL(HE_ERR_NULL_POINTER, res); 92 | } 93 | 94 | void test_config_string_value_is_not_null(void) { 95 | int res = he_internal_set_config_string(conn->username, NULL); 96 | TEST_ASSERT_EQUAL(HE_ERR_NULL_POINTER, res); 97 | } -------------------------------------------------------------------------------- /test/he/test_core.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "he.h" 21 | #include "he_internal.h" 22 | 23 | #include 24 | #include "test_defs.h" 25 | 26 | #include "mock_conn.h" 27 | 28 | // Unit under test 29 | #include "core.h" 30 | 31 | he_conn_t *conn; 32 | 33 | void setUp(void) { 34 | conn = calloc(1, sizeof(he_conn_t)); 35 | } 36 | 37 | void tearDown(void) { 38 | free(conn); 39 | } 40 | 41 | void test_he_internal_stream_setup_state_overwrite(void) { 42 | he_conn_set_ssl_error_Expect(conn, 0); 43 | 44 | conn->incoming_data_left_to_read = 42; 45 | int res = he_internal_setup_stream_state(conn, empty_data, sizeof(empty_data)); 46 | 47 | TEST_ASSERT_EQUAL(HE_ERR_SSL_ERROR, res); 48 | } 49 | -------------------------------------------------------------------------------- /test/he/test_memory.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "he.h" 21 | #include "he_internal.h" 22 | 23 | #include 24 | #include "test_defs.h" 25 | 26 | // Unit under test 27 | #include "memory.h" 28 | 29 | static int malloc_calls = 0; 30 | static int calloc_calls = 0; 31 | static int realloc_calls = 0; 32 | static int free_calls = 0; 33 | 34 | void setUp(void) { 35 | malloc_calls = 0; 36 | calloc_calls = 0; 37 | realloc_calls = 0; 38 | free_calls = 0; 39 | } 40 | 41 | void tearDown(void) { 42 | } 43 | 44 | void *malloc_for_test(size_t size) { 45 | malloc_calls++; 46 | return NULL; 47 | } 48 | 49 | void *calloc_for_test(size_t nmemb, size_t size) { 50 | calloc_calls++; 51 | return NULL; 52 | } 53 | 54 | void *realloc_for_test(void *ptr, size_t size) { 55 | realloc_calls++; 56 | return NULL; 57 | } 58 | 59 | void free_for_test(void *ptr) { 60 | free_calls++; 61 | } 62 | 63 | void test_default_malloc_calloc_free(void) { 64 | int *malloced = he_malloc(sizeof(int)); 65 | TEST_ASSERT_NOT_NULL(malloced); 66 | 67 | int *calloced = he_calloc(1, sizeof(int)); 68 | TEST_ASSERT_NOT_NULL(calloced); 69 | TEST_ASSERT_EQUAL(0, *calloced); 70 | 71 | calloced = he_realloc(calloced, 2 * sizeof(int)); 72 | TEST_ASSERT_NOT_NULL(calloced); 73 | TEST_ASSERT_EQUAL(0, *calloced); 74 | 75 | he_free(malloced); 76 | he_free(calloced); 77 | } 78 | 79 | void test_custom_malloc_calloc_free(void) { 80 | he_set_allocators(malloc_for_test, calloc_for_test, realloc_for_test, free_for_test); 81 | 82 | int *malloced = he_malloc(sizeof(int)); 83 | TEST_ASSERT_NULL(malloced); 84 | TEST_ASSERT_EQUAL(1, malloc_calls); 85 | 86 | int *calloced = he_calloc(1, sizeof(int)); 87 | TEST_ASSERT_NULL(calloced); 88 | TEST_ASSERT_EQUAL(1, calloc_calls); 89 | 90 | calloced = he_realloc(calloced, sizeof(int)); 91 | TEST_ASSERT_NULL(calloced); 92 | TEST_ASSERT_EQUAL(1, realloc_calls); 93 | 94 | he_free(malloced); 95 | TEST_ASSERT_EQUAL(1, free_calls); 96 | } 97 | -------------------------------------------------------------------------------- /test/he/test_network.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "network.h" 4 | #include "test_defs.h" 5 | 6 | void test_he_internal_is_ipv4_packet_valid_null_packet(void) { 7 | // Test with a NULL packet 8 | bool res = he_internal_is_ipv4_packet_valid(NULL, 0); 9 | TEST_ASSERT_EQUAL(false, res); 10 | } 11 | 12 | void test_he_internal_is_ipv4_packet_valid(void) { 13 | // Test with a Valid packet 14 | bool res = he_internal_is_ipv4_packet_valid(fake_ipv4_packet, sizeof(fake_ipv4_packet)); 15 | TEST_ASSERT_EQUAL(true, res); 16 | } 17 | 18 | void test_he_internal_is_ipv4_packet_valid_invalid_packet(void) { 19 | // Test with a invalid packet 20 | bool res = he_internal_is_ipv4_packet_valid(bad_fake_ipv4_packet, sizeof(bad_fake_ipv4_packet)); 21 | TEST_ASSERT_EQUAL(false, res); 22 | } 23 | 24 | void test_he_internal_is_ipv4_packet_valid_packet_too_small(void) { 25 | // Test with too small a packet 26 | bool res = he_internal_is_ipv4_packet_valid(fake_ipv4_packet, sizeof(ipv4_header_t) - 1); 27 | TEST_ASSERT_EQUAL(false, res); 28 | } 29 | -------------------------------------------------------------------------------- /test/he/test_plugin_stats.c: -------------------------------------------------------------------------------- 1 | /* * 2 | * Lightway Core 3 | * Copyright (C) 2021 Express VPN International Ltd. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "he.h" 21 | #include "he_internal.h" 22 | 23 | #include 24 | #include "test_defs.h" 25 | 26 | // Unit under test 27 | #include "plugin_stats.h" 28 | 29 | packet_stats_t stats; 30 | plugin_struct_t plugin = {0}; 31 | 32 | const int NUM_SAMPLES = 10; 33 | size_t samples[] = {61061334, 96783204, 12747090, 82395131, 3333483, 34 | 69755066, 10626275, 76587523, 49382973, 95788115}; 35 | 36 | stats_t expect = { 37 | .sumsq = 42516409741139184, 38 | .sum = 558460194, 39 | .min = 3333483, 40 | .max = 96783204, 41 | .n = 10, 42 | }; 43 | 44 | void setUp(void) { 45 | int res = stats_plugin_create(&plugin); 46 | TEST_ASSERT_EQUAL(HE_PLUGIN_SUCCESS, res); 47 | TEST_ASSERT_NOT_NULL(plugin.data); 48 | } 49 | 50 | void tearDown(void) { 51 | stats_plugin_destroy(&plugin); 52 | memset(&plugin, 0, sizeof(plugin_struct_t)); 53 | memset(&stats, 0, sizeof(packet_stats_t)); 54 | } 55 | 56 | void test_construction(void) { 57 | TEST_ASSERT_EQUAL(0, stats.incoming.n); 58 | TEST_ASSERT_EQUAL(0, stats.outgoing.n); 59 | } 60 | 61 | static void internal_test_stats(stats_t *st) { 62 | TEST_ASSERT_EQUAL(expect.sumsq, st->sumsq); 63 | TEST_ASSERT_EQUAL(expect.sum, st->sum); 64 | TEST_ASSERT_EQUAL(expect.min, st->min); 65 | TEST_ASSERT_EQUAL(expect.max, st->max); 66 | TEST_ASSERT_EQUAL(expect.n, st->n); 67 | } 68 | 69 | void test_operations(void) { 70 | for(int i = 0; i < NUM_SAMPLES; i++) { 71 | stats_plugin_do_ingress(NULL, &samples[i], samples[i], &stats); 72 | stats_plugin_do_egress(NULL, &samples[i], samples[i], &stats); 73 | } 74 | 75 | internal_test_stats(&stats.incoming); 76 | internal_test_stats(&stats.outgoing); 77 | } 78 | 79 | void test_operations_through_plugin_api(void) { 80 | for(int i = 0; i < NUM_SAMPLES; i++) { 81 | plugin.do_ingress(NULL, &samples[i], samples[i], plugin.data); 82 | } 83 | 84 | packet_stats_t *packet_stats = (packet_stats_t *)plugin.data; 85 | 86 | internal_test_stats(&packet_stats->incoming); 87 | } 88 | 89 | void test_null(void) { 90 | int res = stats_plugin_do_ingress(NULL, &samples[0], samples[0], NULL); 91 | TEST_ASSERT_EQUAL(res, HE_PLUGIN_FAIL); 92 | 93 | res = stats_plugin_do_egress(NULL, &samples[0], samples[0], NULL); 94 | TEST_ASSERT_EQUAL(res, HE_PLUGIN_FAIL); 95 | 96 | // Just make sure it doesn't blow up 97 | stats_plugin_destroy(NULL); 98 | 99 | plugin_struct_t empty_plugin = {0}; 100 | 101 | stats_plugin_destroy(&empty_plugin); 102 | } 103 | 104 | void test_print_doesnt_explode(void) { 105 | // No sane way to verify the fprint output but will at least make sure we get it here 106 | stats.incoming.n = PACKET_SAMPLE_N - 1; 107 | int res = stats_plugin_do_ingress(NULL, &samples[0], samples[0], &stats); 108 | TEST_ASSERT_EQUAL(HE_PLUGIN_SUCCESS, res); 109 | 110 | stats.outgoing.n = PACKET_SAMPLE_N - 1; 111 | res = stats_plugin_do_egress(NULL, &samples[0], samples[0], &stats); 112 | TEST_ASSERT_EQUAL(HE_PLUGIN_SUCCESS, res); 113 | } 114 | -------------------------------------------------------------------------------- /test/support/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressvpn/lightway-core/376df03bb311a7e65ba221a62c3512426380df10/test/support/.gitkeep -------------------------------------------------------------------------------- /test/support/fake_dispatch.h: -------------------------------------------------------------------------------- 1 | #ifndef _HE_FAKE_DISPATCH 2 | #define _HE_FAKE_DISPATCH 3 | 4 | #include 5 | #include "he.h" 6 | #include "conn_internal.h" 7 | 8 | /** 9 | * This function should NEVER be defined and only used in test files by 10 | * #include "mock_fake_dispatch.h" 11 | */ 12 | int dispatch(char *func, ...); 13 | 14 | /** 15 | * This function should NEVER be defined and only used in test files by 16 | * #include "mock_fake_dispatch.h" 17 | */ 18 | int dispatch_conn(char *func, he_conn_t *client); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /test/support/fake_rng.h: -------------------------------------------------------------------------------- 1 | #ifndef _HE_FAKE_RNG 2 | #define _HE_FAKE_RNG 3 | 4 | #include "he.h" 5 | #include "he_internal.h" 6 | 7 | /** 8 | * This function should NEVER be defined and only used in test files by 9 | * #include "mock_fake_rng.h" 10 | */ 11 | int wc_InitRng(RNG *rng); 12 | 13 | /** 14 | * This function should NEVER be defined and only used in test files by 15 | * #include "mock_fake_rng.h" 16 | */ 17 | int wc_RNG_GenerateBlock(RNG *rng, byte *bytes, uint32_t sz); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /test/support/test_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef HE_TEST_DEFS 2 | #define HE_TEST_DEFS 3 | 4 | #define FIXTURE_FATAL_ERROR -1 5 | 6 | char *bad_string_too_long = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 7 | 8 | char *good_username = "fsdfkjsfrwejkr"; 9 | char *good_password = "dsgfdfgghgfhgf"; 10 | char *good_hostname = "server1.expressvpn.com"; 11 | 12 | uint8_t fake_cert[] = {0x10, 0x11, 0x12, 0x13, 0x14}; 13 | 14 | uint8_t empty_data[1500] = {0}; 15 | 16 | uint8_t fake_ipv4_packet[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 17 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 18 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 19 | 20 | uint8_t bad_fake_ipv4_packet[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 22 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 23 | 24 | uint8_t fake_he_packet[] = {0x48, 0x65, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 25 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 26 | 27 | uint8_t fake_he_packet_session_reject[] = {0x48, 0x65, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 28 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 29 | 30 | uint16_t calculate_wolf_mtu(uint16_t he_mtu) { 31 | return he_mtu - HE_PACKET_OVERHEAD + HE_WOLF_MAX_HEADER_SIZE; 32 | } 33 | 34 | int call_counter; 35 | 36 | he_return_code_t write_cb(he_conn_t *conn, uint8_t *packet, size_t length, void *context) { 37 | call_counter++; 38 | return HE_SUCCESS; 39 | } 40 | 41 | he_return_code_t state_cb(he_conn_t *conn, he_conn_state_t new_state, void *context) { 42 | call_counter++; 43 | return HE_SUCCESS; 44 | } 45 | 46 | he_return_code_t nudge_time_cb(he_conn_t *conn, int timeout, void *context) { 47 | call_counter++; 48 | return HE_SUCCESS; 49 | } 50 | 51 | he_return_code_t network_config_ipv4_cb(he_conn_t *conn, he_network_config_ipv4_t *config, 52 | void *context) { 53 | call_counter++; 54 | return HE_SUCCESS; 55 | } 56 | 57 | he_return_code_t server_config_cb(he_conn_t *conn, uint8_t *buffer, size_t length, void *context) { 58 | call_counter++; 59 | return HE_SUCCESS; 60 | } 61 | 62 | he_return_code_t state_change_cb(he_conn_t *conn, he_conn_state_t new_state, void *context) { 63 | call_counter++; 64 | return HE_SUCCESS; 65 | } 66 | 67 | he_return_code_t event_cb(he_conn_t *conn, he_conn_event_t event, void *context) { 68 | call_counter++; 69 | return HE_SUCCESS; 70 | } 71 | 72 | bool auth_cb(he_conn_t *conn, char const *username, char const *password, void *context) { 73 | call_counter++; 74 | return HE_SUCCESS; 75 | } 76 | 77 | bool auth_buf_cb(he_conn_t *conn, uint8_t auth_type, uint8_t *buffer, uint16_t length, 78 | void *context) { 79 | call_counter++; 80 | return HE_SUCCESS; 81 | } 82 | 83 | he_return_code_t pop_network_config_cb(he_conn_t *conn, he_network_config_ipv4_t *config, 84 | void *context) { 85 | call_counter++; 86 | return HE_SUCCESS; 87 | } 88 | 89 | he_return_code_t pmtud_time_cb(he_conn_t *conn, int timeout, void *context) { 90 | if(timeout > 0) { 91 | call_counter++; 92 | } 93 | return HE_SUCCESS; 94 | } 95 | 96 | he_return_code_t pmtud_state_change_cb(he_conn_t *conn, he_pmtud_state_t state, void *context) { 97 | call_counter++; 98 | return HE_SUCCESS; 99 | } 100 | 101 | he_return_code_t stub_overflow_plugin(he_plugin_chain_t *chain, uint8_t *packet, size_t *length, 102 | size_t capacity, int numCalls) { 103 | *length = capacity + 1; 104 | return HE_SUCCESS; 105 | } 106 | 107 | #endif // HE_TEST_DEFS 108 | -------------------------------------------------------------------------------- /test/support/wolfssl_testable_types.h: -------------------------------------------------------------------------------- 1 | #ifndef WOLFSSL_TESTABLE_TYPES 2 | #define WOLFSSL_TESTABLE_TYPES 3 | 4 | // #define WOLFSSL_API __attribute__ ((visibility("default"))) 5 | // #define WOLFSSL_LOCAL __attribute__ ((visibility("hidden"))) 6 | 7 | #define WOLFSSL_API 8 | #define WOLFSSL_LOCAL 9 | 10 | typedef struct WOLFSSL { 11 | int id; 12 | } WOLFSSL; 13 | 14 | typedef struct WOLFSSL_CTX { 15 | int id; 16 | } WOLFSSL_CTX; 17 | 18 | struct WOLFSSL_CERT_MANAGER { 19 | int id; 20 | }; 21 | 22 | struct WOLFSSL_X509 { 23 | int id; 24 | }; 25 | 26 | struct WOLFSSL_X509_CRL { 27 | int id; 28 | }; 29 | 30 | struct WOLFSSL_X509_NAME { 31 | int id; 32 | }; 33 | 34 | struct WOLFSSL_X509_NAME_ENTRY { 35 | int id; 36 | }; 37 | 38 | struct WOLFSSL_X509_CHAIN { 39 | int id; 40 | }; 41 | 42 | struct WOLFSSL_X509_VERIFY_PARAM { 43 | int id; 44 | }; 45 | 46 | struct WOLFSSL_CRL { 47 | int id; 48 | }; 49 | 50 | struct WOLFSSL_STACK { 51 | int id; 52 | }; 53 | 54 | struct WOLFSSL_CIPHER { 55 | int id; 56 | }; 57 | 58 | struct WOLFSSL_METHOD { 59 | int id; 60 | }; 61 | 62 | struct WOLFSSL_CHAIN { 63 | int id; 64 | }; 65 | 66 | struct WOLFSSL_SESSION { 67 | int id; 68 | }; 69 | 70 | struct WOLFSSL_DH { 71 | int id; 72 | }; 73 | 74 | struct WOLFSSL_RSA { 75 | int id; 76 | }; 77 | 78 | struct WC_PKCS12 { 79 | int id; 80 | }; 81 | 82 | struct WOLFSSL_EVP_MD_CTX { 83 | int id; 84 | }; 85 | 86 | struct WOLFSSL_X509_EXTENSION { 87 | int id; 88 | }; 89 | 90 | struct WOLFSSL_BIO { 91 | int id; 92 | }; 93 | #endif 94 | -------------------------------------------------------------------------------- /tvos.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for iOS 2 | :import: 3 | - 3rd_party_deps.yml 4 | - unix.yml 5 | 6 | :release_build: 7 | :output: libhelium.a 8 | 9 | :dependencies: 10 | :libraries: 11 | - :name: WolfSSL 12 | :source_path: third_party/wolfssl 13 | :artifact_path: third_party/builds/wolfssl_tvos 14 | :fetch: 15 | :method: :git 16 | :source: $HE_WOLFSSL_SOURCE 17 | :tag: $HE_WOLFSSL_TAG 18 | :build: 19 | - git apply ../../wolfssl/*.patch 20 | - autoreconf -i 21 | - cp ../../ios/autotools-ios-helper.sh ./autotools-ios-helper.sh 22 | - PREFIX=$(pwd)/../builds/wolfssl_tvos ./autotools-ios-helper.sh -appletvuniversal 23 | :artifacts: 24 | :includes: 25 | - include/** 26 | :static_libraries: 27 | - Release-tvos-universal/lib/libwolfssl.a 28 | 29 | :environment: 30 | - MACOSX_DEPLOYMENT_TARGET: "15.0" 31 | -------------------------------------------------------------------------------- /unix.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling include file for shared Linux/Mac items 2 | 3 | # Add -gcov to the plugins list to make sure of the gcov plugin 4 | # You will need to have gcov and gcovr both installed to make it work. 5 | # For more information on these options, see docs in plugins/gcov 6 | :gcov: 7 | :html_report: TRUE 8 | :html_report_type: detailed 9 | :html_medium_threshold: 75 10 | :html_high_threshold: 90 11 | :xml_report: TRUE 12 | :gcovr: 13 | #:report_exclude: "^post.*" 14 | :reports: 15 | - SonarQube 16 | 17 | :tools_test_file_preprocessor: 18 | :arguments: 19 | - -include third_party/builds/wolfssl_build/include/wolfssl/options.h 20 | - -include third_party/builds/wolfssl_build/include/wolfssl/wolfcrypt/settings.h 21 | :tools_test_includes_preprocessor: 22 | :arguments: 23 | - -include third_party/builds/wolfssl_build/include/wolfssl/options.h 24 | - -include third_party/builds/wolfssl_build/include/wolfssl/wolfcrypt/settings.h 25 | - -include third_party/builds/wolfssl_build/include/wolfssl/ssl.h 26 | :tools_release_linker: 27 | :arguments: 28 | - -lm 29 | :tools_test_linker: 30 | :arguments: 31 | - -lm 32 | :tools_gcov_linker: 33 | :arguments: 34 | - -lm 35 | 36 | :flags: 37 | :release: 38 | :compile: 39 | :*: 40 | - -g 41 | - -fPIC 42 | - -O3 43 | :test: 44 | :compile: 45 | :*: 46 | - -g 47 | - -fPIC 48 | - -fsanitize=address 49 | :link: 50 | :*: 51 | - -fsanitize=address 52 | ... 53 | -------------------------------------------------------------------------------- /windows.yml: -------------------------------------------------------------------------------- 1 | --- # Shared config for Windows 2 | :release_build: 3 | :output: libhelium.lib 4 | 5 | :defines: 6 | :test: 7 | - WOLFSSL_USER_SETTINGS 8 | - WOLFSSL_MIN_RSA_BITS=2048 9 | - WOLFSSL_MIN_ECC_BITS=256 10 | - HAVE_SECURE_RENEGOTIATION 11 | - WOLFSSL_DTLS_CH_FRAG 12 | - WOLFSSL_TLS13_MIDDLEBOX_COMPAT 13 | - WOLFSSL_ML_KEM_USE_OLD_IDS 14 | :test_preprocess: 15 | - WOLFSSL_USER_SETTINGS 16 | - WOLFSSL_MIN_RSA_BITS=2048 17 | - WOLFSSL_MIN_ECC_BITS=256 18 | - HAVE_SECURE_RENEGOTIATION 19 | - WOLFSSL_DTLS_CH_FRAG 20 | - WOLFSSL_TLS_MIDDLEBOX_COMPAT 21 | - WOLFSSL_ML_KEM_USE_OLD_IDS 22 | #- USE_WINDOWS_API # avoids use of unistd.h 23 | :release: 24 | - WOLFSSL_USER_SETTINGS 25 | - WOLFSSL_MIN_RSA_BITS=2048 26 | - WOLFSSL_MIN_ECC_BITS=256 27 | - HAVE_SECURE_RENEGOTIATION 28 | - WOLFSSL_DTLS_CH_FRAG 29 | - WOLFSSL_TLS13_MIDDLEBOX_COMPAT 30 | - WOLFSSL_ML_KEM_USE_OLD_IDS 31 | 32 | :libraries: 33 | :path_flag: /LIBPATH:${1} 34 | :flag: ${1}.lib 35 | :test: 36 | - ws2_32 37 | - advapi32 38 | 39 | :cmock: 40 | :when_ptr: :compare_ptr # build/test/mocks/mock_ssl.c(57818): error C2066: cast to function type is illegal 41 | 42 | :environment: 43 | - :path: 44 | # mingw installs a link.exe too, try and avoid it... 45 | - "#{ENV['VCToolsInstallDir']}bin\\\\Host#{ENV['Platform']}\\\\#{ENV['Platform']}" 46 | - "#{ENV['PATH']}" 47 | # Magic to override msvc project settings to use /MT instead of /MD, since -p:RuntimeLibrary=MultiThreaded doesn't work 48 | # http://answers.flyppdevportal.com/MVC/Post/Thread/1a6dd13c-9f5c-430b-88ba-518bfcca00b1?category=vcgeneral 49 | - _CL_: /MT 50 | 51 | :tools_test_file_preprocessor: 52 | :arguments: 53 | - /FI wolfssl/user_settings.h 54 | - /FI wolfssl/wolfcrypt/settings.h 55 | :tools_test_includes_preprocessor: # using gcc 56 | :arguments: 57 | - -include third_party/wolfssl/wolfssl/user_settings.h 58 | - -include third_party/wolfssl/wolfssl/wolfcrypt/settings.h 59 | -------------------------------------------------------------------------------- /windows/ceedling32.bat: -------------------------------------------------------------------------------- 1 | echo off 2 | for /f "usebackq tokens=*" %%a in (`"\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set BASE=%%a 3 | call "%BASE%"/VC\Auxiliary\Build\vcvars32.bat 4 | echo on 5 | echo Running: ceedling %* 6 | ceedling %* 7 | -------------------------------------------------------------------------------- /windows/ceedling64.bat: -------------------------------------------------------------------------------- 1 | echo off 2 | for /f "usebackq tokens=*" %%a in (`"\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set BASE=%%a 3 | call "%BASE%"/VC\Auxiliary\Build\vcvars64.bat 4 | echo on 5 | echo Running: ceedling %* 6 | ceedling %* 7 | -------------------------------------------------------------------------------- /windows/ceedlingarm64.bat: -------------------------------------------------------------------------------- 1 | echo off 2 | for /f "usebackq tokens=*" %%a in (`"\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set BASE=%%a 3 | call "%BASE%"/VC\Auxiliary\Build\vcvarsamd64_arm64.bat 4 | echo on 5 | echo Running: ceedling %* 6 | ceedling %* 7 | -------------------------------------------------------------------------------- /windows/wolfssl-user_settings-32.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN_USER_SETTINGS_H_ 2 | #define _WIN_USER_SETTINGS_H_ 3 | 4 | #undef WOLFSSL_AESNI 5 | 6 | #undef HAVE_INTEL_RDSEED 7 | 8 | #undef USE_INTEL_SPEEDUP 9 | 10 | #undef WOLFSSL_X86_64_BUILD 11 | 12 | #endif /* _WIN_USER_SETTINGS_H_ */ 13 | -------------------------------------------------------------------------------- /windows/wolfssl-user_settings-64.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN_USER_SETTINGS_H_ 2 | #define _WIN_USER_SETTINGS_H_ 3 | 4 | #undef WOLFSSL_AESNI 5 | #define WOLFSSL_AESNI 6 | 7 | #undef HAVE_INTEL_RDSEED 8 | #define HAVE_INTEL_RDSEED 9 | 10 | #undef USE_INTEL_SPEEDUP 11 | // #define USE_INTEL_SPEEDUP // Needs ASM stubs which are not included in the vxproj 12 | 13 | #undef WOLFSSL_X86_64_BUILD 14 | #define WOLFSSL_X86_64_BUILD 15 | 16 | #endif /* _WIN_USER_SETTINGS_H_ */ 17 | -------------------------------------------------------------------------------- /windows/wolfssl-user_settings-arm-64.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN_USER_SETTINGS_H_ 2 | #define _WIN_USER_SETTINGS_H_ 3 | 4 | #undef WOLFSSL_AESNI 5 | 6 | #undef HAVE_INTEL_RDSEED 7 | 8 | #undef USE_INTEL_SPEEDUP 9 | 10 | #undef WOLFSSL_AARCH64_BUILD 11 | #define WOLFSSL_AARCH64_BUILD 12 | 13 | #endif /* _WIN_USER_SETTINGS_H_ */ 14 | -------------------------------------------------------------------------------- /windows/wolfssl-user_settings-common.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN_USER_SETTINGS_COMMON_H_ 2 | #define _WIN_USER_SETTINGS_COMMON_H_ 3 | 4 | /* Verify this is Windows */ 5 | #ifndef _WIN32 6 | #error This user_settings.h header is only designed for Windows 7 | #endif 8 | 9 | /* Check HAVE_SECURE_RENEGOTIATION */ 10 | #ifndef HAVE_SECURE_RENEGOTIATION 11 | #error HAVE_SECURE_RENEGOTIATION is not defined 12 | #endif 13 | 14 | /* Configurations */ 15 | #undef USE_WINDOWS_API 16 | #define USE_WINDOWS_API 17 | 18 | #undef WOLFSSL_TLS13 19 | #define WOLFSSL_TLS13 20 | 21 | #undef HAVE_TLS_EXTENSIONS 22 | #define HAVE_TLS_EXTENSIONS 23 | 24 | #undef HAVE_SUPPORTED_CURVES 25 | #define HAVE_SUPPORTED_CURVES 26 | 27 | #undef WOLFSSL_DTLS_MTU 28 | #define WOLFSSL_DTLS_MTU 29 | 30 | #undef WOLFSSL_DTLS 31 | #define WOLFSSL_DTLS 32 | 33 | #undef WOLFSSL_DTLS13 34 | #define WOLFSSL_DTLS13 35 | 36 | #undef WOLFSSL_SEND_HRR_COOKIE 37 | #define WOLFSSL_SEND_HRR_COOKIE 38 | 39 | #undef SINGLE_THREADED 40 | #define SINGLE_THREADED 41 | 42 | #undef HAVE_THREAD_LS 43 | #define HAVE_THREAD_LS 44 | 45 | #undef TFM_TIMING_RESISTANT 46 | #define TFM_TIMING_RESISTANT 47 | 48 | #undef ECC_TIMING_RESISTANT 49 | #define ECC_TIMING_RESISTANT 50 | 51 | #undef WC_RSA_BLINDING 52 | #define WC_RSA_BLINDING 53 | 54 | #undef HAVE_AESGCM 55 | #define HAVE_AESGCM 56 | 57 | #undef WOLFSSL_SHA512 58 | #define WOLFSSL_SHA512 59 | 60 | #undef WOLFSSL_SHA384 61 | #define WOLFSSL_SHA384 62 | 63 | #undef HAVE_HKDF 64 | #define HAVE_HKDF 65 | 66 | #undef NO_DSA 67 | #define NO_DSA 68 | 69 | #undef HAVE_ECC 70 | #define HAVE_ECC 71 | 72 | #undef TFM_ECC256 73 | #define TFM_ECC256 74 | 75 | #undef ECC_SHAMIR 76 | #define ECC_SHAMIR 77 | 78 | #undef HAVE_CURVE25519 79 | #define HAVE_CURVE25519 80 | 81 | #undef NO_OLD_TLS 82 | #define NO_OLD_TLS 83 | 84 | #undef WC_RSA_PSS 85 | #define WC_RSA_PSS 86 | 87 | #undef NO_DH 88 | #define NO_DH 89 | 90 | #undef WOLFSSL_BASE64_ENCODE 91 | #define WOLFSSL_BASE64_ENCODE 92 | 93 | #undef NO_RC4 94 | #define NO_RC4 95 | 96 | #undef NO_HC128 97 | #define NO_HC128 98 | 99 | #undef NO_RABBIT 100 | #define NO_RABBIT 101 | 102 | #undef WOLFSSL_SHA224 103 | #define WOLFSSL_SHA224 104 | 105 | #undef HAVE_POLY1305 106 | #define HAVE_POLY1305 107 | 108 | #undef HAVE_ONE_TIME_AUTH 109 | #define HAVE_ONE_TIME_AUTH 110 | 111 | #undef HAVE_CHACHA 112 | #define HAVE_CHACHA 113 | 114 | #undef HAVE_HASHDRBG 115 | #define HAVE_HASHDRBG 116 | 117 | #undef HAVE_SNI 118 | #define HAVE_SNI 119 | 120 | #undef HAVE_SUPPORTED_CURVES 121 | #define HAVE_SUPPORTED_CURVES 122 | 123 | #undef HAVE_EXTENDED_MASTER 124 | #define HAVE_EXTENDED_MASTER 125 | 126 | #undef WOLFCRYPT_HAVE_SRP 127 | #define WOLFCRYPT_HAVE_SRP 128 | 129 | #undef NO_RC4 130 | #define NO_RC4 131 | 132 | #undef HAVE_ENCRYPT_THEN_MAC 133 | #define HAVE_ENCRYPT_THEN_MAC 134 | 135 | #undef NO_PSK 136 | #define NO_PSK 137 | 138 | #undef NO_MD4 139 | #define NO_MD4 140 | 141 | #undef NO_PWDBASED 142 | #define NO_PWDBASED 143 | 144 | #undef USE_FAST_MATH 145 | #define USE_FAST_MATH 146 | 147 | #undef WOLFSSL_HAVE_SP_RSA 148 | #define WOLFSSL_HAVE_SP_RSA 149 | 150 | #undef WOLFSSL_SP_4096 151 | #define WOLFSSL_SP_4096 152 | 153 | #undef WOLFSSL_HAVE_SP_ECC 154 | #define WOLFSSL_HAVE_SP_ECC 155 | 156 | #undef HAVE_ECC384 157 | #define HAVE_ECC384 158 | 159 | #undef WOLFSSL_SP_384 160 | #define WOLFSSL_SP_384 161 | 162 | #undef WOLFSSL_SP_ASM 163 | // #define WOLFSSL_SP_ASM 164 | 165 | #undef WOLFSSL_SP_X86_64_ASM 166 | // #define WOLFSSL_SP_X86_64_ASM 167 | 168 | #undef WC_NO_ASYNC_THREADING 169 | #define WC_NO_ASYNC_THREADING 170 | 171 | #undef HAVE_DH_DEFAULT_PARAMS 172 | #define HAVE_DH_DEFAULT_PARAMS 173 | 174 | #undef NO_DES3 175 | #define NO_DES3 176 | 177 | #undef WOLFSSL_SYS_CA_CERTS 178 | #define WOLFSSL_SYS_CA_CERTS 179 | 180 | #undef HAVE_LIBOQS 181 | // #define HAVE_LIBOQS 182 | 183 | #undef WOLFSSL_NO_SPHINCS 184 | #define WOLFSSL_NO_SPHINCS 185 | 186 | #undef WOLFSSL_EXPERIMENTAL_SETTINGS 187 | #define WOLFSSL_EXPERIMENTAL_SETTINGS 188 | 189 | // Post-quantum settings 190 | #undef WOLFSSL_HAVE_MLKEM 191 | #define WOLFSSL_HAVE_MLKEM 192 | 193 | #undef WOLFSSL_WC_MLKEM 194 | #define WOLFSSL_WC_MLKEM 195 | 196 | #undef WOLFSSL_MLKEM_KYBER 197 | #define WOLFSSL_MLKEM_KYBER 198 | 199 | #undef WOLFSSL_NO_ML_KEM 200 | // #define WOLFSSL_NO_ML_KEM 201 | 202 | // Needed for using WolfSSL's Kyber implementation 203 | #undef WOLFSSL_SHA3 204 | #define WOLFSSL_SHA3 205 | 206 | #undef WOLFSSL_SHAKE128 207 | #define WOLFSSL_SHAKE128 208 | 209 | #undef WOLFSSL_SHAKE256 210 | #define WOLFSSL_SHAKE256 211 | 212 | #endif /* _WIN_USER_SETTINGS_COMMON_H_ */ 213 | -------------------------------------------------------------------------------- /windows/wolfssl-user_settings-multithread.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN_USER_SETTINGS_MULTITHREAD_H_ 2 | #define _WIN_USER_SETTINGS_MULTITHREAD_H_ 3 | 4 | #undef SINGLE_THREADED 5 | 6 | #undef WOLFSSL_RW_THREADED 7 | #define WOLFSSL_RW_THREADED 8 | 9 | #endif /* _WIN_USER_SETTINGS_MULTITHREAD_H_ */ 10 | -------------------------------------------------------------------------------- /windows_32.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Windows 2 | :import: 3 | - 3rd_party_deps.yml 4 | - windows.yml 5 | 6 | :dependencies: 7 | :libraries: 8 | - :name: WolfSSL 9 | :source_path: third_party/wolfssl 10 | :fetch: 11 | :method: :git 12 | :source: "%HE_WOLFSSL_SOURCE%" 13 | :tag: "%HE_WOLFSSL_TAG%" 14 | :build: 15 | - git apply ../../wolfssl/0001-CVPN-1945-Lower-max-mtu-for-DTLS-1.3-handshake-message.patch 16 | - git apply ../../wolfssl/0003-use-proper-warnings-on-MSVC.patch 17 | - git apply ../../wolfssl/0004-mlkem-codepoint-backward-compatible.patch 18 | - "cp ../../windows/wolfssl-user_settings-common.h wolfssl/user_settings.h" 19 | - "cat ../../windows/wolfssl-user_settings-32.h >> wolfssl/user_settings.h" 20 | - "cp -f wolfssl/user_settings.h IDE/WIN/user_settings.h" 21 | - "cp -f ../../windows/wolfssl.vcxproj ./wolfssl.vcxproj" 22 | - "MSBuild.exe wolfssl.vcxproj -verbosity:detailed -t:Build -p:Configuration=Release -p:Platform=Win32 -p:PlatformToolset=v143" 23 | :artifacts: 24 | :includes: 25 | - / 26 | - /wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 27 | :static_libraries: 28 | - Release/Win32/wolfssl.lib 29 | 30 | # https://github.com/ThrowTheSwitch/Ceedling/issues/210 -> https://github.com/ThrowTheSwitch/Ceedling/files/1360977/project.txt 31 | :tools: 32 | # Ceedling defaults to using gcc for compiling, linking, etc. 33 | # As [:tools] is blank, gcc will be used (so long as it's in your system path) 34 | # See documentation to configure a given toolchain for use 35 | :test_compiler: 36 | :executable: cl 37 | :name: 'msvc' 38 | :arguments: 39 | - /c 40 | - /nologo 41 | - /MT 42 | - /GL 43 | - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 44 | - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 45 | - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 46 | - /Fo"${2}" 47 | - "${1}" 48 | :test_linker: 49 | :executable: link 50 | :name: 'msvc' 51 | :arguments: 52 | - /MACHINE:X86 53 | - "${1}" 54 | - /FORCE:MULTIPLE # /IGNORE:LNK4006 # mocks deliberately duplicate symbols 55 | - /LTCG 56 | - "${5}" 57 | - "${4}" 58 | - /OUT:"${2}" 59 | :test_file_preprocessor: 60 | :executable: cl 61 | :name: 'msvc' 62 | :arguments: 63 | - /P 64 | - /C 65 | - /I test_file_preprocessor 66 | - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 67 | - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 68 | - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 69 | - /D"$": DEFINES_TEST_PREPROCESS 70 | - /Fi"${2}" 71 | - "${1}" 72 | # This is `gcc -E -MM -MG` which outputs a make dependency rule. 73 | # Unsure how to coax cl.exe into doing this, so just stick with gcc. 74 | #:test_includes_preprocessor: 75 | # :executable: cl 76 | # :name: 'msvc' 77 | # :arguments: 78 | # - /P 79 | # - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 80 | # - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 81 | # - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 82 | # - /D"$": DEFINES_TEST_PREPROCESS 83 | # - "${1}" 84 | :release_compiler: 85 | :executable: cl 86 | :name: 'msvc' 87 | :arguments: 88 | - /c 89 | - /MT 90 | - /I"$": COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR 91 | - /I"$": COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE 92 | - /D"$": COLLECTION_DEFINES_RELEASE_AND_VENDOR 93 | - /Fo"${2}" 94 | - "${1}" 95 | :release_linker: 96 | #:executable: link 97 | :executable: lib 98 | :name: 'msvc' 99 | :arguments: 100 | - /MACHINE:X86 101 | - "${1}" 102 | - /OUT:"${2}" 103 | 104 | ... 105 | -------------------------------------------------------------------------------- /windows_64.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Windows 2 | :import: 3 | - 3rd_party_deps.yml 4 | - windows.yml 5 | 6 | :dependencies: 7 | :libraries: 8 | - :name: WolfSSL 9 | :source_path: third_party/wolfssl 10 | :fetch: 11 | :method: :git 12 | :source: "%HE_WOLFSSL_SOURCE%" 13 | :tag: "%HE_WOLFSSL_TAG%" 14 | :build: 15 | - git apply ../../wolfssl/0001-CVPN-1945-Lower-max-mtu-for-DTLS-1.3-handshake-message.patch 16 | - git apply ../../wolfssl/0003-use-proper-warnings-on-MSVC.patch 17 | - git apply ../../wolfssl/0004-mlkem-codepoint-backward-compatible.patch 18 | - "cp ../../windows/wolfssl-user_settings-common.h wolfssl/user_settings.h" 19 | - "cat ../../windows/wolfssl-user_settings-64.h >> wolfssl/user_settings.h" 20 | - "cp -f wolfssl/user_settings.h IDE/WIN/user_settings.h" 21 | - "cp -f ../../windows/wolfssl.vcxproj ./wolfssl.vcxproj" 22 | - "MSBuild.exe wolfssl.vcxproj -verbosity:detailed -t:Build -p:Configuration=Release -p:Platform=x64 -p:PlatformToolset=v143" 23 | :artifacts: 24 | :includes: 25 | - / 26 | - /wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 27 | :static_libraries: 28 | - Release/x64/wolfssl.lib 29 | 30 | # https://github.com/ThrowTheSwitch/Ceedling/issues/210 -> https://github.com/ThrowTheSwitch/Ceedling/files/1360977/project.txt 31 | :tools: 32 | # Ceedling defaults to using gcc for compiling, linking, etc. 33 | # As [:tools] is blank, gcc will be used (so long as it's in your system path) 34 | # See documentation to configure a given toolchain for use 35 | :test_compiler: 36 | :executable: cl 37 | :name: 'msvc' 38 | :arguments: 39 | - /c 40 | - /nologo 41 | - /MT 42 | - /GL 43 | - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 44 | - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 45 | - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 46 | - /Fo"${2}" 47 | - "${1}" 48 | :test_linker: 49 | :executable: link 50 | :name: 'msvc' 51 | :arguments: 52 | - /MACHINE:X64 53 | - "${1}" 54 | - /FORCE:MULTIPLE # /IGNORE:LNK4006 # mocks deliberately duplicate symbols 55 | - /LTCG 56 | - "${5}" 57 | - "${4}" 58 | - /OUT:"${2}" 59 | :test_file_preprocessor: 60 | :executable: cl 61 | :name: 'msvc' 62 | :arguments: 63 | - /P 64 | - /C 65 | - /I test_file_preprocessor 66 | - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 67 | - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 68 | - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 69 | - /D"$": DEFINES_TEST_PREPROCESS 70 | - /Fi"${2}" 71 | - "${1}" 72 | # This is `gcc -E -MM -MG` which outputs a make dependency rule. 73 | # Unsure how to coax cl.exe into doing this, so just stick with gcc. 74 | #:test_includes_preprocessor: 75 | # :executable: cl 76 | # :name: 'msvc' 77 | # :arguments: 78 | # - /P 79 | # - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 80 | # - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 81 | # - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 82 | # - /D"$": DEFINES_TEST_PREPROCESS 83 | # - "${1}" 84 | :release_compiler: 85 | :executable: cl 86 | :name: 'msvc' 87 | :arguments: 88 | - /c 89 | - /MT 90 | - /I"$": COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR 91 | - /I"$": COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE 92 | - /D"$": COLLECTION_DEFINES_RELEASE_AND_VENDOR 93 | - /Fo"${2}" 94 | - "${1}" 95 | :release_linker: 96 | #:executable: link 97 | :executable: lib 98 | :name: 'msvc' 99 | :arguments: 100 | - /MACHINE:X64 101 | - "${1}" 102 | - /OUT:"${2}" 103 | 104 | ... 105 | -------------------------------------------------------------------------------- /windows_64_multithread.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Windows 2 | :import: 3 | - 3rd_party_deps.yml 4 | - windows.yml 5 | 6 | :dependencies: 7 | :libraries: 8 | - :name: WolfSSL 9 | :source_path: third_party/wolfssl 10 | :fetch: 11 | :method: :git 12 | :source: "%HE_WOLFSSL_SOURCE%" 13 | :tag: "%HE_WOLFSSL_TAG%" 14 | :build: 15 | - git apply ../../wolfssl/0001-CVPN-1945-Lower-max-mtu-for-DTLS-1.3-handshake-message.patch 16 | - git apply ../../wolfssl/0003-use-proper-warnings-on-MSVC.patch 17 | - git apply ../../wolfssl/0004-mlkem-codepoint-backward-compatible.patch 18 | - "cp ../../windows/wolfssl-user_settings-common.h wolfssl/user_settings.h" 19 | - "cat ../../windows/wolfssl-user_settings-64.h >> wolfssl/user_settings.h" 20 | - "cat ../../windows/wolfssl-user_settings-multithread.h >> wolfssl/user_settings.h" 21 | - "cp -f wolfssl/user_settings.h IDE/WIN/user_settings.h" 22 | - "cp -f ../../windows/wolfssl.vcxproj ./wolfssl.vcxproj" 23 | - "MSBuild.exe wolfssl.vcxproj -verbosity:detailed -t:Build -p:Configuration=Release -p:Platform=x64 -p:PlatformToolset=v143" 24 | :artifacts: 25 | :includes: 26 | - / 27 | - /wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 28 | :static_libraries: 29 | - Release/x64/wolfssl.lib 30 | 31 | # https://github.com/ThrowTheSwitch/Ceedling/issues/210 -> https://github.com/ThrowTheSwitch/Ceedling/files/1360977/project.txt 32 | :tools: 33 | # Ceedling defaults to using gcc for compiling, linking, etc. 34 | # As [:tools] is blank, gcc will be used (so long as it's in your system path) 35 | # See documentation to configure a given toolchain for use 36 | :test_compiler: 37 | :executable: cl 38 | :name: 'msvc' 39 | :arguments: 40 | - /std:c11 41 | - /experimental:c11atomics 42 | - /D"HE_ENABLE_MULTITHREADED" 43 | - /c 44 | - /nologo 45 | - /MT 46 | - /GL 47 | - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 48 | - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 49 | - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 50 | - /Fo"${2}" 51 | - "${1}" 52 | :test_linker: 53 | :executable: link 54 | :name: 'msvc' 55 | :arguments: 56 | - /MACHINE:X64 57 | - "${1}" 58 | - /FORCE:MULTIPLE # /IGNORE:LNK4006 # mocks deliberately duplicate symbols 59 | - /LTCG 60 | - "${5}" 61 | - "${4}" 62 | - /OUT:"${2}" 63 | :test_file_preprocessor: 64 | :executable: cl 65 | :name: 'msvc' 66 | :arguments: 67 | - /P 68 | - /C 69 | - /I test_file_preprocessor 70 | - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 71 | - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 72 | - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 73 | - /D"$": DEFINES_TEST_PREPROCESS 74 | - /Fi"${2}" 75 | - "${1}" 76 | # This is `gcc -E -MM -MG` which outputs a make dependency rule. 77 | # Unsure how to coax cl.exe into doing this, so just stick with gcc. 78 | #:test_includes_preprocessor: 79 | # :executable: cl 80 | # :name: 'msvc' 81 | # :arguments: 82 | # - /P 83 | # - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 84 | # - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 85 | # - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 86 | # - /D"$": DEFINES_TEST_PREPROCESS 87 | # - "${1}" 88 | :release_compiler: 89 | :executable: cl 90 | :name: 'msvc' 91 | :arguments: 92 | - /std:c11 93 | - /experimental:c11atomics 94 | - /D"HE_ENABLE_MULTITHREADED" 95 | - /c 96 | - /MT 97 | - /I"$": COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR 98 | - /I"$": COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE 99 | - /D"$": COLLECTION_DEFINES_RELEASE_AND_VENDOR 100 | - /Fo"${2}" 101 | - "${1}" 102 | :release_linker: 103 | #:executable: link 104 | :executable: lib 105 | :name: 'msvc' 106 | :arguments: 107 | - /MACHINE:X64 108 | - "${1}" 109 | - /OUT:"${2}" 110 | 111 | ... 112 | -------------------------------------------------------------------------------- /windows_arm64.yml: -------------------------------------------------------------------------------- 1 | --- # ceedling project file for Windows 2 | :import: 3 | - 3rd_party_deps.yml 4 | - windows.yml 5 | 6 | :dependencies: 7 | :libraries: 8 | - :name: WolfSSL 9 | :source_path: third_party/wolfssl 10 | :fetch: 11 | :method: :git 12 | :source: "%HE_WOLFSSL_SOURCE%" 13 | :tag: "%HE_WOLFSSL_TAG%" 14 | :build: 15 | - git apply ../../wolfssl/0001-CVPN-1945-Lower-max-mtu-for-DTLS-1.3-handshake-message.patch 16 | - git apply ../../wolfssl/0003-use-proper-warnings-on-MSVC.patch 17 | - git apply ../../wolfssl/0004-mlkem-codepoint-backward-compatible.patch 18 | - "cp ../../windows/wolfssl-user_settings-common.h wolfssl/user_settings.h" 19 | - "cat ../../windows/wolfssl-user_settings-arm-64.h >> wolfssl/user_settings.h" 20 | - "cp -f wolfssl/user_settings.h IDE/WIN/user_settings.h" 21 | - "cp -f ../../windows/wolfssl.vcxproj ./wolfssl.vcxproj" 22 | - "MSBuild.exe wolfssl.vcxproj -verbosity:detailed -t:Build -p:Configuration=Release -p:Platform=ARM64 -p:PlatformToolset=v143" 23 | :artifacts: 24 | :includes: 25 | - / 26 | - /wolfssl # needed e.g. for mock_ssl.h to find wolfssl/ssl.h 27 | :static_libraries: 28 | - Release/x64/wolfssl.lib 29 | 30 | # https://github.com/ThrowTheSwitch/Ceedling/issues/210 -> https://github.com/ThrowTheSwitch/Ceedling/files/1360977/project.txt 31 | :tools: 32 | # Ceedling defaults to using gcc for compiling, linking, etc. 33 | # As [:tools] is blank, gcc will be used (so long as it's in your system path) 34 | # See documentation to configure a given toolchain for use 35 | :test_compiler: 36 | :executable: cl 37 | :name: 'msvc' 38 | :arguments: 39 | - /c 40 | - /nologo 41 | - /MT 42 | - /GL 43 | - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 44 | - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 45 | - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 46 | - /Fo"${2}" 47 | - "${1}" 48 | :test_linker: 49 | :executable: link 50 | :name: 'msvc' 51 | :arguments: 52 | - /MACHINE:ARM64 53 | - "${1}" 54 | - /FORCE:MULTIPLE # /IGNORE:LNK4006 # mocks deliberately duplicate symbols 55 | - /LTCG 56 | - "${5}" 57 | - "${4}" 58 | - /OUT:"${2}" 59 | :test_file_preprocessor: 60 | :executable: cl 61 | :name: 'msvc' 62 | :arguments: 63 | - /P 64 | - /C 65 | - /I test_file_preprocessor 66 | - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 67 | - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 68 | - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 69 | - /D"$": DEFINES_TEST_PREPROCESS 70 | - /Fi"${2}" 71 | - "${1}" 72 | # This is `gcc -E -MM -MG` which outputs a make dependency rule. 73 | # Unsure how to coax cl.exe into doing this, so just stick with gcc. 74 | #:test_includes_preprocessor: 75 | # :executable: cl 76 | # :name: 'msvc' 77 | # :arguments: 78 | # - /P 79 | # - /I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR 80 | # - /I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE 81 | # - /D"$": COLLECTION_DEFINES_TEST_AND_VENDOR 82 | # - /D"$": DEFINES_TEST_PREPROCESS 83 | # - "${1}" 84 | :release_compiler: 85 | :executable: cl 86 | :name: 'msvc' 87 | :arguments: 88 | - /c 89 | - /MT 90 | - /I"$": COLLECTION_PATHS_SOURCE_INCLUDE_VENDOR 91 | - /I"$": COLLECTION_PATHS_RELEASE_TOOLCHAIN_INCLUDE 92 | - /D"$": COLLECTION_DEFINES_RELEASE_AND_VENDOR 93 | - /Fo"${2}" 94 | - "${1}" 95 | :release_linker: 96 | #:executable: link 97 | :executable: lib 98 | :name: 'msvc' 99 | :arguments: 100 | - /MACHINE:ARM64 101 | - "${1}" 102 | - /OUT:"${2}" 103 | 104 | ... 105 | -------------------------------------------------------------------------------- /wolfssl/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/expressvpn/lightway-core/376df03bb311a7e65ba221a62c3512426380df10/wolfssl/.gitkeep -------------------------------------------------------------------------------- /wolfssl/0001-CVPN-1945-Lower-max-mtu-for-DTLS-1.3-handshake-message.patch: -------------------------------------------------------------------------------- 1 | From beb661e72616c991b597e17a147dbbb9450dc34e Mon Sep 17 00:00:00 2001 2 | From: Peter Membrey 3 | Date: Wed, 16 Apr 2025 12:09:39 +0800 4 | Subject: [PATCH] CVPN-1945 Lower max mtu for DTLS 1.3 handshake messages to 5 | prevent fragmentation 6 | 7 | --- 8 | src/dtls13.c | 4 +++- 9 | 1 file changed, 3 insertions(+), 1 deletion(-) 10 | 11 | diff --git a/src/dtls13.c b/src/dtls13.c 12 | index cc2c02fa4..6dc086103 100644 13 | --- a/src/dtls13.c 14 | +++ b/src/dtls13.c 15 | @@ -971,7 +971,9 @@ static int Dtls13SendFragmentedInternal(WOLFSSL* ssl) 16 | isEncrypted = Dtls13TypeIsEncrypted( 17 | (enum HandShakeType)ssl->dtls13FragHandshakeType); 18 | rlHeaderLength = Dtls13GetRlHeaderLength(ssl, isEncrypted); 19 | - maxFragment = wolfSSL_GetMaxFragSize(ssl, MAX_RECORD_SIZE); 20 | + // Pete M: Removing 500 bytes to ensure the packet fragments at a ratio 21 | + // of 70/30 rather than 99/1 22 | + maxFragment = wolfSSL_GetMaxFragSize(ssl, MAX_RECORD_SIZE) - 500; 23 | 24 | remainingSize = ssl->dtls13MessageLength - ssl->dtls13FragOffset; 25 | 26 | -- 27 | 2.34.1 28 | 29 | -------------------------------------------------------------------------------- /wolfssl/0002-fix-apple-native-cert-validation.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/internal.c b/src/internal.c 2 | index eb2f16d63..39f5dcd56 100644 3 | --- a/src/internal.c 4 | +++ b/src/internal.c 5 | @@ -211,8 +211,10 @@ int writeAeadAuthData(WOLFSSL* ssl, word16 sz, byte type, byte* additional, 6 | #include 7 | #include 8 | #include 9 | +#if defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) 10 | static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs, 11 | int totalCerts); 12 | +#endif /* #if defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) */ 13 | #endif /* #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */ 14 | 15 | #ifdef WOLFSSL_DTLS13 16 | @@ -2754,10 +2756,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) 17 | maxq10xx_SetupPkCallbacks(ctx, &method->version); 18 | #endif /* WOLFSSL_MAXQ10XX_TLS */ 19 | 20 | -#if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) 21 | +#if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) 22 | /* Should only be set when wolfSSL_CTX_load_system_CA_certs() is called */ 23 | ctx->doAppleNativeCertValidationFlag = 0; 24 | -#endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */ 25 | +#endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) */ 26 | 27 | #if defined(WOLFSSL_SYS_CRYPTO_POLICY) 28 | ret = wolfSSL_crypto_policy_init_ctx(ctx, method); 29 | @@ -15688,7 +15690,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, 30 | } 31 | #endif /* WOLFSSL_ALT_CERT_CHAINS */ 32 | 33 | - #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) 34 | + #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) 35 | /* If we are using native Apple CA validation, it is okay 36 | * for a CA cert to fail validation here, as we will verify 37 | * the entire chain when we hit the peer (leaf) cert */ 38 | @@ -15706,7 +15708,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, 39 | /* do not add to certificate manager */ 40 | skipAddCA = 1; 41 | } 42 | - #endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */ 43 | + #endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) */ 44 | 45 | /* Do verify callback */ 46 | ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args); 47 | @@ -15991,7 +15993,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, 48 | if (args->fatal) 49 | DoCertFatalAlert(ssl, ret); 50 | } 51 | - #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) 52 | + #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) 53 | /* Disregard failure to verify peer cert, as we will verify 54 | * the whole chain with the native API later */ 55 | else if (ssl->ctx->doAppleNativeCertValidationFlag) { 56 | @@ -16002,7 +16004,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, 57 | if (args->fatal) 58 | DoCertFatalAlert(ssl, ret); 59 | } 60 | - #endif/*defined(__APPLE__)&& defined(WOLFSSL_SYS_CA_CERTS)*/ 61 | + #endif/*defined(__APPLE__)&& defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) */ 62 | else { 63 | WOLFSSL_MSG("\tNo callback override available, fatal"); 64 | args->fatal = 1; 65 | @@ -16770,7 +16772,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, 66 | } 67 | #endif 68 | 69 | - #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) 70 | + #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) 71 | /* If we can't validate the peer cert chain against the CAs loaded 72 | * into wolfSSL, try to validate against the system certificates 73 | * using Apple's native trust APIs */ 74 | @@ -16784,7 +16786,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, 75 | WOLFSSL_MSG("Apple native cert chain validation FAIL"); 76 | } 77 | } 78 | - #endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */ 79 | + #endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) */ 80 | 81 | /* Do verify callback */ 82 | ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args); 83 | @@ -42601,7 +42603,7 @@ int wolfSSL_sk_BY_DIR_entry_push(WOLF_STACK_OF(WOLFSSL_BY_DIR_entry)* sk, 84 | 85 | #endif /* OPENSSL_ALL && !NO_FILESYSTEM && !NO_FILESYSTEM */ 86 | 87 | -#if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) 88 | +#if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) 89 | 90 | /* 91 | * Converts a DER formatted certificate to a SecCertificateRef 92 | @@ -42734,7 +42736,7 @@ cleanup: 93 | 94 | return ret; 95 | } 96 | -#endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */ 97 | +#endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) && defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) */ 98 | 99 | #undef ERROR_OUT 100 | 101 | -------------------------------------------------------------------------------- /wolfssl/0003-use-proper-warnings-on-MSVC.patch: -------------------------------------------------------------------------------- 1 | From 9b8dd0de2823cdb023c0c14743024c244d7da813 Mon Sep 17 00:00:00 2001 2 | From: Raihaan Shouhell 3 | Date: Thu, 20 Feb 2025 13:12:17 +0800 4 | Subject: [PATCH] use proper warnings on MSVC 5 | 6 | --- 7 | wolfssl/wolfcrypt/settings.h | 6 +++++- 8 | 1 file changed, 5 insertions(+), 1 deletion(-) 9 | 10 | diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h 11 | index e7452de4c..bd49df456 100644 12 | --- a/wolfssl/wolfcrypt/settings.h 13 | +++ b/wolfssl/wolfcrypt/settings.h 14 | @@ -346,7 +346,11 @@ 15 | * an application build -- then your application can avoid this warning by 16 | * defining WOLFSSL_NO_OPTIONS_H or WOLFSSL_CUSTOM_CONFIG as appropriate. 17 | */ 18 | - #warning "No configuration for wolfSSL detected, check header order" 19 | + #if defined(_MSC_VER) /* Microsoft Visual C++ compiler */ 20 | + #pragma message("No configuration for wolfSSL detected, check header order") 21 | + #else 22 | + #warning "No configuration for wolfSSL detected, check header order" 23 | + #endif 24 | #endif 25 | 26 | #include 27 | -- 28 | 2.48.1 -------------------------------------------------------------------------------- /wolfssl/0005-fix-dn-check-apple-native-cert-validation.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/internal.c b/src/internal.c 2 | index eeba025f1..48f5174c2 100644 3 | --- a/src/internal.c 4 | +++ b/src/internal.c 5 | @@ -222,7 +222,7 @@ int writeAeadAuthData(WOLFSSL* ssl, word16 sz, byte type, byte* additional, 6 | #include 7 | #include 8 | #if defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) 9 | -static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs, 10 | +static int DoAppleNativeCertValidation(WOLFSSL* ssl, const WOLFSSL_BUFFER_INFO* certs, 11 | int totalCerts); 12 | #endif /* #if defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) */ 13 | #endif /* #if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */ 14 | @@ -16411,8 +16411,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, 15 | /* If we can't validate the peer cert chain against the CAs loaded 16 | * into wolfSSL, try to validate against the system certificates 17 | * using Apple's native trust APIs */ 18 | - if ((ret != 0) && (ssl->ctx->doAppleNativeCertValidationFlag)) { 19 | - if (DoAppleNativeCertValidation(args->certs, 20 | + if ((ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)) && 21 | + (ssl->ctx->doAppleNativeCertValidationFlag)) { 22 | + if (DoAppleNativeCertValidation(ssl, args->certs, 23 | args->totalCerts)) { 24 | WOLFSSL_MSG("Apple native cert chain validation SUCCESS"); 25 | ret = 0; 26 | @@ -41952,7 +41953,8 @@ cleanup: 27 | * wolfSSL's built-in certificate validation mechanisms anymore. We instead 28 | * must call into the Security Framework APIs to authenticate peer certificates 29 | */ 30 | -static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs, 31 | +static int DoAppleNativeCertValidation(WOLFSSL* ssl, 32 | + const WOLFSSL_BUFFER_INFO* certs, 33 | int totalCerts) 34 | { 35 | int i; 36 | @@ -41961,7 +41963,8 @@ static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs, 37 | CFMutableArrayRef certArray = NULL; 38 | SecCertificateRef secCert = NULL; 39 | SecTrustRef trust = NULL; 40 | - SecPolicyRef policy = NULL ; 41 | + SecPolicyRef policy = NULL; 42 | + CFStringRef hostname = NULL; 43 | 44 | WOLFSSL_ENTER("DoAppleNativeCertValidation"); 45 | 46 | @@ -41990,7 +41993,18 @@ static int DoAppleNativeCertValidation(const WOLFSSL_BUFFER_INFO* certs, 47 | } 48 | 49 | /* Create trust object for SecCertifiate Ref */ 50 | - policy = SecPolicyCreateSSL(true, NULL); 51 | + if (ssl->buffers.domainName.buffer && 52 | + ssl->buffers.domainName.length > 0) { 53 | + /* Create policy with specified value to require host name match */ 54 | + hostname = CFStringCreateWithCString(kCFAllocatorDefault, 55 | + (const char*)ssl->buffers.domainName.buffer, 56 | + kCFStringEncodingUTF8); 57 | + } 58 | + if (hostname != NULL) { 59 | + policy = SecPolicyCreateSSL(true, hostname); 60 | + } else { 61 | + policy = SecPolicyCreateSSL(true, NULL); 62 | + } 63 | status = SecTrustCreateWithCertificates(certArray, policy, &trust); 64 | if (status != errSecSuccess) { 65 | WOLFSSL_MSG_EX("Error creating trust object, " 66 | @@ -42021,6 +42035,9 @@ cleanup: 67 | if (policy) { 68 | CFRelease(policy); 69 | } 70 | + if (hostname) { 71 | + CFRelease(hostname); 72 | + } 73 | 74 | WOLFSSL_LEAVE("DoAppleNativeCertValidation", ret); 75 | 76 | --------------------------------------------------------------------------------