├── .github └── workflows │ └── workflow.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bin ├── CZC-1.0.bin ├── CZC-1.0_v1.0.0.full.bin ├── bootloader_dio_40m.bin └── partitions.bin ├── lib ├── CCTools │ ├── library.json │ ├── library.properties │ └── src │ │ ├── CCTools.cpp │ │ └── CCTools.h ├── IntelHex │ ├── library.json │ ├── library.properties │ └── src │ │ ├── IntelHex.cpp │ │ └── IntelHex.h └── WireGuard-ESP32 │ ├── .gitignore │ ├── .piopm │ ├── LICENSE │ ├── README.md │ ├── examples │ ├── disconnect │ │ └── disconnect.ino │ ├── uptime_post │ │ └── uptime_post.ino │ └── uptime_udp │ │ └── uptime_udp.ino │ ├── library.properties │ └── src │ ├── WireGuard-ESP32.h │ ├── WireGuard.cpp │ ├── crypto.c │ ├── crypto.h │ ├── crypto │ └── refc │ │ ├── blake2s.c │ │ ├── blake2s.h │ │ ├── chacha20.c │ │ ├── chacha20.h │ │ ├── chacha20poly1305.c │ │ ├── chacha20poly1305.h │ │ ├── poly1305-donna-32.h │ │ ├── poly1305-donna.c │ │ ├── poly1305-donna.h │ │ ├── x25519-license.txt │ │ ├── x25519.c │ │ └── x25519.h │ ├── wireguard-platform.c │ ├── wireguard-platform.h │ ├── wireguard.c │ ├── wireguard.h │ ├── wireguardif.c │ └── wireguardif.h ├── manifest.json ├── platformio.ini ├── src ├── config.h ├── etc.cpp ├── etc.h ├── log.cpp ├── log.h ├── main.cpp ├── mqtt.cpp ├── mqtt.h ├── version.h ├── web.cpp ├── web.h ├── websrc │ ├── .gitignore │ ├── css │ │ ├── bootstrap.min.css │ │ ├── required.css │ │ └── style.css │ ├── html │ │ ├── PAGE_ABOUT.html │ │ ├── PAGE_ETHERNET.html │ │ ├── PAGE_GENERAL.html │ │ ├── PAGE_LOADER.html │ │ ├── PAGE_LOGOUT.html │ │ ├── PAGE_MQTT.html │ │ ├── PAGE_ROOT.html │ │ ├── PAGE_SECURITY.html │ │ ├── PAGE_SERIAL.html │ │ ├── PAGE_SYSTOOLS.html │ │ ├── PAGE_WG.html │ │ └── PAGE_WIFI.html │ ├── img │ │ ├── favicon.ico │ │ ├── icons.svg │ │ └── logo.png │ └── js │ │ ├── bootstrap.min.js │ │ ├── functions.js │ │ ├── jquery-min.js │ │ └── masonry.js ├── zb.cpp ├── zb.h └── zones.h └── tools ├── .version_no_increment ├── build.py ├── commit.sh ├── debug_build.py ├── esptool.py ├── flash.sh ├── make_git_hook.sh ├── merge_bin_esp.py ├── version ├── version_increment_post.py ├── version_increment_pre.py └── webfilesbuilder ├── .gitignore ├── buildWeb.bat ├── build_html.py ├── gulp.js ├── gulp.meta.js ├── gulpfile.js └── package.json /.github/workflows/workflow.yml: -------------------------------------------------------------------------------- 1 | name: Build, release, update 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | workflow_dispatch: 8 | push: 9 | tags: 10 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 11 | 12 | jobs: 13 | build_firmware: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Clone repository 17 | uses: actions/checkout@v4 18 | with: 19 | ref: "czc" 20 | 21 | - name: Install Node JS 22 | uses: actions/setup-node@v3 23 | with: 24 | node-version: 18 25 | - uses: actions/cache@v3 26 | with: 27 | path: | 28 | ~/.cache/pip 29 | ~/.platformio/.cache 30 | key: ${{ runner.os }}-pio 31 | - name: Install Python 32 | uses: actions/setup-python@v4 33 | with: 34 | python-version: '3.9' 35 | - name: Install PlatformIO Core 36 | run: pip install --upgrade platformio==6.1.11 37 | 38 | - name: Build PlatformIO Project 39 | run: pio run 40 | - name: Get Release Version 41 | id: get_version 42 | shell: bash 43 | run: | 44 | value=`cat tools/version` 45 | echo "version=$value" >> $GITHUB_OUTPUT 46 | - name: Get current date 47 | id: date 48 | run: echo "date=$(date +'%d%m%y')" >> $GITHUB_OUTPUT 49 | - name: Release 50 | uses: softprops/action-gh-release@v1 51 | with: 52 | generate_release_notes: true 53 | name: "v${{ steps.get_version.outputs.version }} (${{ steps.date.outputs.date }})" 54 | files: | 55 | bin/CZC-1.0.bin 56 | bin/CZC-1.0_v${{ steps.get_version.outputs.version }}.full.bin 57 | 58 | - name: Updare version in manifest.json 59 | run: | 60 | sed -r 's/v[0-9]{1,4}\.[0-9]{1,4}\.[0-9]{1,4}/v${{ steps.get_version.outputs.version }}/g' manifest.json > new.manifest.json 61 | - name: Move file 62 | shell: bash 63 | run: | 64 | echo "old" 65 | cat manifest.json 66 | mv -f new.manifest.json manifest.json 67 | echo "new" 68 | cat manifest.json 69 | 70 | - name: Commit & Push changes 71 | uses: actions-js/push@master 72 | with: 73 | github_token: ${{ secrets.GITHUB_TOKEN }} 74 | message: 'Release v${{ steps.get_version.outputs.version }} (${{ steps.date.outputs.date }})' 75 | force: true 76 | branch: czc -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | .pio 3 | .vscode 4 | .gcc-flags.json 5 | .clang_complete 6 | commit* 7 | test.html 8 | gzipped 9 | webh 10 | *.code-workspace 11 | logs 12 | todo 13 | !lib 14 | !platformio.ini -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## [0.1.1] 20230813 6 | ### Added 7 | 8 | - Initial release 9 | 10 | ### Changed 11 | 12 | ### Fixed 13 | 14 | ### Removed 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | - Using welcoming and inclusive language 12 | - Being respectful of differing viewpoints and experiences 13 | - Gracefully accepting constructive criticism 14 | - Focusing on what is best for the community 15 | - Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | - Trolling, insulting/derogatory comments, and personal or political attacks 21 | - Public or private harassment 22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | - Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | 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, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at esphome@nabucasa.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | **Any contribution helps our team and makes ZigStar UZG better for the entire community!** 4 | 5 | Everybody is welcome and invited to contribute to UZG Project by: 6 | 7 | * Testing newly released features and reporting issues. 8 | * Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes) 9 | * Contributing missing documentation for features and devices in our [documentation](https://uzg.zig-star.com) 10 | 11 | This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs. 12 | 13 | ## Opening New Issues 14 | 15 | **Issue tracker is NOT a general discussion forum!** 16 | 1. Opening an issue means that a problem exists in the code and should be addressed by the project contributors. 17 | 2. When opening an issue, it is required to fill out the presented template. The requested information is important! If the template is ignored or insufficient info about the issue is provided, the issue may be closed. 18 | 3. Questions of type "How do I..." or "Can you please help me with..." or "Can ZigStar UZG do..." WILL NOT be handled here. Such questions should be directed at a discussion forum or to the ZigStar Support Chat. All issues of this type will be closed with a simple reference to this contributing policy. 19 | 4. Issues about topics already handled in the documentation will be closed in a similar manner. 20 | 5. Issues for unmerged PRs will be closed. If there is an issue with a PR, the explanation should be added to the PR itself. 21 | 6. Issues with accompanied investigation that shows the root of the problem should be given priority. 22 | 7. Duplicate issues will be closed. 23 | 24 | ## Triaging of Issues/PR's 25 | 26 | 1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so. 27 | 2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor. 28 | 3. Issues that are accepted should be marked with appropriate labels. 29 | 4. Issues that could impact functionality for many users should be considered severe. 30 | 5. Issues caused by the SDK or chip should not be marked severe, as there usually isn’t much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users. 31 | 6. Issues with feature requests should be discussed for viability/desirability. 32 | 7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified. 33 | 8. Feature requests that are not accompanied by a PR: 34 | * could be closed immediately (denied). 35 | * could be closed after some predetermined period of time (left as candidate for somebody to pick up). 36 | 9. In some cases, feedback may be requested from the issue reporter, either as additional info for clarification, additional testing, or other. If no feedback is provided, the issue may be closed by a contributor or after 30 days by the STALE bot. 37 | 38 | ## Pull requests 39 | 40 | A Pull Request (PR) is the process where code modifications are managed in GitHub. 41 | 42 | The process is straight-forward. 43 | 44 | - Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0) 45 | - Fork the [Git repository](https://github.com/mercenaruss/uzg-firmware). 46 | - Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc. 47 | - Ensure tests work. 48 | - Create a Pull Request against the [**development**](https://github.com/mercenaruss/uzg-firmware/tree/dev) branch of uzg-firmware. 49 | 50 | 1. All pull requests must be done against the development branch. 51 | 2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). 52 | 3. Only one feature/fix should be added per PR. 53 | 4. If adding a new functionality (new hardware, new library support) not related to an existing component move it to it's own modules (.ino file). 54 | 5. PRs that don't compile (fail in CI Tests) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in development - you might need to rebase and resolve conflicts. 55 | 6. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. 56 | 7. All pull requests should consider updates to the documentation. 57 | 8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. 58 | 9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. 59 | 10. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA. 60 | 11. Pull requests that don't meet the above will be denied and closed. 61 | 62 | -------------------------------------- 63 | 64 | ## Contributor License Agreement (CLA) 65 | 66 | ``` 67 | By making a contribution to this project, I certify that: 68 | 69 | (a) The contribution was created in whole or in part by me and I 70 | have the right to submit it under the GPL-3.0 license; or 71 | 72 | (b) The contribution is based upon previous work that, to the best 73 | of my knowledge, is covered under an appropriate open source 74 | license and I have the right under that license to submit that 75 | work with modifications, whether created in whole or in part 76 | by me, under the GPL-3.0 license; or 77 | 78 | (c) The contribution was provided directly to me by some other 79 | person who certified (a), (b) or (c) and I have not modified 80 | it. 81 | 82 | (d) I understand and agree that this project and the contribution 83 | are public and that a record of the contribution (including all 84 | personal information I submit with it) is maintained indefinitely 85 | and may be redistributed consistent with this project or the open 86 | source license(s) involved. 87 | ``` 88 | 89 | This Contributor License Agreement (CLA) was adopted on April 1st, 2019. 90 | 91 | The text of this license is available under the [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). It is based on the Linux [Developer Certificate Of Origin](http://elinux.org/Developer_Certificate_Of_Origin), but is modified to explicitly use the GPL-3.0 license and not mention sign-off (due to GitHub.com keeps an historial, with your user name, of PRs' commits and all editions on PR's comments). 92 | 93 | To accept the CLA it is required to put a x between [ ] on `[ ] I accept the CLA` in the PR template when submitting it. The [ ] is an opt-in box, so you have to manually accept it. 94 | 95 | **Why a CLA ?** 96 | 97 | _"A Contributor Licence Agreement (CLA) is strongly recommended when accepting third party contributions to an open development project, such as an open source software project. In order to redistribute contributions, it is necessary to ensure that the project has the necessary rights to do so. A Contributor Licence Agreement is a lightweight agreement, signed by the copyright holder, that grants the necessary rights for the contribution to be redistributed as part of the project."_ [OSS Watch](http://oss-watch.ac.uk/resources/cla) 98 | 99 | A CLA is a legal document in which you state _you are entitled to contribute the code/documentation/translation to the project_ you’re contributing to and that _you are willing to have it used in distributions and derivative works_. This means that should there be any kind of legal issue in the future as to the origins and ownership of any particular piece of code, then that project has the necessary forms on file from the contributor(s) saying they were permitted to make this contribution. 100 | 101 | CLA is a safety because it also ensures that once you have provided a contribution, you cannot try to withdraw permission for its use at a later date. People can therefore use that software, confident that they will not be asked to stop using pieces of the code at a later date. 102 | 103 | A __license__ grants "outbound" rights to the user of project. 104 | 105 | A __CLA__ enables a contributor to grant "inbound" rights to a project. 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZigStar codm Zigbee Coordinator Firmware 2 | 3 | This firmware is forked from UZG-01 firmware with changed visuals and board specific changes. 4 | 5 | TBD... 6 | -------------------------------------------------------------------------------- /bin/CZC-1.0.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codm/czc-firmware/b33f581bccd5c7e876616fb3a36458f28ad36099/bin/CZC-1.0.bin -------------------------------------------------------------------------------- /bin/CZC-1.0_v1.0.0.full.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codm/czc-firmware/b33f581bccd5c7e876616fb3a36458f28ad36099/bin/CZC-1.0_v1.0.0.full.bin -------------------------------------------------------------------------------- /bin/bootloader_dio_40m.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codm/czc-firmware/b33f581bccd5c7e876616fb3a36458f28ad36099/bin/bootloader_dio_40m.bin -------------------------------------------------------------------------------- /bin/partitions.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codm/czc-firmware/b33f581bccd5c7e876616fb3a36458f28ad36099/bin/partitions.bin -------------------------------------------------------------------------------- /lib/CCTools/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CCTools", 3 | "frameworks": "Arduino", 4 | "keywords": "cc2652, zigbee, flash", 5 | "description": "Work with TI CC(2538/1352/2652) series chips: read, write, verify firmware, get chip ID, etc.", 6 | "url": "https://github.com/xyzroe/CCTools", 7 | "authors": { 8 | "name": "xyzroe" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/xyzroe/CCTools" 13 | }, 14 | "version": "0.0.1" 15 | } -------------------------------------------------------------------------------- /lib/CCTools/library.properties: -------------------------------------------------------------------------------- 1 | name=CCTools 2 | version=0.0.1 3 | author=xyzroe 4 | maintainer=xyzroe 5 | sentence="Work with TI CC(2538/1352/2652) series chips: read, write, verify firmware, get chip ID, etc." 6 | paragraph= 7 | category=Communication 8 | url="https://github.com/xyzroe/CCTools" 9 | includes=CCTools.h 10 | architectures=esp32 11 | -------------------------------------------------------------------------------- /lib/CCTools/src/CCTools.h: -------------------------------------------------------------------------------- 1 | #ifndef CCTools_DETECT_H 2 | #define CCTools_DETECT_H 3 | 4 | #include 5 | 6 | class CommandInterface 7 | { 8 | protected: 9 | Stream &_stream; 10 | 11 | static const uint8_t ACK_BYTE = 0xCC; 12 | static const uint8_t NACK_BYTE = 0x33; 13 | static const uint8_t COMMAND_RET_SUCCESS = 0x40; 14 | 15 | static const uint32_t ICEPICK_DEVICE_ID = 0x50001318; 16 | static const uint32_t FCFG_USER_ID = 0x50001294; 17 | static const uint32_t PRCM_RAMHWOPT = 0x40082250; 18 | static const uint32_t FLASH_SIZE = 0x4003002C; 19 | static const uint32_t PROTO_MASK_BLE = 0x01; 20 | static const uint32_t PROTO_MASK_IEEE = 0x04; 21 | static const uint32_t PROTO_MASK_BOTH = 0x05; 22 | 23 | static const uint32_t flash_start_addr = 0x00000000; 24 | 25 | static const uint32_t addr_ieee_address_primary = 0x500012F0; 26 | static const uint32_t ccfg_len = 88; 27 | static const uint32_t ieee_address_secondary_offset = 0x20; 28 | static const uint32_t bootloader_dis_offset = 0x30; 29 | 30 | const char *_getStatusString(uint8_t statusCode) 31 | { 32 | switch (statusCode) 33 | { 34 | case 0x40: 35 | return "Success"; 36 | case 0x41: 37 | return "Unknown command"; 38 | case 0x42: 39 | return "Invalid command"; 40 | case 0x43: 41 | return "Invalid address"; 42 | case 0x44: 43 | return "Flash fail"; 44 | default: 45 | return "Unknown"; 46 | } 47 | } 48 | 49 | const char *_getChipIdString(uint32_t chipId) 50 | { 51 | switch (chipId) 52 | { 53 | case 0xb964: 54 | return "CC2538"; 55 | case 0xb965: 56 | return "CC2538"; 57 | case 0xf000: 58 | return "CC2652"; 59 | default: 60 | return "Unknown"; 61 | } 62 | } 63 | 64 | String _getPackage(byte user_id) 65 | { 66 | byte packageCode = user_id & 0x03; // Получаем младшие 2 бита user_id 67 | 68 | switch (packageCode) 69 | { 70 | case 0x00: 71 | return "4x4mm"; 72 | case 0x01: 73 | return "5x5mm"; 74 | case 0x02: 75 | return "7x7mm"; 76 | case 0x03: 77 | return "Wafer"; 78 | case 0x04: 79 | return "2.7x2.7"; 80 | case 0x05: 81 | return "7x7mm Q1"; 82 | default: 83 | return "Unknown"; 84 | } 85 | } 86 | 87 | CommandInterface(Stream &serial); 88 | 89 | bool _sendSynch(); 90 | bool _wait_for_ack(unsigned long timeout); 91 | uint32_t _cmdGetChipId(); 92 | byte *_receivePacket(); 93 | byte *_cmdGetStatus(); 94 | bool _checkLastCmd(); 95 | void _sendAck(); 96 | void _sendNAck(); 97 | void _eraseFlash(); 98 | bool _ping(); 99 | void _encodeAddr(unsigned long addr, byte encodedAddr[4]); 100 | unsigned long _decodeAddr(byte byte0, byte byte1, byte byte2, byte byte3); 101 | byte _calcChecks(byte cmd, unsigned long addr, unsigned long size); 102 | byte *_cmdMemRead(uint32_t address); 103 | }; 104 | 105 | class CCTools : public CommandInterface 106 | { 107 | private: 108 | int _CC_RST_PIN, _CC_BSL_PIN, _BSL_MODE; 109 | 110 | 111 | public: 112 | // Adjusted constructor declaration 113 | CCTools(Stream &serial, int CC_RST_PIN, int CC_BSL_PIN, int BSL_MODE = 0); 114 | 115 | bool begin(); 116 | bool eraseFlash(); 117 | bool ping(); 118 | String detectChipInfo(); 119 | void enterBSL(); 120 | void restart(); 121 | void routerRejoin(); 122 | }; 123 | 124 | #endif // CCTools_DETECT_H -------------------------------------------------------------------------------- /lib/IntelHex/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "IntelHex", 3 | "frameworks": "Arduino", 4 | "keywords": "IntelHex, cc2652, zigbee, flash", 5 | "description": "Read and parse Intel Hex format files from the LittleFS file system.", 6 | "url": "https://github.com/xyzroe/IntelHex", 7 | "authors": { 8 | "name": "OpenAI's ChatGPT with contributions from xyzroe" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/xyzroe/IntelHex" 13 | }, 14 | "version": "0.0.3" 15 | } -------------------------------------------------------------------------------- /lib/IntelHex/library.properties: -------------------------------------------------------------------------------- 1 | name=IntelHex 2 | version=0.0.3 3 | author="OpenAI's ChatGPT with contributions from xyzroe" 4 | maintainer=xyzroe 5 | sentence="Read and parse Intel Hex format files from the LittleFS file system." 6 | paragraph= 7 | category=Communication 8 | url="https://github.com/xyzroe/IntelHex" 9 | includes=IntelHex.h 10 | architectures=esp32 11 | -------------------------------------------------------------------------------- /lib/IntelHex/src/IntelHex.cpp: -------------------------------------------------------------------------------- 1 | #include "IntelHex.h" 2 | #include 3 | 4 | /* 5 | * IntelHex Arduino Library 6 | * 7 | * Description: 8 | * This library is designed to read and parse Intel Hex format files from the LittleFS file system on ESP8266 and ESP32. 9 | * 10 | * License: 11 | * MIT License 12 | * 13 | * Author: 14 | * OpenAI's ChatGPT with contributions from xyzroe 15 | */ 16 | /* 17 | 18 | If you want library to control LittleFS you need to uncomment some lines. 19 | 20 | */ 21 | 22 | #ifndef DEBUG_PRINT 23 | #ifdef DEBUG 24 | #define DEBUG_PRINT(x) Serial.print(String(x)) 25 | #define DEBUG_PRINTLN(x) Serial.println(String(x)) 26 | #else 27 | #define DEBUG_PRINT(x) 28 | #define DEBUG_PRINTLN(x) 29 | #endif 30 | #endif 31 | 32 | IntelHex::IntelHex(const char *filename) : _filename(filename) {} 33 | 34 | IntelHex::~IntelHex() 35 | { 36 | if (_file) 37 | { 38 | _file.close(); 39 | } 40 | } 41 | 42 | bool IntelHex::open() 43 | { 44 | // if (!LittleFS.begin()) { 45 | // Serial.println("Could not mount file system"); 46 | // return false; 47 | // } 48 | _file = LittleFS.open(_filename, "r"); 49 | return _file; 50 | } 51 | 52 | void IntelHex::close() 53 | { 54 | _file.close(); 55 | // LittleFS.end(); 56 | } 57 | 58 | bool IntelHex::parse(void (*preCallback)(), void (*parseCallback)(uint32_t address, uint8_t len, uint8_t *data, size_t currentPosition, size_t totalSize), void (*postCallback)()) 59 | { 60 | if (!open()) 61 | { 62 | return false; 63 | } 64 | 65 | _totalSize = _file.size(); 66 | DEBUG_PRINTLN(String("_file.size() = ") + String(_totalSize)); 67 | 68 | preCallback(); 69 | 70 | bool status = true; 71 | 72 | while (status == true && _file.available() && _file_last_line == false) 73 | { 74 | status = _munchLine(parseCallback); 75 | } 76 | 77 | if (_file_last_line) 78 | { 79 | DEBUG_PRINTLN("HEX file last line found"); 80 | _file_parsed = true; 81 | } 82 | else 83 | { 84 | DEBUG_PRINTLN("HEX file last line NOT found"); 85 | status = false; 86 | } 87 | 88 | postCallback(); 89 | 90 | close(); 91 | return status; 92 | } 93 | 94 | /* 95 | bool IntelHex::validateChecksum() 96 | { 97 | DEBUG_PRINTLN("Starting checksum validation"); 98 | 99 | if (!open()) 100 | { 101 | DEBUG_PRINTLN("Failed to open file"); 102 | return false; 103 | } 104 | 105 | String line; 106 | while (_file.available()) 107 | { 108 | line = _file.readStringUntil('\n'); 109 | line.trim(); 110 | 111 | if (line.length() < 11 || line[0] != ':') 112 | { 113 | DEBUG_PRINTLN("Skipping non-data line or line too short"); 114 | continue; 115 | } 116 | 117 | // Проверяем на строку окончания файла Intel HEX 118 | if (line == ":00000001FF") 119 | { 120 | DEBUG_PRINTLN("Intel HEX file end line found, checksum validation passed"); 121 | close(); 122 | return true; 123 | } 124 | 125 | uint8_t sum = 0; 126 | // Считаем сумму всех байтов строки, за исключением начального ':' 127 | for (int i = 1; i < line.length(); i += 2) 128 | { 129 | uint8_t byteValue = strtol(line.substring(i, i + 2).c_str(), nullptr, 16); 130 | sum += byteValue; 131 | } 132 | 133 | // Проверка контрольной суммы 134 | if (sum != 0) 135 | { 136 | DEBUG_PRINTLN("Checksum validation failed"); 137 | close(); 138 | return false; 139 | } 140 | } 141 | 142 | DEBUG_PRINTLN("Checksum validation passed, but no end line found - file might be incomplete"); 143 | close(); 144 | return false; // Если мы достигли этой точки, значит, строка окончания файла не была найдена. 145 | } 146 | */ 147 | 148 | /* 149 | bool IntelHex::checkBSLConfiguration() { 150 | DEBUG_PRINTLN("checkBSLConfiguration: Starting BSL configuration check"); 151 | 152 | if (!open()) { 153 | DEBUG_PRINTLN("checkBSLConfiguration: Failed to open file"); 154 | return false; 155 | } 156 | 157 | const uint32_t addresses[] = {ALL_CHIP_ADDRESS, P7_CHIP_ADDRESS}; 158 | bool foundBSL = false; 159 | 160 | for (auto address : addresses) { 161 | DEBUG_PRINT("checkBSLConfiguration: Checking address: "); 162 | DEBUG_PRINTLN(String(address, HEX)); 163 | 164 | // Предполагаем, что BSL конфигурация начинается непосредственно с этого адреса. 165 | // Важно отметить, что в файле Intel Hex адреса не обязательно идут последовательно и могут быть разбросаны. 166 | // Это может потребовать специфической логики для перемещения по файлу. 167 | 168 | // Чтение данных из файла, предполагая, что они могут находиться по этому адресу. 169 | _file.seek(address, SeekSet); 170 | uint8_t data[4]; // Предполагаем, что для проверки BSL конфигурации достаточно 4 байтов. 171 | if (_file.read(data, 4) != 4) { 172 | DEBUG_PRINTLN("checkBSLConfiguration: Failed to read data"); 173 | continue; // Если не удается прочитать 4 байта, переходим к следующему адресу. 174 | } 175 | 176 | // Добавляем логирование прочитанных данных, чтобы увидеть, что было считано. 177 | DEBUG_PRINT("checkBSLConfiguration: Read data: "); 178 | for (int i = 0; i < 4; ++i) { 179 | DEBUG_PRINT(String(data[i], HEX)); 180 | DEBUG_PRINT(" "); 181 | } 182 | DEBUG_PRINTLN(); 183 | 184 | foundBSL = _checkBSLconfig(address, 4, data); 185 | if (foundBSL) { 186 | DEBUG_PRINTLN("checkBSLConfiguration: BSL configuration found and valid"); 187 | break; // Если нашли и проверили конфигурацию BSL, прерываем цикл. 188 | } 189 | } 190 | 191 | if (!foundBSL) { 192 | DEBUG_PRINTLN("checkBSLConfiguration: BSL configuration not found or invalid"); 193 | } 194 | 195 | close(); 196 | return foundBSL; 197 | } 198 | */ 199 | 200 | bool IntelHex::_munchLine(void (*parseCallback)(uint32_t address, uint8_t len, uint8_t *data, size_t currentPosition, size_t totalSize)) 201 | { 202 | 203 | String line = _file.readStringUntil('\n'); 204 | line.trim(); 205 | 206 | // DEBUG_PRINTLN("Parsing line: " + line); // Print each processed line 207 | // delay(1); 208 | 209 | if (line.length() == 0 || line[0] != ':') 210 | { 211 | return true; // Continue parsing 212 | } 213 | 214 | uint8_t sum = 0; 215 | for (int i = 1; i < line.length(); i += 2) 216 | { 217 | sum += strtol(line.substring(i, i + 2).c_str(), nullptr, 16); 218 | } 219 | 220 | if (sum != 0) 221 | { 222 | DEBUG_PRINTLN("Checksum line error"); 223 | return false; 224 | } 225 | 226 | if (line == ":00000001FF") 227 | { // look like Intel HEX file end line 228 | DEBUG_PRINTLN("File last line found"); 229 | _file_last_line = true; 230 | return true; 231 | } 232 | 233 | uint8_t len = strtol(line.substring(1, 3).c_str(), nullptr, 16); 234 | uint16_t offset_low = strtol(line.substring(3, 7).c_str(), nullptr, 16); 235 | uint8_t recordType = strtol(line.substring(7, 9).c_str(), nullptr, 16); 236 | 237 | // DEBUG_PRINTLN("Record Type: " + String(recordType, HEX) + ", Offset Low: " + String(offset_low, HEX) + ", Length: " + String(len, HEX)); // Print record info 238 | 239 | uint8_t data[255]; 240 | uint32_t address = offset_low; 241 | // https://jimmywongiot.com/2021/04/20/format-of-IntelHex/ 242 | if (recordType == 4) 243 | { 244 | _offset_high = ((uint32_t)strtol(line.substring(9, 13).c_str(), nullptr, 16)) << 16; // because 4 245 | } 246 | else if (recordType == 2) 247 | { 248 | _offset_high = ((uint32_t)strtol(line.substring(9, 13).c_str(), nullptr, 16)) << 4; // because 2 249 | } 250 | 251 | address += _offset_high; 252 | 253 | esp_task_wdt_reset(); 254 | //#ifdef DEBUG 255 | // delay(5); // to avoid reboot 256 | //#endif 257 | 258 | for (int i = 0; i < ELEMENTCOUNT(CCFG_ADDRESS); i++) 259 | { 260 | // DEBUG_PRINT(CCFG_ADDRESS[i]); 261 | // DEBUG_PRINT(" "); 262 | if (address <= CCFG_ADDRESS[i] && address + len > CCFG_ADDRESS[i] + 4) 263 | { 264 | //DEBUG_PRINTLN(" "); 265 | //DEBUG_PRINTLN("CCFG_ADDRESS[" + String(i) + "] in range"); 266 | 267 | 268 | for (uint8_t i = 0; i < len; i++) 269 | { 270 | data[i] = strtol(line.substring(9 + i * 2, 11 + i * 2).c_str(), nullptr, 16); 271 | } 272 | 273 | if (!_bsl_valid) 274 | { 275 | _bsl_valid = _checkBSLconfig(address, len, data); 276 | } 277 | } 278 | } 279 | 280 | size_t currentPosition = _file.position(); 281 | 282 | parseCallback(address, len, data, currentPosition, _totalSize); 283 | 284 | return true; 285 | } 286 | 287 | bool IntelHex::_checkBSLconfig(uint32_t address, uint8_t len, uint8_t *data) 288 | { 289 | // Check if CCFG is within the buffer 290 | // DEBUG_PRINTLN(" "); 291 | // DEBUG_PRINT(ELEMENTCOUNT(CCFG_ADDRESS)); 292 | // DEBUG_PRINT(" "); 293 | 294 | for (int i = 0; i < ELEMENTCOUNT(CCFG_ADDRESS); i++) 295 | { 296 | // DEBUG_PRINT(CCFG_ADDRESS[i]); 297 | // DEBUG_PRINT(" "); 298 | if (address <= CCFG_ADDRESS[i] && address + len > CCFG_ADDRESS[i] + 4) 299 | { 300 | DEBUG_PRINTLN(" "); 301 | DEBUG_PRINTLN("CCFG_ADDRESS[" + String(i) + "] in range"); 302 | 303 | if (data[CCFG_ADDRESS[i] - address + 3] == BOOTLOADER_ENABLE) 304 | { 305 | DEBUG_PRINTLN("Bootloader enabled"); 306 | _bsl_bootloader_enbl = true; 307 | } 308 | 309 | if (data[CCFG_ADDRESS[i] - address + 0] == BL_ENABLE) 310 | { 311 | DEBUG_PRINTLN("'failure analysis' enabled"); 312 | _bsl_bl_enbl = true; 313 | } 314 | 315 | if (data[CCFG_ADDRESS[i] - address + 2] == BL_LEVEL_LOW) 316 | { 317 | DEBUG_PRINTLN("BSL low level"); 318 | _bsl_level = 1; 319 | } 320 | else if (data[CCFG_ADDRESS[i] - address + 2] == BL_LEVEL_HIGH) 321 | { 322 | DEBUG_PRINTLN("BSL high level"); 323 | _bsl_level = 2; 324 | } 325 | else 326 | { 327 | DEBUG_PRINTLN("BSL level UNKNOWN. Error!"); 328 | _bsl_level = 0; 329 | } 330 | 331 | // Pin in HEX converts to DEC number 332 | _bsl_pin = data[CCFG_ADDRESS[i] - address + 1]; 333 | DEBUG_PRINTLN("BSL pin - " + String(_bsl_pin)); 334 | 335 | if (_bsl_bootloader_enbl && _bsl_bl_enbl && (_bsl_level > 0) && (_bsl_pin > 0)) 336 | { 337 | DEBUG_PRINTLN("BSL valid!"); 338 | _bsl_addr = i; 339 | return true; 340 | } 341 | } 342 | } 343 | return false; 344 | } 345 | -------------------------------------------------------------------------------- /lib/IntelHex/src/IntelHex.h: -------------------------------------------------------------------------------- 1 | #ifndef INTELHEX_H 2 | #define INTELHEX_H 3 | 4 | #include 5 | #include "LittleFS.h" 6 | 7 | #define ELEMENTCOUNT(x) (sizeof(x) / sizeof(x[0])) 8 | 9 | class IntelHex 10 | { 11 | public: 12 | IntelHex(const char *filename); 13 | ~IntelHex(); 14 | 15 | bool parse(void (*preCallback)(), void (*parseCallback)(uint32_t address, uint8_t len, uint8_t *data, size_t currentPosition, size_t totalSize), void (*postCallback)()); 16 | void setFileValidated(bool value) { _file_validated = value; } 17 | 18 | bool fileParsed() const { return _file_parsed; } 19 | bool fileValidated() const { return _file_validated; } 20 | 21 | bool bslActive() const { return _bsl_valid; } 22 | int bslPin() const { return _bsl_pin; } 23 | bool bslLevel() const { return _bsl_level - 1; } // 0 error, 1 low, 2 high 24 | bool bslAddr() const { return _bsl_addr; } // 0 - all seriers, 1 - P/R 7 series 25 | 26 | 27 | bool validateChecksum(); // Построчная валидация контрольной суммы 28 | bool checkBSLConfiguration(); // Проверка конфигурации BSL 29 | 30 | 31 | private: 32 | const char *_filename; 33 | File _file; 34 | bool _file_parsed = false; 35 | bool _file_validated = false; 36 | bool _file_last_line = false; 37 | uint32_t _offset_high; 38 | 39 | bool _bsl_bootloader_enbl = false; 40 | bool _bsl_bl_enbl = false; 41 | int _bsl_level = 0; 42 | int _bsl_pin = 0; 43 | bool _bsl_valid = false; 44 | int _bsl_addr = 0; 45 | 46 | size_t _totalSize = 0; 47 | 48 | // const uint32_t CCFG_ADDRESS = 0x057FD8; // all others 49 | const uint32_t ALL_CHIP_ADDRESS = 0x057FD8; 50 | const uint32_t P7_CHIP_ADDRESS = 0x0AFFD8; 51 | const uint32_t CCFG_ADDRESS[2] = {ALL_CHIP_ADDRESS, P7_CHIP_ADDRESS}; 52 | 53 | #define ALL_CHIP_ID 0 54 | #define P7_CHIP_ID 1 55 | 56 | // const uint32_t CCFG_ADDRESS = 0x0AFFD8; //CC2652R7 and CC1352P7 57 | 58 | /* 59 | Parsing line: :020000025000AC ordinary so 0x057FD8 60 | Parsing line: :02000002A0005C but in 2652R7 so maybe 0x0AFFD8 61 | */ 62 | 63 | const uint32_t BOOTLOADER_ENABLE = 0xC5; //(Bootloader enable. SET_CCFG_BL_CONFIG_BOOTLOADER_ENABLE in CC13xx/CCToolsware) 64 | 65 | const uint32_t BL_LEVEL_LOW = 0xFE; //(Active low. SET_CCFG_BL_CONFIG_BL_LEVEL in CC13xx/CCToolsware) 66 | const uint32_t BL_LEVEL_HIGH = 0xFF; // ? NEED to check! 67 | 68 | const uint32_t BL_ENABLE = 0xC5; // (Enable "failure analysis". SET_CCFG_BL_CONFIG_BL_ENABLE in CC13xx/CCToolsware) 69 | 70 | bool open(); 71 | void close(); 72 | bool _munchLine(void (*parseCallback)(uint32_t address, uint8_t len, uint8_t *data, size_t currentPosition, size_t totalSize)); 73 | bool _checkBSLconfig(uint32_t address, uint8_t len, uint8_t *data); 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/.gitignore: -------------------------------------------------------------------------------- 1 | build.sh -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/.piopm: -------------------------------------------------------------------------------- 1 | {"type": "library", "name": "WireGuard-ESP32", "version": "0.1.5", "spec": {"owner": "ciniml", "id": 12571, "name": "WireGuard-ESP32", "requirements": null, "uri": null}} -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Kenta Ida (fuga@fugafuga.org) 2 | Copyright (c) 2021 Daniel Hope (www.floorsense.nz) 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | * Neither the name of "Floorsense Ltd", "Agile Workspace Ltd" nor the names of 13 | its contributors may be used to endorse or promote products derived from this 14 | software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | Author: Daniel Hope 28 | 29 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/README.md: -------------------------------------------------------------------------------- 1 | # WireGuard Implementation for ESP32 Arduino 2 | 3 | This is an implementation of the [WireGuard®](https://www.wireguard.com/) for ESP32 Arduino. 4 | 5 | Almost all of this code is based on the [WireGuard Implementation for lwIP](https://github.com/smartalock/wireguard-lwip), but some potion of the code is adjusted to build with ESP32 Arduino. 6 | 7 | ## How to use 8 | 9 | 1. Include `WireGuard-ESP32.h` at the early part of the sketch. 10 | 11 | ```c++ 12 | #include 13 | ``` 14 | 15 | 2. Define the instance of the `WireGuard` class at module level. 16 | 17 | ```c++ 18 | static WireGuard wg; 19 | ``` 20 | 21 | 3. Connect to WiFi AP by using `WiFi` class. 22 | 23 | ```c++ 24 | WiFi.begin(ssid, password); 25 | while( !WiFi.isConnected() ) { 26 | delay(1000); 27 | } 28 | ``` 29 | 30 | 4. Sync the system time via NTP. 31 | 32 | ```c++ 33 | configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp", "time.google.com"); 34 | ``` 35 | 36 | 5. Start the WireGuard interface. 37 | 38 | ```c++ 39 | wg.begin( 40 | local_ip, // IP address of the local interface 41 | private_key, // Private key of the local interface 42 | endpoint_address, // Address of the endpoint peer. 43 | public_key, // Public key of the endpoint peer. 44 | endpoint_port); // Port pf the endpoint peer. 45 | ``` 46 | 47 | You can see an example sketch `uptime_post.ino`, which connects SORACOM Arc WireGuard endpoint and post uptime to SORACOM Harvest via WireGuard connection. 48 | 49 | ## License 50 | 51 | The original WireGuard implementation for lwIP is licensed under BSD 3 clause license so the code in this repository also licensed under the same license. 52 | 53 | Original license is below: 54 | 55 | The code is copyrighted under BSD 3 clause Copyright (c) 2021 Daniel Hope (www.floorsense.nz) 56 | 57 | See LICENSE for details 58 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/examples/disconnect/disconnect.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // WiFi configuration --- UPDATE this configuration for your WiFi AP 6 | char ssid[] = "ssid"; 7 | char password[] = "password"; 8 | 9 | // WireGuard configuration --- UPDATE this configuration from JSON 10 | char private_key[] = "(Private Key) "; // [Interface] PrivateKey 11 | IPAddress local_ip(1,2,3,4); // [Interface] Address 12 | char public_key[] = "(Public Key)"; // [Peer] PublicKey 13 | char endpoint_address[] = "link.arc.soracom.io"; // [Peer] Endpoint 14 | int endpoint_port = 11010; // [Peer] Endpoint 15 | 16 | const char host_inside_vpn[] = "10.0.0.1"; 17 | const char host_outside_vpn[] = "192.168.2.1"; 18 | 19 | static constexpr const uint32_t UPDATE_INTERVAL_MS = 5000; 20 | 21 | static WireGuard wg; 22 | 23 | void setup() 24 | { 25 | esp_log_level_set("*", ESP_LOG_DEBUG); 26 | 27 | Serial.begin(115200); 28 | Serial.println("Connecting to the AP..."); 29 | WiFi.begin(ssid, password); 30 | while( !WiFi.isConnected() ) { 31 | delay(1000); 32 | } 33 | 34 | Serial.println("Adjusting system time..."); 35 | configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp", "time.google.com"); 36 | 37 | Serial.println("WiFi Connected."); 38 | } 39 | 40 | void loop() 41 | { 42 | static uint64_t send_count = 0; 43 | static uint64_t loop_count = 0; 44 | if( loop_count % 5 == 0) { 45 | if( !wg.is_initialized() ) { 46 | Serial.println("Initializing WG interface..."); 47 | if( !wg.begin( 48 | local_ip, 49 | private_key, 50 | endpoint_address, 51 | public_key, 52 | endpoint_port) ) { 53 | Serial.println("Failed to initialize WG interface."); 54 | } 55 | } 56 | else { 57 | Serial.println("Shutting down WG interface..."); 58 | wg.end(); 59 | } 60 | } 61 | loop_count++; 62 | 63 | WiFiUDP client; 64 | const char* host = wg.is_initialized() ? host_inside_vpn : host_outside_vpn; 65 | if( !client.beginPacket(host, 23080) ) { 66 | Serial.println("Failed to begin packet..."); 67 | delay(5000); 68 | return; 69 | } 70 | 71 | uint64_t uptime_msec = millis(); 72 | uint8_t buffer[16]; 73 | buffer[ 0] = (uptime_msec >> 0) & 0xff; 74 | buffer[ 1] = (uptime_msec >> 8) & 0xff; 75 | buffer[ 2] = (uptime_msec >> 16) & 0xff; 76 | buffer[ 3] = (uptime_msec >> 24) & 0xff; 77 | buffer[ 4] = (uptime_msec >> 32) & 0xff; 78 | buffer[ 5] = (uptime_msec >> 40) & 0xff; 79 | buffer[ 6] = (uptime_msec >> 48) & 0xff; 80 | buffer[ 7] = (uptime_msec >> 56) & 0xff; 81 | buffer[ 8] = (send_count >> 0) & 0xff; 82 | buffer[ 9] = (send_count >> 8) & 0xff; 83 | buffer[10] = (send_count >> 16) & 0xff; 84 | buffer[11] = (send_count >> 24) & 0xff; 85 | buffer[12] = (send_count >> 32) & 0xff; 86 | buffer[13] = (send_count >> 40) & 0xff; 87 | buffer[14] = (send_count >> 48) & 0xff; 88 | buffer[15] = (send_count >> 56) & 0xff; 89 | 90 | Serial.printf("Sending uptime %lu [ms], count=%d\r\n", uptime_msec, send_count); 91 | client.write(buffer, sizeof(buffer)); 92 | client.endPacket(); 93 | 94 | send_count++; 95 | 96 | IPAddress result; 97 | if( WiFi.hostByName("www.google.com", result) ) { 98 | Serial.printf("hostByName: %s\r\n", result.toString().c_str()); 99 | } 100 | else { 101 | Serial.printf("hostByName failed\r\n"); 102 | } 103 | 104 | delay(UPDATE_INTERVAL_MS); 105 | } 106 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/examples/uptime_post/uptime_post.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // WiFi configuration --- UPDATE this configuration for your WiFi AP 6 | char ssid[] = "ssid"; 7 | char password[] = "password"; 8 | 9 | // WireGuard configuration --- UPDATE this configuration from JSON 10 | char private_key[] = "(Private Key) "; // [Interface] PrivateKey 11 | IPAddress local_ip(1,2,3,4); // [Interface] Address 12 | char public_key[] = "(Public Key)"; // [Peer] PublicKey 13 | char endpoint_address[] = "link.arc.soracom.io"; // [Peer] Endpoint 14 | int endpoint_port = 11010; // [Peer] Endpoint 15 | 16 | static constexpr const uint32_t UPDATE_INTERVAL_MS = 5000; 17 | 18 | static WireGuard wg; 19 | static HTTPClient httpClient; 20 | 21 | void setup() 22 | { 23 | Serial.begin(115200); 24 | Serial.println("Connecting to the AP..."); 25 | WiFi.begin(ssid, password); 26 | while( !WiFi.isConnected() ) { 27 | delay(1000); 28 | } 29 | Serial.println("Adjusting system time..."); 30 | configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp", "time.google.com"); 31 | 32 | Serial.println("Connected. Initializing WireGuard..."); 33 | wg.begin( 34 | local_ip, 35 | private_key, 36 | endpoint_address, 37 | public_key, 38 | endpoint_port); 39 | } 40 | 41 | void loop() 42 | { 43 | WiFiClient client; 44 | 45 | if( !client.connect("uni.soracom.io", 80) ) { 46 | Serial.println("Failed to connect..."); 47 | delay(5000); 48 | return; 49 | } 50 | 51 | uint64_t uptime_msec = millis(); 52 | Serial.printf("Sending uptime %lu [ms]\r\n", uptime_msec); 53 | String json; 54 | json += "{\"uptime_msec\":"; 55 | json.concat(static_cast(uptime_msec)); 56 | json += "}"; 57 | Serial.printf("payload: %s\r\n", json.c_str()); 58 | 59 | client.write("POST / HTTP/1.1\r\n"); 60 | client.write("Host: harvest.soracom.io\r\n"); 61 | client.write("Connection: Keep-Alive\r\n"); 62 | client.write("Keep-Alive: timeout=5, max=2\r\n"); 63 | client.write("Content-Type: application/json\r\n"); 64 | client.write("Content-Length: "); 65 | client.write(String(json.length(), 10).c_str()); 66 | client.write("\r\n\r\n"); 67 | client.write(json.c_str()); 68 | 69 | while(client.connected()) { 70 | auto line = client.readStringUntil('\n'); 71 | Serial.write(line.c_str()); 72 | Serial.write("\n"); 73 | if( line == "\r" ) break; 74 | } 75 | if(client.connected()) { 76 | uint8_t buffer[256]; 77 | size_t bytesToRead = 0; 78 | while((bytesToRead = client.available()) > 0) { 79 | bytesToRead = bytesToRead > sizeof(buffer) ? sizeof(buffer) : bytesToRead; 80 | auto bytesRead = client.readBytes(buffer, bytesToRead); 81 | Serial.write(buffer, bytesRead); 82 | } 83 | } 84 | delay(UPDATE_INTERVAL_MS); 85 | } 86 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/examples/uptime_udp/uptime_udp.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // WiFi configuration --- UPDATE this configuration for your WiFi AP 6 | char ssid[] = "ssid"; 7 | char password[] = "password"; 8 | 9 | // WireGuard configuration --- UPDATE this configuration from JSON 10 | char private_key[] = "(Private Key) "; // [Interface] PrivateKey 11 | IPAddress local_ip(1,2,3,4); // [Interface] Address 12 | char public_key[] = "(Public Key)"; // [Peer] PublicKey 13 | char endpoint_address[] = "link.arc.soracom.io"; // [Peer] Endpoint 14 | int endpoint_port = 11010; // [Peer] Endpoint 15 | 16 | static constexpr const uint32_t UPDATE_INTERVAL_MS = 5000; 17 | 18 | static WireGuard wg; 19 | 20 | void setup() 21 | { 22 | Serial.begin(115200); 23 | Serial.println("Connecting to the AP..."); 24 | WiFi.begin(ssid, password); 25 | while( !WiFi.isConnected() ) { 26 | delay(1000); 27 | } 28 | Serial.println("Adjusting system time..."); 29 | configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp", "time.google.com"); 30 | 31 | Serial.println("Connected. Initializing WireGuard..."); 32 | wg.begin( 33 | local_ip, 34 | private_key, 35 | endpoint_address, 36 | public_key, 37 | endpoint_port); 38 | } 39 | 40 | void loop() 41 | { 42 | static uint64_t send_count = 0; 43 | WiFiUDP client; 44 | if( !client.beginPacket("uni.soracom.io", 23080) ) { 45 | Serial.println("Failed to begin packet..."); 46 | delay(5000); 47 | return; 48 | } 49 | 50 | uint64_t uptime_msec = millis(); 51 | uint8_t buffer[16]; 52 | buffer[ 0] = (uptime_msec >> 0) & 0xff; 53 | buffer[ 1] = (uptime_msec >> 8) & 0xff; 54 | buffer[ 2] = (uptime_msec >> 16) & 0xff; 55 | buffer[ 3] = (uptime_msec >> 24) & 0xff; 56 | buffer[ 4] = (uptime_msec >> 32) & 0xff; 57 | buffer[ 5] = (uptime_msec >> 40) & 0xff; 58 | buffer[ 6] = (uptime_msec >> 48) & 0xff; 59 | buffer[ 7] = (uptime_msec >> 56) & 0xff; 60 | buffer[ 8] = (send_count >> 0) & 0xff; 61 | buffer[ 9] = (send_count >> 8) & 0xff; 62 | buffer[10] = (send_count >> 16) & 0xff; 63 | buffer[11] = (send_count >> 24) & 0xff; 64 | buffer[12] = (send_count >> 32) & 0xff; 65 | buffer[13] = (send_count >> 40) & 0xff; 66 | buffer[14] = (send_count >> 48) & 0xff; 67 | buffer[15] = (send_count >> 56) & 0xff; 68 | 69 | Serial.printf("Sending uptime %lu [ms], count=%d\r\n", uptime_msec, send_count); 70 | client.write(buffer, sizeof(buffer)); 71 | client.endPacket(); 72 | 73 | send_count++; 74 | delay(UPDATE_INTERVAL_MS); 75 | } 76 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/library.properties: -------------------------------------------------------------------------------- 1 | name=WireGuard-ESP32 2 | version=0.1.5 3 | author=Kenta Ida 4 | maintainer=Kenta Ida 5 | sentence=WireGuard implementation for Arduino ESP32 6 | paragraph= 7 | category=Communication 8 | url=https://github.com/ciniml/WireGuard-ESP32-Arduino 9 | includes=WireGuard-ESP32.h 10 | architectures=esp32,Inkplate 11 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/WireGuard-ESP32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * WireGuard implementation for ESP32 Arduino by Kenta Ida (fuga@fugafuga.org) 3 | * SPDX-License-Identifier: BSD-3-Clause 4 | */ 5 | #pragma once 6 | #include 7 | 8 | class WireGuard 9 | { 10 | private: 11 | bool _is_initialized = false; 12 | public: 13 | bool begin(const IPAddress& localIP, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort); 14 | void end(); 15 | bool is_initialized() const { return this->_is_initialized; } 16 | }; 17 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/WireGuard.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * WireGuard implementation for ESP32 Arduino by Kenta Ida (fuga@fugafuga.org) 3 | * SPDX-License-Identifier: BSD-3-Clause 4 | */ 5 | #include "WireGuard-ESP32.h" 6 | 7 | #include "freertos/FreeRTOS.h" 8 | #include "freertos/task.h" 9 | #include "freertos/event_groups.h" 10 | #include "esp_system.h" 11 | 12 | #include "lwip/err.h" 13 | #include "lwip/sys.h" 14 | #include "lwip/ip.h" 15 | #include "lwip/netdb.h" 16 | 17 | #include "esp32-hal-log.h" 18 | 19 | extern "C" { 20 | #include "wireguardif.h" 21 | #include "wireguard-platform.h" 22 | } 23 | 24 | // Wireguard instance 25 | static struct netif wg_netif_struct = {0}; 26 | static struct netif *wg_netif = NULL; 27 | static struct netif *previous_default_netif = NULL; 28 | static uint8_t wireguard_peer_index = WIREGUARDIF_INVALID_INDEX; 29 | 30 | #define TAG "[WireGuard] " 31 | 32 | bool WireGuard::begin(const IPAddress& localIP, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort) { 33 | struct wireguardif_init_data wg; 34 | struct wireguardif_peer peer; 35 | ip_addr_t ipaddr = IPADDR4_INIT(static_cast(localIP)); 36 | ip_addr_t netmask = IPADDR4_INIT_BYTES(255, 255, 255, 255); 37 | ip_addr_t gateway = IPADDR4_INIT_BYTES(0, 0, 0, 0); 38 | 39 | assert(privateKey != NULL); 40 | assert(remotePeerAddress != NULL); 41 | assert(remotePeerPublicKey != NULL); 42 | assert(remotePeerPort != 0); 43 | 44 | // Setup the WireGuard device structure 45 | wg.private_key = privateKey; 46 | wg.listen_port = remotePeerPort; 47 | 48 | wg.bind_netif = NULL; 49 | 50 | // Initialise the first WireGuard peer structure 51 | wireguardif_peer_init(&peer); 52 | // If we know the endpoint's address can add here 53 | bool success_get_endpoint_ip = false; 54 | for(int retry = 0; retry < 5; retry++) { 55 | ip_addr_t endpoint_ip = IPADDR4_INIT_BYTES(0, 0, 0, 0); 56 | struct addrinfo *res = NULL; 57 | struct addrinfo hint; 58 | memset(&hint, 0, sizeof(hint)); 59 | memset(&endpoint_ip, 0, sizeof(endpoint_ip)); 60 | if( lwip_getaddrinfo(remotePeerAddress, NULL, &hint, &res) != 0 ) { 61 | vTaskDelay(pdMS_TO_TICKS(2000)); 62 | continue; 63 | } 64 | success_get_endpoint_ip = true; 65 | struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr; 66 | inet_addr_to_ip4addr(ip_2_ip4(&endpoint_ip), &addr4); 67 | lwip_freeaddrinfo(res); 68 | 69 | peer.endpoint_ip = endpoint_ip; 70 | log_i(TAG "%s is %3d.%3d.%3d.%3d" 71 | , remotePeerAddress 72 | , (endpoint_ip.u_addr.ip4.addr >> 0) & 0xff 73 | , (endpoint_ip.u_addr.ip4.addr >> 8) & 0xff 74 | , (endpoint_ip.u_addr.ip4.addr >> 16) & 0xff 75 | , (endpoint_ip.u_addr.ip4.addr >> 24) & 0xff 76 | ); 77 | break; 78 | } 79 | if( !success_get_endpoint_ip ) { 80 | log_e(TAG "failed to get endpoint ip."); 81 | return false; 82 | } 83 | // Register the new WireGuard network interface with lwIP 84 | wg_netif = netif_add(&wg_netif_struct, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gateway), &wg, &wireguardif_init, &ip_input); 85 | if( wg_netif == nullptr ) { 86 | log_e(TAG "failed to initialize WG netif."); 87 | return false; 88 | } 89 | // Mark the interface as administratively up, link up flag is set automatically when peer connects 90 | netif_set_up(wg_netif); 91 | 92 | peer.public_key = remotePeerPublicKey; 93 | peer.preshared_key = NULL; 94 | // Allow all IPs through tunnel 95 | { 96 | ip_addr_t allowed_ip = IPADDR4_INIT_BYTES(0, 0, 0, 0); 97 | peer.allowed_ip = allowed_ip; 98 | ip_addr_t allowed_mask = IPADDR4_INIT_BYTES(0, 0, 0, 0); 99 | peer.allowed_mask = allowed_mask; 100 | } 101 | 102 | peer.endport_port = remotePeerPort; 103 | 104 | // Initialize the platform 105 | wireguard_platform_init(); 106 | // Register the new WireGuard peer with the netwok interface 107 | wireguardif_add_peer(wg_netif, &peer, &wireguard_peer_index); 108 | if ((wireguard_peer_index != WIREGUARDIF_INVALID_INDEX) && !ip_addr_isany(&peer.endpoint_ip)) { 109 | // Start outbound connection to peer 110 | log_i(TAG "connecting wireguard..."); 111 | wireguardif_connect(wg_netif, wireguard_peer_index); 112 | // Save the current default interface for restoring when shutting down the WG interface. 113 | previous_default_netif = netif_default; 114 | // Set default interface to WG device. 115 | netif_set_default(wg_netif); 116 | } 117 | 118 | this->_is_initialized = true; 119 | return true; 120 | } 121 | 122 | void WireGuard::end() { 123 | if( !this->_is_initialized ) return; 124 | 125 | // Restore the default interface. 126 | netif_set_default(previous_default_netif); 127 | previous_default_netif = nullptr; 128 | // Disconnect the WG interface. 129 | wireguardif_disconnect(wg_netif, wireguard_peer_index); 130 | // Remove peer from the WG interface 131 | wireguardif_remove_peer(wg_netif, wireguard_peer_index); 132 | wireguard_peer_index = WIREGUARDIF_INVALID_INDEX; 133 | // Shutdown the wireguard interface. 134 | wireguardif_shutdown(wg_netif); 135 | // Remove the WG interface; 136 | netif_remove(wg_netif); 137 | wg_netif = nullptr; 138 | 139 | this->_is_initialized = false; 140 | } -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto.c: -------------------------------------------------------------------------------- 1 | #include "crypto.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void crypto_zero(void *dest, size_t len) { 8 | volatile uint8_t *p = (uint8_t *)dest; 9 | while (len--) { 10 | *p++ = 0; 11 | } 12 | } 13 | 14 | bool crypto_equal(const void *a, const void *b, size_t size) { 15 | uint8_t neq = 0; 16 | while (size > 0) { 17 | neq |= *(uint8_t *)a ^ *(uint8_t *)b; 18 | a += 1; 19 | b += 1; 20 | size -= 1; 21 | } 22 | return (neq) ? false : true; 23 | } 24 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto.h: -------------------------------------------------------------------------------- 1 | #ifndef _CRYPTO_H_ 2 | #define _CRYPTO_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // BLAKE2S IMPLEMENTATION 9 | #include "crypto/refc/blake2s.h" 10 | #define wireguard_blake2s_ctx blake2s_ctx 11 | #define wireguard_blake2s_init(ctx,outlen,key,keylen) blake2s_init(ctx,outlen,key,keylen) 12 | #define wireguard_blake2s_update(ctx,in,inlen) blake2s_update(ctx,in,inlen) 13 | #define wireguard_blake2s_final(ctx,out) blake2s_final(ctx,out) 14 | #define wireguard_blake2s(out,outlen,key,keylen,in,inlen) blake2s(out,outlen,key,keylen,in,inlen) 15 | 16 | // X25519 IMPLEMENTATION 17 | #include "crypto/refc/x25519.h" 18 | #define wireguard_x25519(a,b,c) x25519(a,b,c,1) 19 | 20 | // CHACHA20POLY1305 IMPLEMENTATION 21 | #include "crypto/refc/chacha20poly1305.h" 22 | #define wireguard_aead_encrypt(dst,src,srclen,ad,adlen,nonce,key) chacha20poly1305_encrypt(dst,src,srclen,ad,adlen,nonce,key) 23 | #define wireguard_aead_decrypt(dst,src,srclen,ad,adlen,nonce,key) chacha20poly1305_decrypt(dst,src,srclen,ad,adlen,nonce,key) 24 | #define wireguard_xaead_encrypt(dst,src,srclen,ad,adlen,nonce,key) xchacha20poly1305_encrypt(dst,src,srclen,ad,adlen,nonce,key) 25 | #define wireguard_xaead_decrypt(dst,src,srclen,ad,adlen,nonce,key) xchacha20poly1305_decrypt(dst,src,srclen,ad,adlen,nonce,key) 26 | 27 | 28 | // Endian / unaligned helper macros 29 | #define U8C(v) (v##U) 30 | #define U32C(v) (v##U) 31 | 32 | #define U8V(v) ((uint8_t)(v) & U8C(0xFF)) 33 | #define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF)) 34 | 35 | #define U8TO32_LITTLE(p) \ 36 | (((uint32_t)((p)[0]) ) | \ 37 | ((uint32_t)((p)[1]) << 8) | \ 38 | ((uint32_t)((p)[2]) << 16) | \ 39 | ((uint32_t)((p)[3]) << 24)) 40 | 41 | #define U8TO64_LITTLE(p) \ 42 | (((uint64_t)((p)[0]) ) | \ 43 | ((uint64_t)((p)[1]) << 8) | \ 44 | ((uint64_t)((p)[2]) << 16) | \ 45 | ((uint64_t)((p)[3]) << 24) | \ 46 | ((uint64_t)((p)[4]) << 32) | \ 47 | ((uint64_t)((p)[5]) << 40) | \ 48 | ((uint64_t)((p)[6]) << 48) | \ 49 | ((uint64_t)((p)[7]) << 56)) 50 | 51 | #define U16TO8_BIG(p, v) \ 52 | do { \ 53 | (p)[1] = U8V((v) ); \ 54 | (p)[0] = U8V((v) >> 8); \ 55 | } while (0) 56 | 57 | #define U32TO8_LITTLE(p, v) \ 58 | do { \ 59 | (p)[0] = U8V((v) ); \ 60 | (p)[1] = U8V((v) >> 8); \ 61 | (p)[2] = U8V((v) >> 16); \ 62 | (p)[3] = U8V((v) >> 24); \ 63 | } while (0) 64 | 65 | #define U32TO8_BIG(p, v) \ 66 | do { \ 67 | (p)[3] = U8V((v) ); \ 68 | (p)[2] = U8V((v) >> 8); \ 69 | (p)[1] = U8V((v) >> 16); \ 70 | (p)[0] = U8V((v) >> 24); \ 71 | } while (0) 72 | 73 | #define U64TO8_LITTLE(p, v) \ 74 | do { \ 75 | (p)[0] = U8V((v) ); \ 76 | (p)[1] = U8V((v) >> 8); \ 77 | (p)[2] = U8V((v) >> 16); \ 78 | (p)[3] = U8V((v) >> 24); \ 79 | (p)[4] = U8V((v) >> 32); \ 80 | (p)[5] = U8V((v) >> 40); \ 81 | (p)[6] = U8V((v) >> 48); \ 82 | (p)[7] = U8V((v) >> 56); \ 83 | } while (0) 84 | 85 | #define U64TO8_BIG(p, v) \ 86 | do { \ 87 | (p)[7] = U8V((v) ); \ 88 | (p)[6] = U8V((v) >> 8); \ 89 | (p)[5] = U8V((v) >> 16); \ 90 | (p)[4] = U8V((v) >> 24); \ 91 | (p)[3] = U8V((v) >> 32); \ 92 | (p)[2] = U8V((v) >> 40); \ 93 | (p)[1] = U8V((v) >> 48); \ 94 | (p)[0] = U8V((v) >> 56); \ 95 | } while (0) 96 | 97 | 98 | void crypto_zero(void *dest, size_t len); 99 | bool crypto_equal(const void *a, const void *b, size_t size); 100 | 101 | #endif /* _CRYPTO_H_ */ 102 | 103 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/blake2s.c: -------------------------------------------------------------------------------- 1 | // Taken from RFC7693 - https://tools.ietf.org/html/rfc7693 2 | 3 | #include "blake2s.h" 4 | #include "../../crypto.h" 5 | 6 | // Cyclic right rotation. 7 | 8 | #ifndef ROTR32 9 | #define ROTR32(x, y) (((x) >> (y)) ^ ((x) << (32 - (y)))) 10 | #endif 11 | 12 | // Mixing function G. 13 | #define B2S_G(a, b, c, d, x, y) { \ 14 | v[a] = v[a] + v[b] + x; \ 15 | v[d] = ROTR32(v[d] ^ v[a], 16); \ 16 | v[c] = v[c] + v[d]; \ 17 | v[b] = ROTR32(v[b] ^ v[c], 12); \ 18 | v[a] = v[a] + v[b] + y; \ 19 | v[d] = ROTR32(v[d] ^ v[a], 8); \ 20 | v[c] = v[c] + v[d]; \ 21 | v[b] = ROTR32(v[b] ^ v[c], 7); } 22 | 23 | // Initialization Vector. 24 | static const uint32_t blake2s_iv[8] = 25 | { 26 | 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 27 | 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 28 | }; 29 | 30 | // Compression function. "last" flag indicates last block. 31 | static void blake2s_compress(blake2s_ctx *ctx, int last) 32 | { 33 | const uint8_t sigma[10][16] = { 34 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 35 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, 36 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, 37 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, 38 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, 39 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, 40 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, 41 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, 42 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, 43 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 } 44 | }; 45 | int i; 46 | uint32_t v[16], m[16]; 47 | 48 | for (i = 0; i < 8; i++) { // init work variables 49 | v[i] = ctx->h[i]; 50 | v[i + 8] = blake2s_iv[i]; 51 | } 52 | 53 | v[12] ^= ctx->t[0]; // low 32 bits of offset 54 | v[13] ^= ctx->t[1]; // high 32 bits 55 | if (last) // last block flag set ? 56 | v[14] = ~v[14]; 57 | for (i = 0; i < 16; i++) // get little-endian words 58 | m[i] = U8TO32_LITTLE(&ctx->b[4 * i]); 59 | 60 | for (i = 0; i < 10; i++) { // ten rounds 61 | B2S_G( 0, 4, 8, 12, m[sigma[i][ 0]], m[sigma[i][ 1]]); 62 | B2S_G( 1, 5, 9, 13, m[sigma[i][ 2]], m[sigma[i][ 3]]); 63 | B2S_G( 2, 6, 10, 14, m[sigma[i][ 4]], m[sigma[i][ 5]]); 64 | B2S_G( 3, 7, 11, 15, m[sigma[i][ 6]], m[sigma[i][ 7]]); 65 | B2S_G( 0, 5, 10, 15, m[sigma[i][ 8]], m[sigma[i][ 9]]); 66 | B2S_G( 1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]); 67 | B2S_G( 2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]); 68 | B2S_G( 3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]); 69 | } 70 | 71 | for( i = 0; i < 8; ++i ) 72 | ctx->h[i] ^= v[i] ^ v[i + 8]; 73 | } 74 | 75 | // Initialize the hashing context "ctx" with optional key "key". 76 | // 1 <= outlen <= 32 gives the digest size in bytes. 77 | // Secret key (also <= 32 bytes) is optional (keylen = 0). 78 | int blake2s_init(blake2s_ctx *ctx, size_t outlen, 79 | const void *key, size_t keylen) // (keylen=0: no key) 80 | { 81 | size_t i; 82 | 83 | if (outlen == 0 || outlen > 32 || keylen > 32) 84 | return -1; // illegal parameters 85 | 86 | for (i = 0; i < 8; i++) // state, "param block" 87 | ctx->h[i] = blake2s_iv[i]; 88 | ctx->h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen; 89 | 90 | ctx->t[0] = 0; // input count low word 91 | ctx->t[1] = 0; // input count high word 92 | ctx->c = 0; // pointer within buffer 93 | ctx->outlen = outlen; 94 | 95 | for (i = keylen; i < 64; i++) // zero input block 96 | ctx->b[i] = 0; 97 | if (keylen > 0) { 98 | blake2s_update(ctx, key, keylen); 99 | ctx->c = 64; // at the end 100 | } 101 | 102 | return 0; 103 | } 104 | 105 | // Add "inlen" bytes from "in" into the hash. 106 | void blake2s_update(blake2s_ctx *ctx, 107 | const void *in, size_t inlen) // data bytes 108 | { 109 | size_t i; 110 | 111 | for (i = 0; i < inlen; i++) { 112 | if (ctx->c == 64) { // buffer full ? 113 | ctx->t[0] += ctx->c; // add counters 114 | if (ctx->t[0] < ctx->c) // carry overflow ? 115 | ctx->t[1]++; // high word 116 | blake2s_compress(ctx, 0); // compress (not last) 117 | ctx->c = 0; // counter to zero 118 | } 119 | ctx->b[ctx->c++] = ((const uint8_t *) in)[i]; 120 | } 121 | } 122 | 123 | // Generate the message digest (size given in init). 124 | // Result placed in "out". 125 | void blake2s_final(blake2s_ctx *ctx, void *out) 126 | { 127 | size_t i; 128 | 129 | ctx->t[0] += ctx->c; // mark last block offset 130 | if (ctx->t[0] < ctx->c) // carry overflow 131 | ctx->t[1]++; // high word 132 | 133 | while (ctx->c < 64) // fill up with zeros 134 | ctx->b[ctx->c++] = 0; 135 | blake2s_compress(ctx, 1); // final block flag = 1 136 | 137 | // little endian convert and store 138 | for (i = 0; i < ctx->outlen; i++) { 139 | ((uint8_t *) out)[i] = 140 | (ctx->h[i >> 2] >> (8 * (i & 3))) & 0xFF; 141 | } 142 | } 143 | 144 | // Convenience function for all-in-one computation. 145 | int blake2s(void *out, size_t outlen, 146 | const void *key, size_t keylen, 147 | const void *in, size_t inlen) 148 | { 149 | blake2s_ctx ctx; 150 | if (blake2s_init(&ctx, outlen, key, keylen)) 151 | return -1; 152 | blake2s_update(&ctx, in, inlen); 153 | blake2s_final(&ctx, out); 154 | 155 | return 0; 156 | } 157 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/blake2s.h: -------------------------------------------------------------------------------- 1 | // Taken from RFC7693 - https://tools.ietf.org/html/rfc7693 2 | // BLAKE2s Hashing Context and API Prototypes 3 | #ifndef _BLAKE2S_H 4 | #define _BLAKE2S_H 5 | 6 | #define BLAKE2S_BLOCK_SIZE 64 7 | 8 | #include 9 | #include 10 | 11 | // state context 12 | typedef struct { 13 | uint8_t b[64]; // input buffer 14 | uint32_t h[8]; // chained state 15 | uint32_t t[2]; // total number of bytes 16 | size_t c; // pointer for b[] 17 | size_t outlen; // digest size 18 | } blake2s_ctx; 19 | 20 | // Initialize the hashing context "ctx" with optional key "key". 21 | // 1 <= outlen <= 32 gives the digest size in bytes. 22 | // Secret key (also <= 32 bytes) is optional (keylen = 0). 23 | int blake2s_init(blake2s_ctx *ctx, size_t outlen, 24 | const void *key, size_t keylen); // secret key 25 | 26 | // Add "inlen" bytes from "in" into the hash. 27 | void blake2s_update(blake2s_ctx *ctx, // context 28 | const void *in, size_t inlen); // data to be hashed 29 | 30 | // Generate the message digest (size given in init). 31 | // Result placed in "out". 32 | void blake2s_final(blake2s_ctx *ctx, void *out); 33 | 34 | // All-in-one convenience function. 35 | int blake2s(void *out, size_t outlen, // return buffer for digest 36 | const void *key, size_t keylen, // optional secret key 37 | const void *in, size_t inlen); // data to be hashed 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/chacha20.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Daniel Hope (www.floorsense.nz) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this 12 | * list of conditions and the following disclaimer in the documentation and/or 13 | * other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of "Floorsense Ltd", "Agile Workspace Ltd" nor the names of 16 | * its contributors may be used to endorse or promote products derived from this 17 | * software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * Author: Daniel Hope 31 | */ 32 | 33 | // RFC7539 implementation of ChaCha20 with modified nonce size for WireGuard 34 | // https://tools.ietf.org/html/rfc7539 35 | // Adapted from https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/ref/chacha.c by D. J. Bernstein (Public Domain) 36 | // HChaCha20 is described here: https://tools.ietf.org/id/draft-arciszewski-xchacha-02.html 37 | 38 | #include "chacha20.h" 39 | 40 | #include 41 | #include 42 | #include "../../crypto.h" 43 | 44 | // 2.3. The ChaCha20 Block Function 45 | // The first four words (0-3) are constants: 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 46 | static const uint32_t CHACHA20_CONSTANT_1 = 0x61707865; 47 | static const uint32_t CHACHA20_CONSTANT_2 = 0x3320646e; 48 | static const uint32_t CHACHA20_CONSTANT_3 = 0x79622d32; 49 | static const uint32_t CHACHA20_CONSTANT_4 = 0x6b206574; 50 | 51 | #define ROTL32(v, n) (U32V((v) << (n)) | ((v) >> (32 - (n)))) 52 | 53 | #define PLUS(v,w) (U32V((v) + (w))) 54 | #define PLUSONE(v) (PLUS((v),1)) 55 | 56 | // 2.1. The ChaCha Quarter Round 57 | // 1. a += b; d ^= a; d <<<= 16; 58 | // 2. c += d; b ^= c; b <<<= 12; 59 | // 3. a += b; d ^= a; d <<<= 8; 60 | // 4. c += d; b ^= c; b <<<= 7; 61 | 62 | #define QUARTERROUND(a, b, c, d) \ 63 | a += b; d ^= a; d = ROTL32(d, 16); \ 64 | c += d; b ^= c; b = ROTL32(b, 12); \ 65 | a += b; d ^= a; d = ROTL32(d, 8); \ 66 | c += d; b ^= c; b = ROTL32(b, 7) 67 | 68 | static inline void INNER_BLOCK(uint32_t *block) { 69 | QUARTERROUND(block[0], block[4], block[ 8], block[12]); // column 0 70 | QUARTERROUND(block[1], block[5], block[ 9], block[13]); // column 1 71 | QUARTERROUND(block[2], block[6], block[10], block[14]); // column 2 72 | QUARTERROUND(block[3], block[7], block[11], block[15]); // column 3 73 | QUARTERROUND(block[0], block[5], block[10], block[15]); // diagonal 1 74 | QUARTERROUND(block[1], block[6], block[11], block[12]); // diagonal 2 75 | QUARTERROUND(block[2], block[7], block[ 8], block[13]); // diagonal 3 76 | QUARTERROUND(block[3], block[4], block[ 9], block[14]); // diagonal 4 77 | } 78 | 79 | #define TWENTY_ROUNDS(x) ( \ 80 | INNER_BLOCK(x), \ 81 | INNER_BLOCK(x), \ 82 | INNER_BLOCK(x), \ 83 | INNER_BLOCK(x), \ 84 | INNER_BLOCK(x), \ 85 | INNER_BLOCK(x), \ 86 | INNER_BLOCK(x), \ 87 | INNER_BLOCK(x), \ 88 | INNER_BLOCK(x), \ 89 | INNER_BLOCK(x) \ 90 | ) 91 | 92 | // 2.3. The ChaCha20 Block Function 93 | // chacha20_block(key, counter, nonce): 94 | // state = constants | key | counter | nonce 95 | // working_state = state 96 | // for i=1 upto 10 97 | // inner_block(working_state) 98 | // end 99 | // state += working_state 100 | // return serialize(state) 101 | // end 102 | static void chacha20_block(struct chacha20_ctx *ctx, uint8_t *stream) { 103 | uint32_t working_state[16]; 104 | int i; 105 | 106 | for (i = 0; i < 16; ++i) { 107 | working_state[i] = ctx->state[i]; 108 | } 109 | 110 | TWENTY_ROUNDS(working_state); 111 | 112 | for (i = 0; i < 16; ++i) { 113 | U32TO8_LITTLE(stream + (4 * i), PLUS(working_state[i], ctx->state[i])); 114 | } 115 | } 116 | 117 | void chacha20(struct chacha20_ctx *ctx, uint8_t *out, const uint8_t *in, uint32_t len) { 118 | uint8_t output[CHACHA20_BLOCK_SIZE]; 119 | int i; 120 | 121 | if (len) { 122 | for (;;) { 123 | chacha20_block(ctx, output); 124 | // Word 12 is a block counter 125 | ctx->state[12] = PLUSONE(ctx->state[12]); 126 | if (len <= 64) { 127 | for (i = 0;i < len;++i) { 128 | out[i] = in[i] ^ output[i]; 129 | } 130 | return; 131 | } 132 | for (i = 0;i < 64;++i) { 133 | out[i] = in[i] ^ output[i]; 134 | } 135 | len -= 64; 136 | out += 64; 137 | in += 64; 138 | } 139 | } 140 | } 141 | 142 | 143 | // 2.3. The ChaCha20 Block Function 144 | // The first four words (0-3) are constants: 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 145 | // The next eight words (4-11) are taken from the 256-bit key by reading the bytes in little-endian order, in 4-byte chunks. 146 | // Word 12 is a block counter. Since each block is 64-byte, a 32-bit word is enough for 256 gigabytes of data. 147 | // Words 13-15 are a nonce, which should not be repeated for the same key. 148 | // For wireguard: "nonce being composed of 32 bits of zeros followed by the 64-bit little-endian value of counter." where counter comes from the Wireguard layer and is separate from the block counter in word 12 149 | void chacha20_init(struct chacha20_ctx *ctx, const uint8_t *key, const uint64_t nonce) { 150 | ctx->state[0] = CHACHA20_CONSTANT_1; 151 | ctx->state[1] = CHACHA20_CONSTANT_2; 152 | ctx->state[2] = CHACHA20_CONSTANT_3; 153 | ctx->state[3] = CHACHA20_CONSTANT_4; 154 | ctx->state[4] = U8TO32_LITTLE(key + 0); 155 | ctx->state[5] = U8TO32_LITTLE(key + 4); 156 | ctx->state[6] = U8TO32_LITTLE(key + 8); 157 | ctx->state[7] = U8TO32_LITTLE(key + 12); 158 | ctx->state[8] = U8TO32_LITTLE(key + 16); 159 | ctx->state[9] = U8TO32_LITTLE(key + 20); 160 | ctx->state[10] = U8TO32_LITTLE(key + 24); 161 | ctx->state[11] = U8TO32_LITTLE(key + 28); 162 | ctx->state[12] = 0; 163 | ctx->state[13] = 0; 164 | ctx->state[14] = nonce & 0xFFFFFFFF; 165 | ctx->state[15] = nonce >> 32; 166 | } 167 | 168 | // 2.2. HChaCha20 169 | // HChaCha20 is initialized the same way as the ChaCha cipher, except that HChaCha20 uses a 128-bit nonce and has no counter. 170 | // After initialization, proceed through the ChaCha rounds as usual. 171 | // Once the 20 ChaCha rounds have been completed, the first 128 bits and last 128 bits of the ChaCha state (both little-endian) are concatenated, and this 256-bit subkey is returned. 172 | void hchacha20(uint8_t *out, const uint8_t *nonce, const uint8_t *key) { 173 | uint32_t state[16]; 174 | state[0] = CHACHA20_CONSTANT_1; 175 | state[1] = CHACHA20_CONSTANT_2; 176 | state[2] = CHACHA20_CONSTANT_3; 177 | state[3] = CHACHA20_CONSTANT_4; 178 | state[4] = U8TO32_LITTLE(key + 0); 179 | state[5] = U8TO32_LITTLE(key + 4); 180 | state[6] = U8TO32_LITTLE(key + 8); 181 | state[7] = U8TO32_LITTLE(key + 12); 182 | state[8] = U8TO32_LITTLE(key + 16); 183 | state[9] = U8TO32_LITTLE(key + 20); 184 | state[10] = U8TO32_LITTLE(key + 24); 185 | state[11] = U8TO32_LITTLE(key + 28); 186 | state[12] = U8TO32_LITTLE(nonce + 0); 187 | state[13] = U8TO32_LITTLE(nonce + 4); 188 | state[14] = U8TO32_LITTLE(nonce + 8); 189 | state[15] = U8TO32_LITTLE(nonce + 12); 190 | 191 | TWENTY_ROUNDS(state); 192 | 193 | // Concatenate first/last 128 bits into 256bit output (as little endian) 194 | U32TO8_LITTLE(out + 0, state[0]); 195 | U32TO8_LITTLE(out + 4, state[1]); 196 | U32TO8_LITTLE(out + 8, state[2]); 197 | U32TO8_LITTLE(out + 12, state[3]); 198 | U32TO8_LITTLE(out + 16, state[12]); 199 | U32TO8_LITTLE(out + 20, state[13]); 200 | U32TO8_LITTLE(out + 24, state[14]); 201 | U32TO8_LITTLE(out + 28, state[15]); 202 | } 203 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/chacha20.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Daniel Hope (www.floorsense.nz) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this 12 | * list of conditions and the following disclaimer in the documentation and/or 13 | * other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of "Floorsense Ltd", "Agile Workspace Ltd" nor the names of 16 | * its contributors may be used to endorse or promote products derived from this 17 | * software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * Author: Daniel Hope 31 | */ 32 | 33 | // RFC7539 implementation of ChaCha20 with modified nonce size for WireGuard 34 | // https://tools.ietf.org/html/rfc7539 35 | // Adapted from https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/ref/chacha.c by D. J. Bernstein (Public Domain) 36 | // HChaCha20 is described here: https://tools.ietf.org/id/draft-arciszewski-xchacha-02.html 37 | #ifndef _CHACHA20_H_ 38 | #define _CHACHA20_H_ 39 | 40 | #include 41 | 42 | #define CHACHA20_BLOCK_SIZE (64) 43 | #define CHACHA20_KEY_SIZE (32) 44 | 45 | struct chacha20_ctx { 46 | uint32_t state[16]; 47 | }; 48 | 49 | void chacha20_init(struct chacha20_ctx *ctx, const uint8_t *key, const uint64_t nonce); 50 | void chacha20(struct chacha20_ctx *ctx, uint8_t *out, const uint8_t *in, uint32_t len); 51 | void hchacha20(uint8_t *out, const uint8_t *nonce, const uint8_t *key); 52 | 53 | #endif /* _CHACHA20_H_ */ 54 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/chacha20poly1305.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Daniel Hope (www.floorsense.nz) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this 12 | * list of conditions and the following disclaimer in the documentation and/or 13 | * other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of "Floorsense Ltd", "Agile Workspace Ltd" nor the names of 16 | * its contributors may be used to endorse or promote products derived from this 17 | * software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * Author: Daniel Hope 31 | */ 32 | 33 | // AEAD_CHACHA20_POLY1305 as described in https://tools.ietf.org/html/rfc7539 34 | // AEAD_XChaCha20_Poly1305 as described in https://tools.ietf.org/id/draft-arciszewski-xchacha-02.html 35 | #include "chacha20poly1305.h" 36 | #include "chacha20.h" 37 | #include "poly1305-donna.h" 38 | 39 | #include 40 | #include 41 | #include "../../crypto.h" 42 | 43 | #define POLY1305_KEY_SIZE 32 44 | #define POLY1305_MAC_SIZE 16 45 | 46 | static const uint8_t zero[CHACHA20_BLOCK_SIZE] = { 0 }; 47 | 48 | // 2.6. Generating the Poly1305 Key Using ChaCha20 49 | static void generate_poly1305_key(struct poly1305_context *poly1305_state, struct chacha20_ctx *chacha20_state, const uint8_t *key, uint64_t nonce) { 50 | uint8_t block[POLY1305_KEY_SIZE] = {0}; 51 | 52 | // The method is to call the block function with the following parameters: 53 | // - The 256-bit session integrity key is used as the ChaCha20 key. 54 | // - The block counter is set to zero. 55 | // - The protocol will specify a 96-bit or 64-bit nonce 56 | chacha20_init(chacha20_state, key, nonce); 57 | 58 | // We take the first 256 bits or the serialized state, and use those as the one-time Poly1305 key 59 | chacha20(chacha20_state, block, block, sizeof(block)); 60 | 61 | poly1305_init(poly1305_state, block); 62 | 63 | crypto_zero(&block, sizeof(block)); 64 | } 65 | 66 | // 2.8. AEAD Construction (Encryption) 67 | void chacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, uint64_t nonce, const uint8_t *key) { 68 | struct poly1305_context poly1305_state; 69 | struct chacha20_ctx chacha20_state; 70 | uint8_t block[8]; 71 | size_t padded_len; 72 | 73 | // First, a Poly1305 one-time key is generated from the 256-bit key and nonce using the procedure described in Section 2.6. 74 | generate_poly1305_key(&poly1305_state, &chacha20_state, key, nonce); 75 | 76 | // Next, the ChaCha20 encryption function is called to encrypt the plaintext, using the same key and nonce, and with the initial counter set to 1. 77 | chacha20(&chacha20_state, dst, src, src_len); 78 | 79 | // Finally, the Poly1305 function is called with the Poly1305 key calculated above, and a message constructed as a concatenation of the following: 80 | // - The AAD 81 | poly1305_update(&poly1305_state, ad, ad_len); 82 | // - padding1 -- the padding is up to 15 zero bytes, and it brings the total length so far to an integral multiple of 16 83 | padded_len = (ad_len + 15) & 0xFFFFFFF0; // Round up to next 16 bytes 84 | poly1305_update(&poly1305_state, zero, padded_len - ad_len); 85 | // - The ciphertext 86 | poly1305_update(&poly1305_state, dst, src_len); 87 | // - padding2 -- the padding is up to 15 zero bytes, and it brings the total length so far to an integral multiple of 16. 88 | padded_len = (src_len + 15) & 0xFFFFFFF0; // Round up to next 16 bytes 89 | poly1305_update(&poly1305_state, zero, padded_len - src_len); 90 | // - The length of the additional data in octets (as a 64-bit little-endian integer) 91 | U64TO8_LITTLE(block, (uint64_t)ad_len); 92 | poly1305_update(&poly1305_state, block, sizeof(block)); 93 | // - The length of the ciphertext in octets (as a 64-bit little-endian integer). 94 | U64TO8_LITTLE(block, (uint64_t)src_len); 95 | poly1305_update(&poly1305_state, block, sizeof(block)); 96 | 97 | // The output from the AEAD is twofold: 98 | // - A ciphertext of the same length as the plaintext. (above, output of chacha20 into dst) 99 | // - A 128-bit tag, which is the output of the Poly1305 function. (append to dst) 100 | poly1305_finish(&poly1305_state, dst + src_len); 101 | 102 | // Make sure we leave nothing sensitive on the stack 103 | crypto_zero(&chacha20_state, sizeof(chacha20_state)); 104 | crypto_zero(&block, sizeof(block)); 105 | } 106 | 107 | // 2.8. AEAD Construction (Decryption) 108 | bool chacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, uint64_t nonce, const uint8_t *key) { 109 | struct poly1305_context poly1305_state; 110 | struct chacha20_ctx chacha20_state; 111 | uint8_t block[8]; 112 | uint8_t mac[POLY1305_MAC_SIZE]; 113 | size_t padded_len; 114 | int dst_len; 115 | bool result = false; 116 | 117 | // Decryption is similar [to encryption] with the following differences: 118 | // - The roles of ciphertext and plaintext are reversed, so the ChaCha20 encryption function is applied to the ciphertext, producing the plaintext. 119 | // - The Poly1305 function is still run on the AAD and the ciphertext, not the plaintext. 120 | // - The calculated tag is bitwise compared to the received tag. The message is authenticated if and only if the tags match. 121 | 122 | if (src_len >= POLY1305_MAC_SIZE) { 123 | dst_len = src_len - POLY1305_MAC_SIZE; 124 | 125 | // First, a Poly1305 one-time key is generated from the 256-bit key and nonce using the procedure described in Section 2.6. 126 | generate_poly1305_key(&poly1305_state, &chacha20_state, key, nonce); 127 | 128 | // Calculate the MAC before attempting decryption 129 | 130 | // the Poly1305 function is called with the Poly1305 key calculated above, and a message constructed as a concatenation of the following: 131 | // - The AAD 132 | poly1305_update(&poly1305_state, ad, ad_len); 133 | // - padding1 -- the padding is up to 15 zero bytes, and it brings the total length so far to an integral multiple of 16 134 | padded_len = (ad_len + 15) & 0xFFFFFFF0; // Round up to next 16 bytes 135 | poly1305_update(&poly1305_state, zero, padded_len - ad_len); 136 | // - The ciphertext (note the Poly1305 function is still run on the AAD and the ciphertext, not the plaintext) 137 | poly1305_update(&poly1305_state, src, dst_len); 138 | // - padding2 -- the padding is up to 15 zero bytes, and it brings the total length so far to an integral multiple of 16. 139 | padded_len = (dst_len + 15) & 0xFFFFFFF0; // Round up to next 16 bytes 140 | poly1305_update(&poly1305_state, zero, padded_len - dst_len); 141 | // - The length of the additional data in octets (as a 64-bit little-endian integer) 142 | U64TO8_LITTLE(block, (uint64_t)ad_len); 143 | poly1305_update(&poly1305_state, block, sizeof(block)); 144 | // - The length of the ciphertext in octets (as a 64-bit little-endian integer). 145 | U64TO8_LITTLE(block, (uint64_t)dst_len); 146 | poly1305_update(&poly1305_state, block, sizeof(block)); 147 | 148 | // The output from the AEAD is twofold: 149 | // - A plaintext of the same length as the ciphertext. (below, output of chacha20 into dst) 150 | // - A 128-bit tag, which is the output of the Poly1305 function. (into mac for checking against passed mac) 151 | poly1305_finish(&poly1305_state, mac); 152 | 153 | 154 | if (crypto_equal(mac, src + dst_len, POLY1305_MAC_SIZE)) { 155 | // mac is correct - do the decryption 156 | // Next, the ChaCha20 encryption function is called to decrypt the ciphertext, using the same key and nonce, and with the initial counter set to 1. 157 | chacha20(&chacha20_state, dst, src, dst_len); 158 | result = true; 159 | } 160 | } 161 | return result; 162 | } 163 | 164 | // AEAD_XChaCha20_Poly1305 165 | // XChaCha20-Poly1305 is a variant of the ChaCha20-Poly1305 AEAD construction as defined in [RFC7539] that uses a 192-bit nonce instead of a 96-bit nonce. 166 | // The algorithm for XChaCha20-Poly1305 is as follows: 167 | // 1. Calculate a subkey from the first 16 bytes of the nonce and the key, using HChaCha20 (Section 2.2). 168 | // 2. Use the subkey and remaining 8 bytes of the nonce (prefixed with 4 NUL bytes) with AEAD_CHACHA20_POLY1305 from [RFC7539] as normal. The definition for XChaCha20 is given in Section 2.3. 169 | void xchacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, const uint8_t *nonce, const uint8_t *key) { 170 | uint8_t subkey[CHACHA20_KEY_SIZE]; 171 | uint64_t new_nonce; 172 | 173 | new_nonce = U8TO64_LITTLE(nonce + 16); 174 | 175 | hchacha20(subkey, nonce, key); 176 | chacha20poly1305_encrypt(dst, src, src_len, ad, ad_len, new_nonce, subkey); 177 | 178 | crypto_zero(subkey, sizeof(subkey)); 179 | } 180 | 181 | bool xchacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, const uint8_t *nonce, const uint8_t *key) { 182 | uint8_t subkey[CHACHA20_KEY_SIZE]; 183 | uint64_t new_nonce; 184 | bool result; 185 | 186 | new_nonce = U8TO64_LITTLE(nonce + 16); 187 | 188 | hchacha20(subkey, nonce, key); 189 | result = chacha20poly1305_decrypt(dst, src, src_len, ad, ad_len, new_nonce, subkey); 190 | 191 | crypto_zero(subkey, sizeof(subkey)); 192 | return result; 193 | } 194 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/chacha20poly1305.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Daniel Hope (www.floorsense.nz) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this 12 | * list of conditions and the following disclaimer in the documentation and/or 13 | * other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of "Floorsense Ltd", "Agile Workspace Ltd" nor the names of 16 | * its contributors may be used to endorse or promote products derived from this 17 | * software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * Author: Daniel Hope 31 | */ 32 | 33 | #ifndef _CHACHA20POLY1305_H_ 34 | #define _CHACHA20POLY1305_H_ 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | // Aead(key, counter, plain text, auth text) ChaCha20Poly1305 AEAD, as specified in RFC7539 [17], with its nonce being composed of 32 bits of zeros followed by the 64-bit little-endian value of counter. 41 | // AEAD_CHACHA20_POLY1305 as described in https://tools.ietf.org/html/rfc7539 42 | void chacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, uint64_t nonce, const uint8_t *key); 43 | bool chacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, uint64_t nonce, const uint8_t *key); 44 | 45 | // Xaead(key, nonce, plain text, auth text) XChaCha20Poly1305 AEAD, with a 24-byte random nonce, instantiated using HChaCha20 [6] and ChaCha20Poly1305. 46 | // AEAD_XChaCha20_Poly1305 as described in https://tools.ietf.org/id/draft-arciszewski-xchacha-02.html 47 | void xchacha20poly1305_encrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, const uint8_t *nonce, const uint8_t *key); 48 | bool xchacha20poly1305_decrypt(uint8_t *dst, const uint8_t *src, size_t src_len, const uint8_t *ad, size_t ad_len, const uint8_t *nonce, const uint8_t *key); 49 | 50 | #endif /* _CHACHA20POLY1305_H_ */ 51 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna-32.h: -------------------------------------------------------------------------------- 1 | // Taken from https://github.com/floodyberry/poly1305-donna - public domain or MIT 2 | /* 3 | poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition 4 | */ 5 | 6 | #if defined(_MSC_VER) 7 | #define POLY1305_NOINLINE __declspec(noinline) 8 | #elif defined(__GNUC__) 9 | #define POLY1305_NOINLINE __attribute__((noinline)) 10 | #else 11 | #define POLY1305_NOINLINE 12 | #endif 13 | 14 | #define poly1305_block_size 16 15 | 16 | /* 17 + sizeof(size_t) + 14*sizeof(unsigned long) */ 17 | typedef struct poly1305_state_internal_t { 18 | unsigned long r[5]; 19 | unsigned long h[5]; 20 | unsigned long pad[4]; 21 | size_t leftover; 22 | unsigned char buffer[poly1305_block_size]; 23 | unsigned char final; 24 | } poly1305_state_internal_t; 25 | 26 | /* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */ 27 | static unsigned long 28 | U8TO32(const unsigned char *p) { 29 | return 30 | (((unsigned long)(p[0] & 0xff) ) | 31 | ((unsigned long)(p[1] & 0xff) << 8) | 32 | ((unsigned long)(p[2] & 0xff) << 16) | 33 | ((unsigned long)(p[3] & 0xff) << 24)); 34 | } 35 | 36 | /* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */ 37 | static void 38 | U32TO8(unsigned char *p, unsigned long v) { 39 | p[0] = (v ) & 0xff; 40 | p[1] = (v >> 8) & 0xff; 41 | p[2] = (v >> 16) & 0xff; 42 | p[3] = (v >> 24) & 0xff; 43 | } 44 | 45 | void 46 | poly1305_init(poly1305_context *ctx, const unsigned char key[32]) { 47 | poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 48 | 49 | /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ 50 | st->r[0] = (U8TO32(&key[ 0]) ) & 0x3ffffff; 51 | st->r[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03; 52 | st->r[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff; 53 | st->r[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff; 54 | st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff; 55 | 56 | /* h = 0 */ 57 | st->h[0] = 0; 58 | st->h[1] = 0; 59 | st->h[2] = 0; 60 | st->h[3] = 0; 61 | st->h[4] = 0; 62 | 63 | /* save pad for later */ 64 | st->pad[0] = U8TO32(&key[16]); 65 | st->pad[1] = U8TO32(&key[20]); 66 | st->pad[2] = U8TO32(&key[24]); 67 | st->pad[3] = U8TO32(&key[28]); 68 | 69 | st->leftover = 0; 70 | st->final = 0; 71 | } 72 | 73 | static void 74 | poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) { 75 | const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */ 76 | unsigned long r0,r1,r2,r3,r4; 77 | unsigned long s1,s2,s3,s4; 78 | unsigned long h0,h1,h2,h3,h4; 79 | unsigned long long d0,d1,d2,d3,d4; 80 | unsigned long c; 81 | 82 | r0 = st->r[0]; 83 | r1 = st->r[1]; 84 | r2 = st->r[2]; 85 | r3 = st->r[3]; 86 | r4 = st->r[4]; 87 | 88 | s1 = r1 * 5; 89 | s2 = r2 * 5; 90 | s3 = r3 * 5; 91 | s4 = r4 * 5; 92 | 93 | h0 = st->h[0]; 94 | h1 = st->h[1]; 95 | h2 = st->h[2]; 96 | h3 = st->h[3]; 97 | h4 = st->h[4]; 98 | 99 | while (bytes >= poly1305_block_size) { 100 | /* h += m[i] */ 101 | h0 += (U8TO32(m+ 0) ) & 0x3ffffff; 102 | h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff; 103 | h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff; 104 | h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff; 105 | h4 += (U8TO32(m+12) >> 8) | hibit; 106 | 107 | /* h *= r */ 108 | d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1); 109 | d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2); 110 | d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3); 111 | d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4); 112 | d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0); 113 | 114 | /* (partial) h %= p */ 115 | c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff; 116 | d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff; 117 | d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff; 118 | d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff; 119 | d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff; 120 | h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; 121 | h1 += c; 122 | 123 | m += poly1305_block_size; 124 | bytes -= poly1305_block_size; 125 | } 126 | 127 | st->h[0] = h0; 128 | st->h[1] = h1; 129 | st->h[2] = h2; 130 | st->h[3] = h3; 131 | st->h[4] = h4; 132 | } 133 | 134 | POLY1305_NOINLINE void 135 | poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) { 136 | poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 137 | unsigned long h0,h1,h2,h3,h4,c; 138 | unsigned long g0,g1,g2,g3,g4; 139 | unsigned long long f; 140 | unsigned long mask; 141 | 142 | /* process the remaining block */ 143 | if (st->leftover) { 144 | size_t i = st->leftover; 145 | st->buffer[i++] = 1; 146 | for (; i < poly1305_block_size; i++) 147 | st->buffer[i] = 0; 148 | st->final = 1; 149 | poly1305_blocks(st, st->buffer, poly1305_block_size); 150 | } 151 | 152 | /* fully carry h */ 153 | h0 = st->h[0]; 154 | h1 = st->h[1]; 155 | h2 = st->h[2]; 156 | h3 = st->h[3]; 157 | h4 = st->h[4]; 158 | 159 | c = h1 >> 26; h1 = h1 & 0x3ffffff; 160 | h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; 161 | h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; 162 | h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; 163 | h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; 164 | h1 += c; 165 | 166 | /* compute h + -p */ 167 | g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; 168 | g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; 169 | g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; 170 | g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; 171 | g4 = h4 + c - (1UL << 26); 172 | 173 | /* select h if h < p, or h + -p if h >= p */ 174 | mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1; 175 | g0 &= mask; 176 | g1 &= mask; 177 | g2 &= mask; 178 | g3 &= mask; 179 | g4 &= mask; 180 | mask = ~mask; 181 | h0 = (h0 & mask) | g0; 182 | h1 = (h1 & mask) | g1; 183 | h2 = (h2 & mask) | g2; 184 | h3 = (h3 & mask) | g3; 185 | h4 = (h4 & mask) | g4; 186 | 187 | /* h = h % (2^128) */ 188 | h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; 189 | h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; 190 | h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; 191 | h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; 192 | 193 | /* mac = (h + pad) % (2^128) */ 194 | f = (unsigned long long)h0 + st->pad[0] ; h0 = (unsigned long)f; 195 | f = (unsigned long long)h1 + st->pad[1] + (f >> 32); h1 = (unsigned long)f; 196 | f = (unsigned long long)h2 + st->pad[2] + (f >> 32); h2 = (unsigned long)f; 197 | f = (unsigned long long)h3 + st->pad[3] + (f >> 32); h3 = (unsigned long)f; 198 | 199 | U32TO8(mac + 0, h0); 200 | U32TO8(mac + 4, h1); 201 | U32TO8(mac + 8, h2); 202 | U32TO8(mac + 12, h3); 203 | 204 | /* zero out the state */ 205 | st->h[0] = 0; 206 | st->h[1] = 0; 207 | st->h[2] = 0; 208 | st->h[3] = 0; 209 | st->h[4] = 0; 210 | st->r[0] = 0; 211 | st->r[1] = 0; 212 | st->r[2] = 0; 213 | st->r[3] = 0; 214 | st->r[4] = 0; 215 | st->pad[0] = 0; 216 | st->pad[1] = 0; 217 | st->pad[2] = 0; 218 | st->pad[3] = 0; 219 | } 220 | 221 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna.c: -------------------------------------------------------------------------------- 1 | // Taken from https://github.com/floodyberry/poly1305-donna - public domain or MIT 2 | 3 | #include "poly1305-donna.h" 4 | #include "poly1305-donna-32.h" 5 | 6 | void 7 | poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) { 8 | poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 9 | size_t i; 10 | 11 | /* handle leftover */ 12 | if (st->leftover) { 13 | size_t want = (poly1305_block_size - st->leftover); 14 | if (want > bytes) 15 | want = bytes; 16 | for (i = 0; i < want; i++) 17 | st->buffer[st->leftover + i] = m[i]; 18 | bytes -= want; 19 | m += want; 20 | st->leftover += want; 21 | if (st->leftover < poly1305_block_size) 22 | return; 23 | poly1305_blocks(st, st->buffer, poly1305_block_size); 24 | st->leftover = 0; 25 | } 26 | 27 | /* process full blocks */ 28 | if (bytes >= poly1305_block_size) { 29 | size_t want = (bytes & ~(poly1305_block_size - 1)); 30 | poly1305_blocks(st, m, want); 31 | m += want; 32 | bytes -= want; 33 | } 34 | 35 | /* store leftover */ 36 | if (bytes) { 37 | for (i = 0; i < bytes; i++) 38 | st->buffer[st->leftover + i] = m[i]; 39 | st->leftover += bytes; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/poly1305-donna.h: -------------------------------------------------------------------------------- 1 | // Taken from https://github.com/floodyberry/poly1305-donna - public domain or MIT 2 | #ifndef POLY1305_DONNA_H 3 | #define POLY1305_DONNA_H 4 | 5 | #include 6 | 7 | typedef struct poly1305_context { 8 | size_t aligner; 9 | unsigned char opaque[136]; 10 | } poly1305_context; 11 | 12 | void poly1305_init(poly1305_context *ctx, const unsigned char key[32]); 13 | void poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes); 14 | void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]); 15 | 16 | #endif /* POLY1305_DONNA_H */ 17 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/x25519-license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 Cryptography Research, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/crypto/refc/x25519.h: -------------------------------------------------------------------------------- 1 | // Taken from https://sourceforge.net/p/strobe (MIT Licence) 2 | /** 3 | * @file x25519.h 4 | * @copyright 5 | * Copyright (c) 2016 Cryptography Research, Inc. \n 6 | * Released under the MIT License. See LICENSE.txt for license information. 7 | * @author Mike Hamburg 8 | * @brief X25519 key exchange and signatures. 9 | */ 10 | 11 | #ifndef __X25519_H__ 12 | #define __X25519_H__ 13 | 14 | #define X25519_BYTES (256/8) 15 | 16 | /* The base point (9) */ 17 | extern const unsigned char X25519_BASE_POINT[X25519_BYTES]; 18 | 19 | /** Number of bytes in an EC public key */ 20 | #define EC_PUBLIC_BYTES 32 21 | 22 | /** Number of bytes in an EC private key */ 23 | #define EC_PRIVATE_BYTES 32 24 | 25 | /** 26 | * Number of bytes in a Schnorr challenge. 27 | * Could be set to 16 in a pinch. (FUTURE?) 28 | */ 29 | #define EC_CHALLENGE_BYTES 32 30 | 31 | /** Enough bytes to get a uniform sample mod #E. For eg a Brainpool 32 | * curve this would need to be more than for a private key, but due 33 | * to the special prime used by Curve25519, the same size is enough. 34 | */ 35 | #define EC_UNIFORM_BYTES 32 36 | 37 | /* x25519 scalar multiplication. Sets out to scalar*base. 38 | * 39 | * If clamp is set (and supported by X25519_INTEROP_SUPPORT_CLAMP) 40 | * then the scalar will be "clamped" like a Curve25519 secret key. 41 | * This adds almost no security, but permits interop with other x25519 42 | * implementations without manually clamping the keys. 43 | * 44 | * Per RFC 7748, this function returns failure (-1) if the output 45 | * is zero and clamp is set. This indicates "non-contributory behavior", 46 | * meaning that one party might steer the key so that the other party's 47 | * contribution doesn't matter, or contributes only a little entropy. 48 | * 49 | * WARNING: however, this function differs from RFC 7748 in another way: 50 | * it pays attention to the high bit base[EC_PUBLIC_BYTES-1] & 0x80, but 51 | * RFC 7748 says to ignore this bit. For compatibility with RFC 7748, 52 | * you must also clear this bit by running base[EC_PUBLIC_BYTES-1] &= 0x7F. 53 | * This library won't clear it for you because it takes the base point as 54 | * const, and (depending on build flags) dosen't copy it. 55 | * 56 | * If clamp==0, or if X25519_INTEROP_SUPPORT_CLAMP==0, then this function 57 | * always returns 0. 58 | */ 59 | int x25519 ( 60 | unsigned char out[EC_PUBLIC_BYTES], 61 | const unsigned char scalar[EC_PRIVATE_BYTES], 62 | const unsigned char base[EC_PUBLIC_BYTES], 63 | int clamp 64 | ); 65 | 66 | /** 67 | * Returns 0 on success, -1 on failure. 68 | * 69 | * Per RFC 7748, this function returns failure if the output 70 | * is zero and clamp is set. This usually doesn't matter for 71 | * base scalarmuls. 72 | * 73 | * If clamp==0, or if X25519_INTEROP_SUPPORT_CLAMP==0, then this function 74 | * always returns 0. 75 | * 76 | * Same as x255(out,scalar,X255_BASE_POINT), except that 77 | * other implementations may optimize it. 78 | */ 79 | static inline int x25519_base ( 80 | unsigned char out[EC_PUBLIC_BYTES], 81 | const unsigned char scalar[EC_PRIVATE_BYTES], 82 | int clamp 83 | ) { 84 | return x25519(out,scalar,X25519_BASE_POINT,clamp); 85 | } 86 | 87 | /** 88 | * As x25519_base, but with a scalar that's EC_UNIFORM_BYTES long, 89 | * and clamp always 0 (and thus, no return value). 90 | * 91 | * This is used for signing. Implementors must replace it for 92 | * curves that require more bytes for uniformity (Brainpool). 93 | */ 94 | static inline void x25519_base_uniform ( 95 | unsigned char out[EC_PUBLIC_BYTES], 96 | const unsigned char scalar[EC_UNIFORM_BYTES] 97 | ) { 98 | (void)x25519_base(out,scalar,0); 99 | } 100 | 101 | /** 102 | * STROBE-compatible Schnorr signatures using curve25519 (not ed25519) 103 | * 104 | * The user will call x25519_base_uniform(eph,eph_secret) to schedule 105 | * a random ephemeral secret key. They then call a Schnorr oracle to 106 | * get a challenge, and compute the response using this function. 107 | */ 108 | void x25519_sign_p2 ( 109 | unsigned char response[EC_PRIVATE_BYTES], 110 | const unsigned char challenge[EC_CHALLENGE_BYTES], 111 | const unsigned char eph_secret[EC_UNIFORM_BYTES], 112 | const unsigned char secret[EC_PRIVATE_BYTES] 113 | ); 114 | 115 | /** 116 | * STROBE-compatible signature verification using curve25519 (not ed25519). 117 | * This function is the public equivalent x25519_sign_p2, taking the long-term 118 | * and ephemeral public keys instead of secret ones. 119 | * 120 | * Returns -1 on failure and 0 on success. 121 | */ 122 | int x25519_verify_p2 ( 123 | const unsigned char response[X25519_BYTES], 124 | const unsigned char challenge[X25519_BYTES], 125 | const unsigned char eph[X25519_BYTES], 126 | const unsigned char pub[X25519_BYTES] 127 | ); 128 | 129 | #endif /* __X25519_H__ */ 130 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/wireguard-platform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * WireGuard implementation for ESP32 Arduino by Kenta Ida (fuga@fugafuga.org) 3 | * SPDX-License-Identifier: BSD-3-Clause 4 | */ 5 | 6 | #include "wireguard-platform.h" 7 | 8 | #include 9 | #include "crypto.h" 10 | #include "lwip/sys.h" 11 | #include "mbedtls/entropy.h" 12 | #include "mbedtls/ctr_drbg.h" 13 | #include "esp_system.h" 14 | 15 | static struct mbedtls_ctr_drbg_context random_context; 16 | static struct mbedtls_entropy_context entropy_context; 17 | static bool is_platform_initialized = false; 18 | 19 | static int entropy_hw_random_source( void *data, unsigned char *output, size_t len, size_t *olen ) { 20 | esp_fill_random(output, len); 21 | *olen = len; 22 | return 0; 23 | } 24 | 25 | void wireguard_platform_init() { 26 | if( is_platform_initialized ) return; 27 | 28 | mbedtls_entropy_init(&entropy_context); 29 | mbedtls_ctr_drbg_init(&random_context); 30 | mbedtls_entropy_add_source(&entropy_context, entropy_hw_random_source, NULL, 134, MBEDTLS_ENTROPY_SOURCE_STRONG); 31 | mbedtls_ctr_drbg_seed(&random_context, mbedtls_entropy_func, &entropy_context, NULL, 0); 32 | 33 | is_platform_initialized = true; 34 | } 35 | 36 | void wireguard_random_bytes(void *bytes, size_t size) { 37 | uint8_t *out = (uint8_t *)bytes; 38 | mbedtls_ctr_drbg_random(&random_context, bytes, size); 39 | } 40 | 41 | uint32_t wireguard_sys_now() { 42 | // Default to the LwIP system time 43 | return sys_now(); 44 | } 45 | 46 | void wireguard_tai64n_now(uint8_t *output) { 47 | // See https://cr.yp.to/libtai/tai64.html 48 | // 64 bit seconds from 1970 = 8 bytes 49 | // 32 bit nano seconds from current second 50 | 51 | // Get timestamp. Note that the timestamp must be synced by NTP, 52 | // or at least preserved in NVS, not to go back after reset. 53 | // Otherwise, the WireGuard remote peer rejects handshake. 54 | struct timeval tv; 55 | gettimeofday(&tv, NULL); 56 | uint64_t millis = (tv.tv_sec * 1000LL + (tv.tv_usec / 1000LL)); 57 | 58 | // Split into seconds offset + nanos 59 | uint64_t seconds = 0x400000000000000aULL + (millis / 1000); 60 | uint32_t nanos = (millis % 1000) * 1000; 61 | U64TO8_BIG(output + 0, seconds); 62 | U32TO8_BIG(output + 8, nanos); 63 | } 64 | 65 | bool wireguard_is_under_load() { 66 | return false; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/wireguard-platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Ported to ESP32 Arduino by Kenta Ida (fuga@fugafuga.org) 3 | * The original license is below: 4 | * 5 | * Copyright (c) 2021 Daniel Hope (www.floorsense.nz) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without modification, 9 | * are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, this 15 | * list of conditions and the following disclaimer in the documentation and/or 16 | * other materials provided with the distribution. 17 | * 18 | * 3. Neither the name of "Floorsense Ltd", "Agile Workspace Ltd" nor the names of 19 | * its contributors may be used to endorse or promote products derived from this 20 | * software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 26 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 29 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * Author: Daniel Hope 34 | */ 35 | 36 | #ifndef _WIREGUARD_PLATFORM_H_ 37 | #define _WIREGUARD_PLATFORM_H_ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | // Peers are allocated statically inside the device structure to avoid malloc 44 | #define WIREGUARD_MAX_PEERS 1 45 | #define WIREGUARD_MAX_SRC_IPS 2 46 | 47 | // Per device limit on accepting (valid) initiation requests - per peer 48 | #define MAX_INITIATIONS_PER_SECOND (2) 49 | 50 | // 51 | // Your platform integration needs to provide implementations of these functions 52 | // 53 | 54 | void wireguard_platform_init(); 55 | 56 | // The number of milliseconds since system boot - for LwIP systems this could be sys_now() 57 | uint32_t wireguard_sys_now(); 58 | 59 | // Fill the supplied buffer with random data - random data is used for generating new session keys periodically 60 | void wireguard_random_bytes(void *bytes, size_t size); 61 | 62 | // Get the current time in tai64n format - 8 byte seconds, 4 byte nano sub-second - see https://cr.yp.to/libtai/tai64.html for details 63 | // Output buffer passed is 12 bytes 64 | // The Wireguard implementation doesn't strictly need this to be a time, but instead an increasing value 65 | // The remote end of the Wireguard tunnel will use this value in handshake replay detection 66 | void wireguard_tai64n_now(uint8_t *output); 67 | 68 | // Is the system under load - i.e. should we generate cookie reply message in response to initiation messages 69 | bool wireguard_is_under_load(); 70 | 71 | #endif /* _WIREGUARD_PLATFORM_H_ */ 72 | -------------------------------------------------------------------------------- /lib/WireGuard-ESP32/src/wireguardif.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Ported to ESP32 Arduino by Kenta Ida (fuga@fugafuga.org) 3 | * The original license is below: 4 | * 5 | * Copyright (c) 2021 Daniel Hope (www.floorsense.nz) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without modification, 9 | * are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * 2. Redistributions in binary form must reproduce the above copyright notice, this 15 | * list of conditions and the following disclaimer in the documentation and/or 16 | * other materials provided with the distribution. 17 | * 18 | * 3. Neither the name of "Floorsense Ltd", "Agile Workspace Ltd" nor the names of 19 | * its contributors may be used to endorse or promote products derived from this 20 | * software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 26 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 29 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * Author: Daniel Hope 34 | */ 35 | 36 | 37 | #ifndef _WIREGUARDIF_H_ 38 | #define _WIREGUARDIF_H_ 39 | 40 | #include "lwip/arch.h" 41 | #include "lwip/netif.h" 42 | #include "lwip/ip_addr.h" 43 | 44 | // Default MTU for WireGuard is 1420 bytes 45 | #define WIREGUARDIF_MTU (1420) 46 | 47 | #define WIREGUARDIF_DEFAULT_PORT (51820) 48 | #define WIREGUARDIF_KEEPALIVE_DEFAULT (0xFFFF) 49 | 50 | struct wireguardif_init_data { 51 | // Required: the private key of this WireGuard network interface 52 | const char *private_key; 53 | // Required: What UDP port to listen on 54 | u16_t listen_port; 55 | // Optional: restrict send/receive of encapsulated WireGuard traffic to this network interface only (NULL to use routing table) 56 | struct netif *bind_netif; 57 | }; 58 | 59 | struct wireguardif_peer { 60 | const char *public_key; 61 | // Optional pre-shared key (32 bytes) - make sure this is NULL if not to be used 62 | const uint8_t *preshared_key; 63 | // tai64n of largest timestamp we have seen during handshake to avoid replays 64 | uint8_t greatest_timestamp[12]; 65 | 66 | // Allowed ip/netmask (can add additional later but at least one is required) 67 | ip_addr_t allowed_ip; 68 | ip_addr_t allowed_mask; 69 | 70 | // End-point details (may be blank) 71 | ip_addr_t endpoint_ip; 72 | u16_t endport_port; 73 | u16_t keep_alive; 74 | }; 75 | 76 | #define WIREGUARDIF_INVALID_INDEX (0xFF) 77 | 78 | /* static struct netif wg_netif_struct = {0}; 79 | * struct wireguard_interface wg; 80 | * wg.private_key = "abcdefxxx..xxxxx="; 81 | * wg.listen_port = 51820; 82 | * wg.bind_netif = NULL; // Pass netif to listen on, NULL for all interfaces 83 | * 84 | * netif = netif_add(&netif_struct, &ipaddr, &netmask, &gateway, &wg, &wireguardif_init, &ip_input); 85 | * 86 | * netif_set_up(wg_net); 87 | * 88 | * struct wireguardif_peer peer; 89 | * wireguardif_peer_init(&peer); 90 | * peer.public_key = "apoehc...4322abcdfejg=; 91 | * peer.preshared_key = NULL; 92 | * peer.allowed_ip = allowed_ip; 93 | * peer.allowed_mask = allowed_mask; 94 | * 95 | * // If you want to enable output connection 96 | * peer.endpoint_ip = peer_ip; 97 | * peer.endport_port = 12345; 98 | * 99 | * uint8_t wireguard_peer_index; 100 | * wireguardif_add_peer(netif, &peer, &wireguard_peer_index); 101 | * 102 | * if ((wireguard_peer_index != WIREGUARDIF_INVALID_INDEX) && !ip_addr_isany(&peer.endpoint_ip)) { 103 | * // Start outbound connection to peer 104 | * wireguardif_connect(wg_net, wireguard_peer_index); 105 | * } 106 | * 107 | */ 108 | 109 | // Initialise a new WireGuard network interface (netif) 110 | err_t wireguardif_init(struct netif *netif); 111 | 112 | // Shutdown a WireGuard network interface (netif) 113 | void wireguardif_shutdown(struct netif *netif); 114 | 115 | // Helper to initialise the peer struct with defaults 116 | void wireguardif_peer_init(struct wireguardif_peer *peer); 117 | 118 | // Add a new peer to the specified interface - see wireguard.h for maximum number of peers allowed 119 | // On success the peer_index can be used to reference this peer in future function calls 120 | err_t wireguardif_add_peer(struct netif *netif, struct wireguardif_peer *peer, u8_t *peer_index); 121 | 122 | // Remove the given peer from the network interface 123 | err_t wireguardif_remove_peer(struct netif *netif, u8_t peer_index); 124 | 125 | // Update the "connect" IP of the given peer 126 | err_t wireguardif_update_endpoint(struct netif *netif, u8_t peer_index, const ip_addr_t *ip, u16_t port); 127 | 128 | // Try and connect to the given peer 129 | err_t wireguardif_connect(struct netif *netif, u8_t peer_index); 130 | 131 | // Stop trying to connect to the given peer 132 | err_t wireguardif_disconnect(struct netif *netif, u8_t peer_index); 133 | 134 | // Is the given peer "up"? A peer is up if it has a valid session key it can communicate with 135 | err_t wireguardif_peer_is_up(struct netif *netif, u8_t peer_index, ip_addr_t *current_ip, u16_t *current_port); 136 | 137 | #endif /* _WIREGUARDIF_H_ */ 138 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CZC-FW", 3 | "version": "v1.0.0", 4 | "builds": [ 5 | { 6 | "chipFamily": "ESP32", 7 | "improv": false, 8 | "parts": [ 9 | { "path": "bin/CZC-1.0_v1.0.0.full.bin", "offset": 0 } 10 | ] 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | ;It was difficult to find working platform for https get function on solo board. Here are some logs: 12 | ;https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5/platform-espressif32-2.0.5.zip ;- old build. - unkown board 13 | ;https://github.com/tasmota/platform-espressif32/releases/download/2023.01.00/platform-espressif32.zip ; fuck yeaar. it works on solo 14 | ;https://github.com/tasmota/platform-espressif32/releases/download/2023.07.00/platform-espressif32.zip ; fuck yeaar. it also works on solo 15 | ;https://github.com/tasmota/platform-espressif32/releases/download/2023.08.00/platform-espressif32.zip ; bitch. did't work -1 16 | ;https://github.com/tasmota/platform-espressif32/releases/download/2023.10.01/platform-espressif32.zip ;- build but -1 17 | ;https://github.com/tasmota/platform-espressif32/releases/download/2023.10.03/platform-espressif32.zip ;- last builds version but -1 18 | ;https://github.com/tasmota/platform-espressif32/releases/download/2023.10.05/platform-espressif32.zip ;- WiFiClientSecure.h: No such file or directory 19 | ;https://github.com/tasmota/platform-espressif32/releases/download/2023.10.10/platform-espressif32.zip ; - logs2.txt 20 | ;espressif32 @ ^6.4.0 ;- unkown board 21 | ;espressif32 @ 5.1.0 ; - works but no solo 22 | 23 | [platformio] 24 | default_envs = codm-v1-prod 25 | 26 | [env] 27 | framework = arduino 28 | lib_deps = 29 | bblanchon/ArduinoJson@6.21.3 30 | rlogiacco/CircularBuffer@>=1.3.3 31 | plerup/EspSoftwareSerial@8.1.0 32 | marian-craciunescu/ESP32Ping@>=1.7 33 | sstaub/Ticker@>=4.4.0 34 | knolleary/PubSubClient@^2.8 35 | ESP Async WebServer 36 | Martin-Laclaustra/CronAlarms 37 | monitor_filters = esp32_exception_decoder, default ;, log2file 38 | monitor_speed = 115200 39 | upload_speed = 460800 40 | extra_scripts = 41 | pre:tools/version_increment_pre.py 42 | pre:tools/webfilesbuilder/build_html.py 43 | post:tools/build.py 44 | build_flags = 45 | -DBUILD_ENV_NAME=$PIOENV 46 | 47 | 48 | [env:prod-solo] 49 | platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.07.00/platform-espressif32.zip 50 | board = esp32-solo1 51 | build_flags = 52 | ${env.build_flags} 53 | -DFRAMEWORK_ARDUINO_SOLO1 54 | board_build.f_cpu = 160000000L 55 | extra_scripts = 56 | ${env.extra_scripts} 57 | 58 | [env:debug-solo] 59 | platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.07.00/platform-espressif32.zip 60 | board = esp32-solo1 61 | build_flags = 62 | -DDEBUG 63 | ${env.build_flags} 64 | -DFRAMEWORK_ARDUINO_SOLO1 65 | board_build.f_cpu = 160000000L 66 | extra_scripts = 67 | ${env.extra_scripts} 68 | 69 | 70 | [env:prod] 71 | platform = espressif32 @ 6.4.0 72 | board = esp32dev 73 | build_flags = 74 | ${env.build_flags} 75 | extra_scripts = 76 | ${env.extra_scripts} 77 | 78 | [env:debug] 79 | platform = espressif32 @ 6.4.0 80 | board = esp32dev 81 | build_flags = 82 | -DDEBUG 83 | ${env.build_flags} 84 | extra_scripts = 85 | ${env.extra_scripts} 86 | 87 | [env:codm-v1-prod] 88 | platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.07.00/platform-espressif32.zip 89 | board = esp32-solo1 90 | build_flags = 91 | ${env.build_flags} 92 | -DCODM_BOARD 93 | extra_scripts = 94 | ${env.extra_scripts} 95 | 96 | [env:codm-v1-debug] 97 | platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.07.00/platform-espressif32.zip 98 | board = esp32-solo1 99 | build_flags = 100 | -DDEBUG 101 | ${env.build_flags} 102 | -DCODM_BOARD 103 | extra_scripts = 104 | ${env.extra_scripts} -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H_ 2 | #define CONFIG_H_ 3 | 4 | #include 5 | #include 6 | #include "version.h" 7 | 8 | #ifdef CODM_BOARD 9 | // ESP32 PINS TO CONTROL LAN8720 10 | #define ETH_CLK_MODE_1 ETH_CLOCK_GPIO17_OUT 11 | #define ETH_POWER_PIN_ALTERNATIVE_1 5 12 | #define ETH_POWER_PIN_1 -1 13 | #define ETH_TYPE_1 ETH_PHY_LAN8720 14 | #define ETH_ADDR_1 0 15 | #define ETH_MDC_PIN_1 23 16 | #define ETH_MDIO_PIN_1 18 17 | // ESP32 PINS TO CONTROL CC2652P 18 | #define CC2652P_RST 16 19 | #define CC2652P_FLASH 32 20 | #define CC2652P_RXD 36 //seen from ESP 21 | #define CC2652P_TXD 4 //seen from ESP 22 | #define BTN 35 23 | #define MODE_SWITCH 33 24 | #define DEBOUNCE_TIME 70 25 | #define PRODUCTION 1 26 | #define TCP_LISTEN_PORT 9999 27 | #define FORMAT_LITTLEFS_IF_FAILED true 28 | #define BOARD_DEVICE_MODEL "CZC" 29 | #define BOARD_DEVICE_MODEL_REV "CZC v1.0" 30 | #define BOARD_MDNS_HOST "_czc" 31 | #else 32 | //ESP32 PINS TO CONTROL LAN8720 33 | #define ETH_CLK_MODE_1 ETH_CLOCK_GPIO17_OUT 34 | #define ETH_POWER_PIN_ALTERNATIVE_1 5 35 | #define ETH_POWER_PIN_1 -1 36 | #define ETH_TYPE_1 ETH_PHY_LAN8720 37 | #define ETH_ADDR_1 0 38 | #define ETH_MDC_PIN_1 23 39 | #define ETH_MDIO_PIN_1 18 40 | //ESP32 PINS TO CONTROL CC2652P 41 | #define CC2652P_RST 16 42 | #define CC2652P_FLASH 32 43 | #define CC2652P_RXD 36 44 | #define CC2652P_TXD 4 45 | #define BTN 35 46 | #define MODE_SWITCH 33 47 | #define DEBOUNCE_TIME 70 48 | 49 | #define TCP_LISTEN_PORT 9999 50 | #define FORMAT_LITTLEFS_IF_FAILED true 51 | #define BOARD_DEVICE_MODEL "UZG-01" 52 | #define BOARD_DEVICE_MODEL_REV "UZG-01" 53 | #define BOARD_MDNS_HOST "_uzg-01" 54 | #endif 55 | 56 | 57 | // CC2652 settings (FOR BSL VALIDATION!) 58 | #define NEED_BSL_PIN 15 // CC2652 pin number (FOR BSL VALIDATION!) 59 | #define NEED_BSL_LEVEL 0 // 0-LOW 1-HIGH 60 | 61 | const int16_t overseerInterval = 5 * 1000; // check lan or wifi connection every 5sec 62 | const uint8_t overseerMaxRetry = 3; // 5x12 = 60sec delay for AP start 63 | const uint8_t LED_USB = 12; // RED 64 | const uint8_t LED_PWR = 14; // BLUE 65 | const uint8_t MAX_SOCKET_CLIENTS = 5; 66 | 67 | enum COORDINATOR_MODE_t : uint8_t 68 | { 69 | COORDINATOR_MODE_LAN, 70 | COORDINATOR_MODE_WIFI, 71 | COORDINATOR_MODE_USB 72 | }; 73 | 74 | extern const char *coordMode;// coordMode node name 75 | extern const char *prevCoordMode;// prevCoordMode node name 76 | extern const char *configFileSystem; 77 | extern const char *configFileWifi; 78 | extern const char *configFileEther; 79 | extern const char *configFileGeneral; 80 | extern const char *configFileSecurity; 81 | extern const char *configFileSerial; 82 | extern const char *configFileMqtt; 83 | extern const char *configFileWg; 84 | extern const char *deviceModel; 85 | 86 | struct ConfigSettingsStruct 87 | { 88 | char ssid[50]; 89 | char password[50]; 90 | char ipAddressWiFi[18]; 91 | char ipMaskWiFi[16]; 92 | char ipGWWiFi[18]; 93 | bool dhcpWiFi; 94 | bool dhcp; 95 | bool connectedEther; 96 | char ipAddress[18]; 97 | char ipMask[16]; 98 | char ipGW[18]; 99 | int serialSpeed; 100 | int socketPort; 101 | bool disableWeb; 102 | int refreshLogs; 103 | char hostname[50]; 104 | bool connectedSocket[10]; 105 | int connectedClients; 106 | unsigned long socketTime; 107 | int tempOffset; 108 | bool webAuth; 109 | char webUser[50]; 110 | char webPass[50]; 111 | bool disableLedUSB; 112 | bool disableLedPwr; 113 | // bool disablePingCtrl; 114 | bool disableLeds; 115 | COORDINATOR_MODE_t coordinator_mode; 116 | COORDINATOR_MODE_t prevCoordinator_mode; // for button 117 | bool keepWeb; 118 | bool apStarted; 119 | bool wifiWebSetupInProgress; 120 | bool fwEnabled; 121 | IPAddress fwIp; 122 | 123 | bool zbLedState; 124 | bool zbFlashing; 125 | char timeZone[50]; 126 | }; 127 | 128 | struct MqttSettingsStruct 129 | { 130 | bool enable; 131 | char server[50]; 132 | IPAddress serverIP; 133 | int port; 134 | char user[50]; 135 | char pass[50]; 136 | char topic[50]; 137 | // bool retain; 138 | int interval; 139 | bool discovery; 140 | unsigned long reconnectTime; 141 | unsigned long heartbeatTime; 142 | }; 143 | 144 | struct WgSettingsStruct 145 | { 146 | bool enable; 147 | bool init = 0; 148 | char localAddr[20]; 149 | IPAddress localIP; 150 | char localPrivKey[45]; 151 | char endAddr[45]; 152 | char endPubKey[45]; 153 | int endPort; 154 | }; 155 | 156 | /* 157 | struct InfosStruct 158 | { 159 | char device[8]; 160 | char mac[8]; 161 | char flash[8]; 162 | }; 163 | */ 164 | 165 | struct zbVerStruct 166 | { 167 | uint32_t zbRev; 168 | uint8_t maintrel; 169 | uint8_t minorrel; 170 | uint8_t majorrel; 171 | uint8_t product; 172 | uint8_t transportrev; 173 | String chipID; 174 | }; 175 | 176 | typedef CircularBuffer LogConsoleType; 177 | 178 | // #define WL_MAC_ADDR_LENGTH 6 179 | 180 | extern uint8_t _global_usb_mode; 181 | 182 | #ifdef DEBUG 183 | #define DEBUG_PRINT(x) if(!_global_usb_mode) {Serial.print(String(x));} 184 | #define DEBUG_PRINTLN(x) if(!_global_usb_mode) {Serial.println(String(x));} 185 | #else 186 | #define DEBUG_PRINT(x) 187 | #define DEBUG_PRINTLN(x) 188 | #endif 189 | #endif 190 | -------------------------------------------------------------------------------- /src/etc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "config.h" 10 | #include "web.h" 11 | #include "log.h" 12 | #include "etc.h" 13 | #include "zones.h" 14 | 15 | extern struct ConfigSettingsStruct ConfigSettings; 16 | 17 | extern CCTools CCTool; 18 | 19 | const char *coordMode = "coordMode"; // coordMode node name 20 | const char *prevCoordMode = "prevCoordMode"; // prevCoordMode node name 21 | const char *configFileSystem = "/config/system.json"; 22 | const char *configFileWifi = "/config/configWifi.json"; 23 | const char *configFileEther = "/config/configEther.json"; 24 | const char *configFileGeneral = "/config/configGeneral.json"; 25 | const char *configFileSecurity = "/config/configSecurity.json"; 26 | const char *configFileSerial = "/config/configSerial.json"; 27 | const char *configFileMqtt = "/config/configMqtt.json"; 28 | const char *configFileWg = "/config/configWg.json"; 29 | const char *deviceModel = BOARD_DEVICE_MODEL_REV; 30 | 31 | void getReadableTime(String &readableTime, unsigned long beginTime) 32 | { 33 | unsigned long currentMillis; 34 | unsigned long seconds; 35 | unsigned long minutes; 36 | unsigned long hours; 37 | unsigned long days; 38 | currentMillis = millis() - beginTime; 39 | seconds = currentMillis / 1000; 40 | minutes = seconds / 60; 41 | hours = minutes / 60; 42 | days = hours / 24; 43 | currentMillis %= 1000; 44 | seconds %= 60; 45 | minutes %= 60; 46 | hours %= 24; 47 | 48 | readableTime = String(days) + " d "; 49 | 50 | if (hours < 10) 51 | { 52 | readableTime += "0"; 53 | } 54 | readableTime += String(hours) + ":"; 55 | 56 | if (minutes < 10) 57 | { 58 | readableTime += "0"; 59 | } 60 | readableTime += String(minutes) + ":"; 61 | 62 | if (seconds < 10) 63 | { 64 | readableTime += "0"; 65 | } 66 | readableTime += String(seconds) + ""; 67 | } 68 | 69 | float readtemp(bool clear) 70 | { 71 | if (clear == true) 72 | { 73 | return (temprature_sens_read() - 32) / 1.8; 74 | } 75 | else 76 | { 77 | return (temprature_sens_read() - 32) / 1.8 - ConfigSettings.tempOffset; 78 | } 79 | } 80 | 81 | float getCPUtemp(bool clear) 82 | { 83 | DEBUG_PRINTLN(F("getCPUtemp")); 84 | float CPUtemp = 0.0; 85 | if (WiFi.getMode() == WIFI_MODE_NULL || WiFi.getMode() == WIFI_OFF) 86 | { 87 | DEBUG_PRINTLN(F("enable wifi to enable temp sensor")); 88 | WiFi.mode(WIFI_STA); // enable wifi to enable temp sensor 89 | CPUtemp = readtemp(clear); 90 | WiFi.disconnect(); 91 | WiFi.mode(WIFI_OFF); // disable wifi 92 | } 93 | else 94 | { 95 | CPUtemp = readtemp(clear); 96 | } 97 | return CPUtemp; 98 | } 99 | 100 | void zigbeeRouterRejoin() 101 | { 102 | printLogMsg("Router rejoin begin"); 103 | DEBUG_PRINTLN(F("Router rejoin begin")); 104 | CCTool.routerRejoin(); 105 | printLogMsg("Router in join mode!"); 106 | DEBUG_PRINTLN(F("Router in join mode!")); 107 | } 108 | 109 | void zigbeeEnableBSL() 110 | { 111 | printLogMsg("ZB enable BSL"); 112 | DEBUG_PRINTLN(F("ZB enable BSL")); 113 | CCTool.enterBSL(); 114 | printLogMsg("Now you can flash CC2652!"); 115 | DEBUG_PRINTLN(F("Now you can flash CC2652!")); 116 | } 117 | 118 | void zigbeeRestart() 119 | { 120 | printLogMsg("ZB RST begin"); 121 | DEBUG_PRINTLN(F("ZB RST begin")); 122 | CCTool.restart(); 123 | printLogMsg("ZB restart was done"); 124 | DEBUG_PRINTLN(F("ZB restart was done")); 125 | } 126 | 127 | void adapterModeUSB() 128 | { 129 | printLogMsg("Switched UZG-01 to USB mode"); 130 | _global_usb_mode = true; 131 | DEBUG_PRINTLN(F("Switched UZG-01 to USB mode")); 132 | Serial.flush(); 133 | // digitalWrite(MODE_SWITCH, 1); 134 | digitalWrite(LED_USB, 1); 135 | } 136 | 137 | void adapterModeLAN() 138 | { 139 | printLogMsg("Switched UZG-01 to LAN mode"); 140 | _global_usb_mode = false; 141 | DEBUG_PRINTLN(F("Switched UZG-01 to LAN mode")); 142 | // digitalWrite(MODE_SWITCH, 0); 143 | digitalWrite(LED_USB, 0); 144 | } 145 | 146 | void ledPowerToggle() 147 | { 148 | printLogMsg("BLUE LED has been toggled"); 149 | DEBUG_PRINTLN(F("BLUE LED has been toggled")); 150 | digitalWrite(LED_PWR, !digitalRead(LED_PWR)); 151 | } 152 | 153 | void ledUSBToggle() 154 | { 155 | printLogMsg("RED LED has been toggled"); 156 | DEBUG_PRINTLN(F("RED LED has been toggled")); 157 | digitalWrite(LED_USB, !digitalRead(LED_USB)); 158 | } 159 | 160 | void getDeviceID(char *arr) 161 | { 162 | String mac = ETH.macAddress(); 163 | int last = mac.lastIndexOf(':'); 164 | String last_str = mac.substring(last + 1, last + 3); 165 | int pre_last = last - 3; 166 | String pre_last_str = mac.substring(pre_last + 1, pre_last + 3); 167 | sprintf(arr, "%s-%s%s", BOARD_DEVICE_MODEL, pre_last_str, last_str); 168 | } 169 | 170 | // void writeDefaultConfig(const char *path, String StringConfig) 171 | // { 172 | // DEBUG_PRINTLN(path); 173 | // DEBUG_PRINTLN(F("failed open. try to write defaults")); 174 | // DEBUG_PRINTLN(StringConfig); 175 | 176 | // DynamicJsonDocument doc(1024); 177 | // deserializeJson(doc, StringConfig); 178 | 179 | // File configFile = LittleFS.open(path, FILE_WRITE); 180 | // if (!configFile) 181 | // { 182 | // DEBUG_PRINTLN(F("failed write")); 183 | // //return false; 184 | // } 185 | // else 186 | // { 187 | // serializeJson(doc, configFile); 188 | // } 189 | // configFile.close(); 190 | // } 191 | 192 | void writeDefaultConfig(const char *path, DynamicJsonDocument &doc) 193 | { 194 | DEBUG_PRINTLN(path); 195 | DEBUG_PRINTLN(F("Write defaults")); 196 | 197 | File configFile = LittleFS.open(path, FILE_WRITE); 198 | if (!configFile) 199 | { 200 | DEBUG_PRINTLN(F("Failed Write")); 201 | // return false; 202 | } 203 | else 204 | { 205 | serializeJson(doc, configFile); 206 | } 207 | configFile.close(); 208 | } 209 | 210 | String hexToDec(String hexString) 211 | { 212 | 213 | unsigned int decValue = 0; 214 | int nextInt; 215 | 216 | for (int i = 0; i < hexString.length(); i++) 217 | { 218 | 219 | nextInt = int(hexString.charAt(i)); 220 | if (nextInt >= 48 && nextInt <= 57) 221 | nextInt = map(nextInt, 48, 57, 0, 9); 222 | if (nextInt >= 65 && nextInt <= 70) 223 | nextInt = map(nextInt, 65, 70, 10, 15); 224 | if (nextInt >= 97 && nextInt <= 102) 225 | nextInt = map(nextInt, 97, 102, 10, 15); 226 | nextInt = constrain(nextInt, 0, 15); 227 | 228 | decValue = (decValue * 16) + nextInt; 229 | } 230 | 231 | return String(decValue); 232 | } 233 | 234 | void resetSettings() 235 | { 236 | DEBUG_PRINTLN(F("[resetSettings] Start")); 237 | digitalWrite(LED_USB, 1); 238 | digitalWrite(LED_PWR, 0); 239 | for (uint8_t i = 0; i < 15; i++) 240 | { 241 | delay(200); 242 | digitalWrite(LED_USB, !digitalRead(LED_USB)); 243 | digitalWrite(LED_PWR, !digitalRead(LED_PWR)); 244 | } 245 | DEBUG_PRINTLN(F("[resetSettings] Led blinking done")); 246 | if (!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED, "/lfs2", 10)) 247 | { 248 | DEBUG_PRINTLN(F("Error with LITTLEFS")); 249 | } 250 | LittleFS.remove(configFileSerial); 251 | LittleFS.remove(configFileSecurity); 252 | LittleFS.remove(configFileGeneral); 253 | LittleFS.remove(configFileEther); 254 | LittleFS.remove(configFileWifi); 255 | LittleFS.remove(configFileSystem); 256 | LittleFS.remove(configFileWg); 257 | DEBUG_PRINTLN(F("[resetSettings] Config del done")); 258 | ESP.restart(); 259 | } 260 | 261 | void setClock() 262 | { 263 | configTime(0, 0, "pool.ntp.org", "time.google.com"); 264 | 265 | DEBUG_PRINT(F("Waiting for NTP time sync: ")); 266 | int startTryingTime = millis(); 267 | DEBUG_PRINTLN(startTryingTime); 268 | startTryingTime = startTryingTime / 1000; 269 | time_t nowSecs = time(nullptr); 270 | DEBUG_PRINTLN(nowSecs); 271 | while ((nowSecs - startTryingTime) < 60) 272 | { 273 | delay(500); 274 | DEBUG_PRINT(F(".")); 275 | yield(); 276 | nowSecs = time(nullptr); 277 | } 278 | 279 | DEBUG_PRINTLN(); 280 | struct tm timeinfo; 281 | localtime_r(&nowSecs, &timeinfo); 282 | DEBUG_PRINT(F("Current GMT time: ")); 283 | DEBUG_PRINT(asctime(&timeinfo)); 284 | 285 | char *zoneToFind = const_cast("Europe/Berlin"); 286 | if (ConfigSettings.timeZone) 287 | { 288 | zoneToFind = ConfigSettings.timeZone; 289 | } 290 | const char *gmtOffset = getGmtOffsetForZone(zoneToFind); 291 | 292 | String timezone = "EET-2EEST,M3.5.0/3,M10.5.0/4"; 293 | 294 | if (gmtOffset != nullptr) 295 | { 296 | DEBUG_PRINT(F("GMT Offset for ")); 297 | DEBUG_PRINT(zoneToFind); 298 | DEBUG_PRINT(F(" is ")); 299 | DEBUG_PRINTLN(gmtOffset); 300 | timezone = gmtOffset; 301 | setTimezone(timezone); 302 | } 303 | else 304 | { 305 | DEBUG_PRINT(F("GMT Offset for ")); 306 | DEBUG_PRINT(zoneToFind); 307 | DEBUG_PRINTLN(F(" not found.")); 308 | } 309 | } 310 | 311 | void setTimezone(String timezone) 312 | { 313 | DEBUG_PRINTLN(F("Setting Timezone")); 314 | setenv("TZ", timezone.c_str(), 1); // Now adjust the TZ. Clock settings are adjusted to show the new local time 315 | tzset(); 316 | time_t nowSecs = time(nullptr); 317 | struct tm timeinfo; 318 | localtime_r(&nowSecs, &timeinfo); 319 | 320 | String timeNow = asctime(&timeinfo); 321 | timeNow.remove(timeNow.length() - 1); 322 | DEBUG_PRINT(F("Local time: ")); 323 | DEBUG_PRINTLN(timeNow); 324 | printLogMsg("Local time: " + timeNow); 325 | } 326 | 327 | const char *getGmtOffsetForZone(const char *zone) 328 | { 329 | for (int i = 0; i < timeZoneCount; i++) 330 | { 331 | if (strcmp(zone, timeZones[i].zone) == 0) 332 | { 333 | // Зона найдена, возвращаем GMT Offset 334 | return timeZones[i].gmtOffset; 335 | } 336 | } 337 | // Зона не найдена 338 | return nullptr; 339 | } 340 | 341 | void ledsScheduler() 342 | { 343 | DEBUG_PRINTLN(F("LEDS Scheduler")); 344 | } -------------------------------------------------------------------------------- /src/etc.h: -------------------------------------------------------------------------------- 1 | void getReadableTime(String &readableTime, unsigned long beginTime); 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | uint8_t temprature_sens_read(); 7 | #ifdef __cplusplus 8 | } 9 | #endif 10 | uint8_t temprature_sens_read(); 11 | 12 | 13 | #define STRINGIFY(s) STRINGIFY1(s) // Don’t ask why. It has to do with the inner workings of the preprocessor. 14 | #define STRINGIFY1(s) #s // https://community.platformio.org/t/how-to-put-a-string-in-a-define-in-build-flag-into-a-libary-json-file/13480/6 15 | 16 | 17 | 18 | float getCPUtemp(bool clear = false); 19 | 20 | void zigbeeRouterRejoin(); 21 | void zigbeeEnableBSL(); 22 | void zigbeeRestart(); 23 | 24 | void adapterModeUSB(); 25 | void adapterModeLAN(); 26 | 27 | void ledPowerToggle(); 28 | void ledUSBToggle(); 29 | 30 | void getDeviceID(char * arr); 31 | void writeDefaultConfig(const char *path, DynamicJsonDocument& doc); 32 | 33 | void resetSettings(); 34 | 35 | String hexToDec(String hexString); 36 | 37 | void setClock(); 38 | void setTimezone(String timezone); 39 | const char* getGmtOffsetForZone(const char* zone); 40 | void ledsScheduler (); 41 | 42 | //#define min(a, b) ((a) < (b) ? (a) : (b)) -------------------------------------------------------------------------------- /src/log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "log.h" 4 | #include "config.h" 5 | 6 | LogConsoleType logConsole; 7 | 8 | void logPush(char c) 9 | { 10 | logConsole.push(c); 11 | } 12 | 13 | String logPrint() 14 | { 15 | 16 | String buff = ""; 17 | 18 | if (logConsole.isEmpty()) { 19 | return ""; 20 | } else { 21 | for (decltype(logConsole)::index_t i = 0; i < logConsole.size() - 1; i++) { 22 | buff += logConsole[i]; 23 | } 24 | return buff; 25 | } 26 | } 27 | 28 | void logClear() 29 | { 30 | if (!logConsole.isEmpty()) { 31 | logConsole.clear(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | void logPush(char c); 2 | void logClear(); 3 | String logPrint(); 4 | -------------------------------------------------------------------------------- /src/mqtt.h: -------------------------------------------------------------------------------- 1 | 2 | void mqttConnectSetup(); 3 | void mqttReconnect(); 4 | void mqttCallback(char *topic, byte *payload, unsigned int length); 5 | void mqttLoop(); 6 | void mqttPublishState(); 7 | void mqttOnConnect(); 8 | void mqttPublishAvail(); 9 | void mqttPublishDiscovery(); 10 | void mqttPublishMsg(String topic, String msg, bool retain); 11 | void mqttPublishIo(String const &io, String const &state); 12 | void mqttSubscribe(String topic); -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | 2 | // AUTO GENERATED FILE, DO NOT EDIT 3 | #ifndef VERSION 4 | #define VERSION "1.0.0" 5 | #endif 6 | #ifndef BUILD_TIMESTAMP 7 | #define BUILD_TIMESTAMP "2024-05-14 12:09:00.389647" 8 | #endif 9 | -------------------------------------------------------------------------------- /src/web.h: -------------------------------------------------------------------------------- 1 | #include 2 | void handleEvents(); 3 | void initWebServer(); 4 | void webServerHandleClient(); 5 | void handleGeneral(); 6 | void handleSecurity(); 7 | void handleRoot(); 8 | void handleWifi(); 9 | void handleEther(); 10 | void handleMqtt(); 11 | void handleWg(); 12 | void handleZigbeeBSL(); 13 | void handleZigbeeRestart(); 14 | void handleSerial(); 15 | void handleSavefile(); 16 | void handleApi(); 17 | void handleStatus(); 18 | void sendGzip(const char* contentType, const uint8_t content[], uint16_t contentLen); 19 | void handleSysTools(); 20 | void printLogTime(); 21 | void printLogMsg(String msg); 22 | void handleSaveParams(); 23 | bool checkAuth(); 24 | 25 | void sendEvent(const char *event, const uint8_t evsz, const String data); 26 | void progressFunc(unsigned int progress, unsigned int total); 27 | 28 | void getEspUpdate(String esp_fw_url); 29 | void runEspUpdateFirmware(uint8_t *data, size_t len); 30 | 31 | void setClock(); 32 | 33 | #define UPD_FILE "https://github.com/codm/czc-firmware/releases/latest/download/CZC-1.0.bin" 34 | -------------------------------------------------------------------------------- /src/websrc/.gitignore: -------------------------------------------------------------------------------- 1 | gzipped/ -------------------------------------------------------------------------------- /src/websrc/css/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --bs-primary: #212227; 3 | --bs-primary-rgb: rgb(33, 34, 39); 4 | --bs-secondary: #6c757d; 5 | --bs-secondary-rgb: 108, 117, 125; 6 | --bs-nav-link-hover-color: #ff7400; 7 | --bs-link-hover-color: #ff7400; 8 | --bs-nav-link-color: #212227; 9 | --bs-link-color: #212227; 10 | } 11 | 12 | .btn-outline-primary { 13 | --bs-btn-color:#212227; 14 | --bs-btn-border-color: #212227; 15 | --bs-btn-hover-border-color: #ff7400; 16 | --bs-btn-hover-color: #ff7400; 17 | --bs-btn-hover-bg: var(--bs-body-bg-rgb); 18 | } 19 | 20 | .btn-outline-green { 21 | --bs-btn-color:#212227; 22 | --bs-btn-border-color: #212227; 23 | --bs-btn-hover-color: var(--bs-green); 24 | --bs-btn-hover-bg: #dee2e6; 25 | --bs-btn-hover-border-color: var(--bs-green); 26 | --bs-btn-hover-bg: var(--bs-body-bg-rgb); 27 | } 28 | 29 | .btn-outline-red { 30 | --bs-btn-color:#212227; 31 | --bs-btn-border-color: #212227; 32 | --bs-btn-hover-color: var(--bs-red); 33 | --bs-btn-hover-bg: #dee2e6; 34 | --bs-btn-hover-border-color: var(--bs-red); 35 | --bs-btn-hover-bg: var(--bs-body-bg-rgb); 36 | } 37 | 38 | .btn-outline-yellow { 39 | --bs-btn-color:#212227; 40 | --bs-btn-border-color: #212227; 41 | --bs-btn-hover-color: var(--bs-yellow); 42 | --bs-btn-hover-bg: #dee2e6; 43 | --bs-btn-hover-border-color: var(--bs-yellow); 44 | --bs-btn-hover-bg: var(--bs-body-bg-rgb); 45 | } 46 | 47 | input.swFx{ 48 | border: 1px solid rgba(0,0,0,.25) !important; 49 | } 50 | 51 | input.swFx:checked { 52 | background-color: #303fa1 !important; 53 | border-color: #303fa1 !important; 54 | } 55 | 56 | label.swFx{ 57 | color: black !important; 58 | } 59 | 60 | /* Preloader */ 61 | .uzg-loader { 62 | width:100px; 63 | height:100px; 64 | border-radius:50%; 65 | border:16px solid; 66 | border-color:#047cc3 #0000; 67 | animation:s1 0.5s infinite; 68 | } 69 | @keyframes s1 {to{transform: rotate(.5turn)}} 70 | 71 | #uzPreloader{ 72 | position: absolute; 73 | left: calc(50% - 50px); 74 | top: calc(50% - 50px); 75 | z-index: 1000; 76 | width: 100px; 77 | height: 100px; 78 | } 79 | 80 | .card-disabled{ 81 | opacity: 0.5; 82 | cursor: not-allowed; 83 | } 84 | 85 | .card-disabled > *{ 86 | pointer-events: none; 87 | } 88 | 89 | @media (min-width: 576px) { 90 | .nav { 91 | padding-left: 8px; 92 | } 93 | 94 | } 95 | 96 | @media (max-width: 767px) { 97 | .nav-container { 98 | position: fixed; 99 | left: -250px; 100 | transition: all 0.3s ease-out; 101 | top: -1px !important; 102 | } 103 | 104 | nav.navbar { 105 | display: flex !important; 106 | z-index: 99; 107 | } 108 | 109 | #pagenamePC { 110 | display: none; 111 | } 112 | } 113 | 114 | .sidenav-active { 115 | left: -1px !important; 116 | transition: all 0.6s ease-out; 117 | } 118 | 119 | .toast { 120 | z-index: 100; 121 | margin-right: 20px; 122 | } 123 | 124 | .nav-container { 125 | min-width: fit-content; 126 | z-index: 100; 127 | } 128 | 129 | .nav { 130 | width: 100%; 131 | white-space: nowrap; 132 | } 133 | 134 | .logo-wrapper { 135 | padding-left: 8px; 136 | padding-right: 8px; 137 | margin-bottom: 10px; 138 | } 139 | 140 | .logo-wrapper span { 141 | padding-left: 6px; 142 | vertical-align: middle; 143 | } 144 | 145 | .app-main-content { 146 | padding-top: 0px; 147 | } 148 | 149 | .cardPadding { 150 | padding-bottom: 20px; 151 | } 152 | 153 | .nav-item span { 154 | vertical-align: inherit; 155 | } 156 | 157 | .nav-item { 158 | width: 100%; 159 | padding-left: 8px; 160 | padding-right: 8px; 161 | } 162 | 163 | .nav-item a { 164 | border-radius: 0 !important; 165 | } 166 | 167 | .nav-item:last-child a { 168 | border-bottom: none !important; 169 | } 170 | 171 | #file-input { 172 | padding: 0; 173 | border: 1px solid #ddd; 174 | line-height: 44px; 175 | text-align: left; 176 | display: block; 177 | cursor: pointer; 178 | width: 100%; 179 | height: 44px; 180 | border-radius: 4px; 181 | margin: 10px auto; 182 | font-size: 15px 183 | } 184 | 185 | #bar, 186 | #prgbar { 187 | background-color: #f1f1f1; 188 | border-radius: 10px 189 | } 190 | 191 | #bar { 192 | background-color: #17a2b8; 193 | width: 0%; 194 | height: 10px 195 | } 196 | 197 | form#upload_form { 198 | background: #fff; 199 | max-width: 408px; 200 | border-radius: 5px; 201 | text-align: center 202 | } 203 | 204 | h2 { 205 | text-align: center 206 | } 207 | 208 | div#update_info { 209 | max-width: 55%; 210 | margin: auto; 211 | margin-bottom: 25px; 212 | } 213 | 214 | div#main { 215 | margin-left: auto; 216 | margin-right: auto; 217 | } -------------------------------------------------------------------------------- /src/websrc/html/PAGE_ABOUT.html: -------------------------------------------------------------------------------- 1 |
2 | 36 |
-------------------------------------------------------------------------------- /src/websrc/html/PAGE_ETHERNET.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
Ethernet options
7 |
8 |
9 | 11 | 12 |
13 |
14 | 15 | 17 |
18 |
19 | 20 | 22 |
23 |
24 | 25 | 27 |
28 | 34 |
35 |
36 | 38 |
39 |
40 |
41 |
42 |
43 |
44 |
-------------------------------------------------------------------------------- /src/websrc/html/PAGE_GENERAL.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
General settings
7 |
8 |
9 |
10 |
11 |
12 | Select the device operating mode: 13 |
14 | 16 | 19 |
20 |
21 | 23 | 26 |
27 | 28 | 45 |
46 |
47 |
48 |
49 |
50 |
51 | Using the Toggle buttons, you can control the state of the LEDs in the 52 | current 53 | session (not saved on reboot): 54 |
55 |
56 |
57 | 59 | 61 | 63 |
64 |
65 |
66 | 67 |
68 |
69 | Control the behavior of the LEDs (with saving on reboot) using the 70 | switches 71 | below: 72 |
73 | 75 | 77 |
78 | 84 |
85 |
86 |
87 |
88 |
89 |
90 | 92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
-------------------------------------------------------------------------------- /src/websrc/html/PAGE_LOADER.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | 32 |
33 | 51 | 67 |
68 |
69 | 183 |
184 |

185 |
186 | 187 |
188 |
© 2023 190 | ZigStar
191 |
192 |
193 |
194 | 195 | 196 | 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /src/websrc/html/PAGE_LOGOUT.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/websrc/html/PAGE_MQTT.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
MQTT options
7 |
8 |
9 | 11 | 12 |
13 |
14 | 15 | 17 |
18 |
19 | 20 | 22 |
23 |
24 | 25 | 27 |
28 |
29 | 30 | 32 |
33 |
34 | 35 | 37 |
38 |
39 | 40 | 42 |
43 | 44 |
45 | 46 | 48 |
49 |
50 |
51 | 53 |
54 |
55 |
56 |
57 |
58 |
59 |
-------------------------------------------------------------------------------- /src/websrc/html/PAGE_ROOT.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
Device status
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
Operational mode:
Ethernet connected:
Socket client connected:
WiFi Client enabled:
WiFi Client status:
WiFi Access Point enabled:
WiFi Access Point status:
Device Uptime:
Socket uptime:
48 |
49 |
50 |
51 |
52 |
53 |
Device information
54 |
55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 |
Zig-Star model:
ESP32 fw ver:
ESP32 hw version:
ESP32 temperature: °C
ESP32 frequency: cores @ MHz
ESP32 flash size: Mb,
ESP32 heap (free / total): / KiB
CC2652P hw version:
CC2652P fw rev:
Hostname:
103 |
104 |
105 |
106 |
107 |
108 |
Ethernet
109 |
110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 |
Connection status:
DHCP:
IP address:
Subnet mask:
Default gateway:
Connection speed:
MAC address:
142 |
143 |
144 |
145 |
146 |
147 |
WiFi
148 |
149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
Mode:
SSID:
IP address:
Subnet mask:
Default gateway:
RSSI:
MAC address:
181 |
182 |
183 |
184 |
185 |
186 |
VPN
187 |
188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 |
Initialized:
Local IP address:
Endpoint address:
204 |
205 |
206 |
207 |
208 |
-------------------------------------------------------------------------------- /src/websrc/html/PAGE_SECURITY.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
Security options
5 |
6 |
7 |
8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
-------------------------------------------------------------------------------- /src/websrc/html/PAGE_SERIAL.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
Serial options
6 |
7 |
8 |
9 |
10 | 11 | 18 |
19 |
20 |
21 |
22 | 23 | 25 |
26 |
27 |
28 |
29 |
30 | 32 |
33 |
34 |
35 |
36 |
37 | 38 |
39 |
41 | 42 | Config generator
43 |
44 |
45 |
46 |
47 | 52 | 69 | 70 | 75 |
76 |
77 |
78 |
79 |
80 |
-------------------------------------------------------------------------------- /src/websrc/html/PAGE_WG.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
WireGuard options
7 |
8 |
9 | 11 | 12 |
13 |
14 | 15 | 17 |
18 |
19 | 20 | 22 |
23 |
24 | 25 | 27 |
28 |
29 | 30 | 32 |
33 |
34 | 35 | 37 |
38 |
39 | 41 |
42 |
43 |
44 |
45 |
46 |
47 |
-------------------------------------------------------------------------------- /src/websrc/html/PAGE_WIFI.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
Wifi Setup
5 |
6 |
7 |
8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 28 | 29 | 30 | 36 | 37 | 38 |
SSIDSecurityChannelRSSI
21 |
22 |
26 |
27 |
31 |
32 | 34 |
35 |
39 |
40 |
41 |
42 | 43 | 45 |
46 |
47 | 48 | 51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | 61 | 62 |
63 |
64 |
65 | 66 | 68 |
69 |
70 | 71 | 73 |
74 |
75 | 76 | 78 |
79 |
80 |
81 |
82 |
83 | 85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
-------------------------------------------------------------------------------- /src/websrc/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codm/czc-firmware/b33f581bccd5c7e876616fb3a36458f28ad36099/src/websrc/img/favicon.ico -------------------------------------------------------------------------------- /src/websrc/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codm/czc-firmware/b33f581bccd5c7e876616fb3a36458f28ad36099/src/websrc/img/logo.png -------------------------------------------------------------------------------- /src/zb.h: -------------------------------------------------------------------------------- 1 | void clearS2Buffer(); 2 | void getZbVer(); 3 | void zbCheck(); 4 | // void getZbChip(); 5 | void zbLedToggle(); 6 | void checkFwHex(const char *tempFile); 7 | void zbInit(); 8 | -------------------------------------------------------------------------------- /tools/.version_no_increment: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codm/czc-firmware/b33f581bccd5c7e876616fb3a36458f28ad36099/tools/.version_no_increment -------------------------------------------------------------------------------- /tools/build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from subprocess import call 3 | Import("env") 4 | import shutil 5 | import os 6 | import time 7 | from glob import glob 8 | 9 | def after_build(source, target, env): 10 | time.sleep(2) 11 | shutil.copy(firmware_source, 'bin/firmware.bin') 12 | for f in glob ('bin/CZC-1.0*.bin'): 13 | os.unlink (f) 14 | 15 | exit_code = call("python tools/merge_bin_esp.py --output_folder ./bin --output_name CZC-1.0.bin --bin_path bin/bootloader_dio_40m.bin bin/firmware.bin bin/partitions.bin --bin_address 0x1000 0x10000 0x8000", shell=True) 16 | 17 | VERSION_FILE = 'tools/version' 18 | try: 19 | with open(VERSION_FILE) as FILE: 20 | VERSION_NUMBER = FILE.readline() 21 | except: 22 | print('No version file found') 23 | VERSION_NUMBER = '0.0.0' 24 | 25 | NEW_NAME_FULL = 'bin/CZC-1.0_v'+VERSION_NUMBER+'.full.bin' 26 | NEW_NAME = 'bin/CZC-1.0.bin' 27 | 28 | shutil.move('bin/CZC-1.0.bin', NEW_NAME_FULL) 29 | shutil.move('bin/firmware.bin', NEW_NAME) 30 | 31 | print('') 32 | print('--------------------------------------------------------') 33 | print('{} created with success !'.format(str(NEW_NAME_FULL))) 34 | print('{} created with success !'.format(str(NEW_NAME))) 35 | print('--------------------------------------------------------') 36 | print('') 37 | 38 | env.AddPostAction("buildprog", after_build) 39 | 40 | firmware_source = os.path.join(env.subst("$BUILD_DIR"), "firmware.bin") -------------------------------------------------------------------------------- /tools/commit.sh: -------------------------------------------------------------------------------- 1 | git add -A 2 | git commit -F ../commit.md 3 | version=$(cat version) 4 | git tag "v$version" 5 | git push 6 | git push origin "v$version" -------------------------------------------------------------------------------- /tools/debug_build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from subprocess import call 3 | Import("env") 4 | import shutil 5 | import os 6 | from glob import glob 7 | 8 | def after_build(source, target, env): 9 | 10 | shutil.copy(firmware_source, 'bin/firmware.bin') 11 | for f in glob ('bin/CZC-1.0*.debug.bin'): 12 | os.unlink (f) 13 | 14 | VERSION_FILE = 'tools/version' 15 | try: 16 | with open(VERSION_FILE) as FILE: 17 | VERSION_NUMBER = FILE.readline() 18 | except: 19 | print('No version file found') 20 | VERSION_NUMBER = '0.0.0' 21 | 22 | NEW_NAME = 'bin/CZC-1.0_v'+VERSION_NUMBER+'.debug.bin' 23 | 24 | shutil.move('bin/firmware.bin', NEW_NAME) 25 | 26 | print('') 27 | print('--DEBUG--DEBUG--DEBUG--DEBUG--DEBUG--DEBUG--DEBUG--') 28 | print('{} created with success !'.format(str(NEW_NAME))) 29 | print('--DEBUG--DEBUG--DEBUG--DEBUG--DEBUG--DEBUG--DEBUG--') 30 | print('') 31 | 32 | env.AddPostAction("buildprog", after_build) 33 | 34 | firmware_source = os.path.join(env.subst("$BUILD_DIR"), "firmware.bin") -------------------------------------------------------------------------------- /tools/flash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | python esptool.py --port "/dev/cu.usbserial-0001" erase_flash 3 | python esptool.py --port "/dev/cu.usbserial-0001" --baud 460800 write_flash --verify -z --flash_mode dio --flash_freq 40m --flash_size detect 0x0 ../bin/CZC-1.0*.full.bin 4 | 5 | #python esptool.py --port "/dev/cu.usbserial-0001" --baud 460800 write_flash --verify -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader_dio_40m.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 UZG-01*.bin 6 | -------------------------------------------------------------------------------- /tools/make_git_hook.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Add git.hook to remove .version_no_increment file before commit 4 | 5 | cd .. 6 | echo "python ./tools/version_increment_post.py" > ./.git/hooks/pre-commit 7 | chmod +x ./.git/hooks/pre-commit 8 | -------------------------------------------------------------------------------- /tools/merge_bin_esp.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | class bin(): 5 | def __init__(self, file_path, addr): 6 | self.file_path = file_path 7 | self.file_name = os.path.basename(file_path) 8 | self.addr = addr 9 | self.size = self.get_size() 10 | 11 | def get_size(self): 12 | return int(os.path.getsize(self.file_path)) 13 | 14 | class multiple_bin(): 15 | def __init__(self, name, output_folder): 16 | self.name = name 17 | self.output_folder = output_folder 18 | try: 19 | os.makedirs(os.path.realpath(self.output_folder)) 20 | except: 21 | pass 22 | self.output_path = os.path.realpath(os.path.join(self.output_folder,self.name)) 23 | self.bin_array = [] 24 | 25 | def add_bin(self, file_path, addr): 26 | self.bin_array.append(bin(file_path, addr)) 27 | 28 | def sort_bin(self): 29 | swapped = True 30 | while swapped: 31 | swapped = False 32 | for i in range(len(self.bin_array) - 1): 33 | if self.bin_array[i].addr > self.bin_array[i + 1].addr: 34 | self.bin_array[i], self.bin_array[i + 1] = self.bin_array[i + 1], self.bin_array[i] 35 | swapped = True 36 | 37 | def add_bin_to_other_bin(self, previous, binary): 38 | with open(self.output_path, "ab") as output_file: 39 | output_file.write( b'\xff' * (binary.addr-previous)) 40 | print ("Add %s from 0x%x to 0x%x (0x%x)"%(binary.file_name, binary.addr, binary.addr+binary.size, binary.size)) 41 | with open(self.output_path, "ab") as output_file, open(binary.file_path, "rb") as bin_file: 42 | output_file.write(bin_file.read()) 43 | return binary.addr+binary.size 44 | 45 | def create_bin(self): 46 | new_start = 0 47 | open(self.output_path, "wb").close 48 | for b in self.bin_array: 49 | new_start = self.add_bin_to_other_bin(new_start, b) 50 | 51 | def check_if_possible(self): 52 | for i in range(1, len(self.bin_array)): 53 | if(self.bin_array[i].addr < (self.bin_array[i-1].addr+self.bin_array[i-1].size)): 54 | print (self.bin_array[i].addr, (self.bin_array[i-1].addr+self.bin_array[i-1].size)) 55 | raise Exception("Not possible to create this bin, overlapping between %s and %s"%(self.bin_array[i].file_name, self.bin_array[i-1].file_name)) 56 | 57 | def main(): 58 | parser = argparse.ArgumentParser(description='Script to merge *.bin file at different position') 59 | parser.add_argument( 60 | '--output_name', 61 | help = 'Output file name', default = "output.bin") 62 | parser.add_argument( 63 | '--output_folder', default = "output", 64 | help = 'Output folder path') 65 | parser.add_argument( 66 | '--input_folder', default = "", 67 | help = 'Input folder path') 68 | parser.add_argument( 69 | '--bin_path',nargs='+',required=True, 70 | help = 'List of bin path, same order as bin_address (space seperated)') 71 | parser.add_argument( 72 | '--bin_address',nargs='+',type=lambda x: int(x,0),required=True, 73 | help = 'List of addr, same order as bin_path (space seperated)') 74 | parser.add_argument 75 | args = parser.parse_args() 76 | mb = multiple_bin(args.output_name, args.output_folder) 77 | for path,address in zip(args.bin_path, args.bin_address): 78 | mb.add_bin(os.path.join(args.input_folder, path), address) 79 | mb.sort_bin() 80 | mb.check_if_possible() 81 | mb.create_bin() 82 | print ("%s generated with success ! (size %u)"%(args.output_name, int(os.path.getsize(mb.output_path)))) 83 | 84 | if __name__ == "__main__": 85 | exit(main()) -------------------------------------------------------------------------------- /tools/version: -------------------------------------------------------------------------------- 1 | 1.0.0 -------------------------------------------------------------------------------- /tools/version_increment_post.py: -------------------------------------------------------------------------------- 1 | """ Remove version increment guard file if present """ 2 | import os 3 | 4 | if os.path.exists("tools/.version_no_increment"): 5 | os.remove("tools/.version_no_increment") 6 | 7 | # Copyright (C) 2020 Davide Perini 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 10 | # this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in 17 | # all copies or substantial portions of the Software. 18 | # 19 | # You should have received a copy of the MIT License along with this program. 20 | # If not, see . 21 | # -------------------------------------------------------------------------------- /tools/version_increment_pre.py: -------------------------------------------------------------------------------- 1 | """ Create version header and tracker file if missing """ 2 | import datetime 3 | import os 4 | 5 | Import("env") 6 | 7 | ## DO NOT EDIT THIS FILE, edit version file if you want to start from a different version 8 | # 9 | # version_increment_pre.py - Simple versioning script for Platformio 10 | # 11 | # Copyright (C) 2020 Davide Perini 12 | # 13 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 14 | # this software and associated documentation files (the "Software"), to deal 15 | # in the Software without restriction, including without limitation the rights 16 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | # copies of the Software, and to permit persons to whom the Software is 18 | # furnished to do so, subject to the following conditions: 19 | # 20 | # The above copyright notice and this permission notice shall be included in 21 | # all copies or substantial portions of the Software. 22 | # 23 | # You should have received a copy of the MIT License along with this program. 24 | # If not, see . 25 | # 26 | 27 | VERSION_FILE = 'tools/version' 28 | VERSION_HEADER = 'version.h' 29 | VERSION_PREFIX = '0.1.' 30 | VERSION_PATCH_NUMBER = 0 31 | 32 | if not os.path.exists("tools/.version_no_increment"): 33 | try: 34 | with open(VERSION_FILE) as FILE: 35 | VERSION_PATCH_NUMBER = FILE.readline() 36 | VERSION_PREFIX = VERSION_PATCH_NUMBER[0:VERSION_PATCH_NUMBER.rindex('.')+1] 37 | VERSION_PATCH_NUMBER = int(VERSION_PATCH_NUMBER[VERSION_PATCH_NUMBER.rindex('.')+1:]) 38 | if not os.path.exists("tools/.version_no_increment_update_date"): 39 | VERSION_PATCH_NUMBER = VERSION_PATCH_NUMBER + 1 40 | except: 41 | print('No version file found or incorrect data in it. Starting from 0.1.0') 42 | VERSION_PATCH_NUMBER = 0 43 | with open(VERSION_FILE, 'w+') as FILE: 44 | FILE.write(VERSION_PREFIX + str(VERSION_PATCH_NUMBER)) 45 | print('Build number: {}'.format(VERSION_PREFIX + str(VERSION_PATCH_NUMBER))) 46 | 47 | HEADER_FILE = """ 48 | // AUTO GENERATED FILE, DO NOT EDIT 49 | #ifndef VERSION 50 | #define VERSION "{}" 51 | #endif 52 | #ifndef BUILD_TIMESTAMP 53 | #define BUILD_TIMESTAMP "{}" 54 | #endif 55 | """.format(VERSION_PREFIX + str(VERSION_PATCH_NUMBER), datetime.datetime.now()) 56 | 57 | if os.environ.get('PLATFORMIO_INCLUDE_DIR') is not None: 58 | VERSION_HEADER = os.environ.get('PLATFORMIO_INCLUDE_DIR') + os.sep + VERSION_HEADER 59 | elif os.path.exists("src"): 60 | VERSION_HEADER = "src" + os.sep + VERSION_HEADER 61 | else: 62 | PROJECT_DIR = env.subst("$PROJECT_DIR") 63 | os.mkdir(PROJECT_DIR + os.sep + "include") 64 | VERSION_HEADER = "include" + os.sep + VERSION_HEADER 65 | 66 | with open(VERSION_HEADER, 'w+') as FILE: 67 | FILE.write(HEADER_FILE) 68 | 69 | open('tools/.version_no_increment', 'a').close() 70 | else: 71 | if os.path.exists("tools/version"): 72 | FILE = open(VERSION_FILE) 73 | VERSION_NUMBER = FILE.readline() 74 | print('Build number: {} (waiting for upload before next increment)'.format(str(VERSION_NUMBER))) 75 | else: 76 | print('No version file found or incorrect data in it!!') 77 | -------------------------------------------------------------------------------- /tools/webfilesbuilder/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | .no_web_update* -------------------------------------------------------------------------------- /tools/webfilesbuilder/buildWeb.bat: -------------------------------------------------------------------------------- 1 | echo off 2 | :build 3 | node gulp.js 4 | Title "UZG-01 webfiles builder" 5 | echo Press any key for build again or close window 6 | pause 7 | goto build 8 | -------------------------------------------------------------------------------- /tools/webfilesbuilder/build_html.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | Import("env") 4 | import os 5 | 6 | if not os.path.exists("tools/webfilesbuilder/.no_web_update"): 7 | 8 | print("Try to build HMTL gzip files") 9 | 10 | try: 11 | os.mkdir('./src/webh') 12 | except OSError as error: 13 | print(error) 14 | 15 | os.chdir('./tools/webfilesbuilder/') 16 | 17 | 18 | cwd = os.getcwd() 19 | print("{0}".format(cwd)) 20 | 21 | env.Execute("npm install") 22 | 23 | env.Execute("npx gulp") 24 | -------------------------------------------------------------------------------- /tools/webfilesbuilder/gulp.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-path-concat */ 2 | 3 | 'use strict'; 4 | 5 | var path = require('path'); 6 | process.env.NODE_PATH = (process.env.NODE_PATH || '').split(path.delimiter) 7 | .filter((p) => p).concat(__dirname + '/node_modules').join(path.delimiter); 8 | require('module')._initPaths(); // eslint-disable-line no-underscore-dangle 9 | 10 | require('gulp'); 11 | require('gulp-concat'); 12 | require('gulp/bin/gulp.js'); 13 | require('fs'); 14 | require('gulp-gzip'); 15 | require('gulp-flatmap'); 16 | require('path'); 17 | require('gulp-htmlmin'); 18 | require('gulp-uglify'); 19 | require('pump'); -------------------------------------------------------------------------------- /tools/webfilesbuilder/gulp.meta.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function () { 4 | return { 5 | packages: [ 'gulp-concat', 'gulp-htmlmin', 'gulp-flatmap', 'gulp-gzip', 'gulp-uglify', 'fs', 'path', 'pump'], 6 | deployFiles: [ 'gulpfile.js' ], 7 | take: 'last-line' 8 | }; 9 | }; -------------------------------------------------------------------------------- /tools/webfilesbuilder/gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var fs = require('fs'); 3 | var concat = require('gulp-concat'); 4 | var gzip = require('gulp-gzip'); 5 | var flatmap = require('gulp-flatmap'); 6 | var path = require('path'); 7 | var htmlmin = require('gulp-htmlmin'); 8 | var uglify = require('gulp-uglify'); 9 | var pump = require('pump'); 10 | 11 | function stylesConcat() { 12 | return gulp.src(['../../src/websrc/css/bootstrap.min.css', '../../src/websrc/css/style.css']) 13 | .pipe(concat({ 14 | path: 'required.css', 15 | stat: { 16 | mode: 0666 17 | } 18 | })) 19 | .pipe(gulp.dest('../../src/websrc/css/')) 20 | .pipe(gzip({ 21 | append: true 22 | })) 23 | .pipe(gulp.dest('../../src/websrc/gzipped/css/')); 24 | } 25 | 26 | function styles(cb) { 27 | var source = "../../src/websrc/gzipped/css/" + "required.css.gz"; 28 | var destination = "../../src/webh/" + "required.css.gz.h"; 29 | 30 | var wstream = fs.createWriteStream(destination); 31 | wstream.on('error', function (err) { 32 | console.log(err); 33 | }); 34 | 35 | var data = fs.readFileSync(source); 36 | 37 | wstream.write('#define required_css_gz_len ' + data.length + '\n'); 38 | wstream.write('const uint8_t required_css_gz[] PROGMEM = {') 39 | 40 | for (i=0; i