From ea37c38de2671087f5ef0f1d762ea6bc80c778ee Mon Sep 17 00:00:00 2001 From: JeremyTubongbanua Date: Mon, 21 Aug 2023 19:48:26 -0400 Subject: [PATCH] docs: lots of examples and docs --- README.md | 117 +----------------- examples/atclient_esp32/CMakeLists.txt | 10 -- examples/atclient_esp32/main/main.c | 74 ----------- examples/atclient_esp32_source/CMakeLists.txt | 10 ++ examples/atclient_esp32_source/README.md | 37 ++++++ .../include/atchops/aes_ctr.h | 0 .../include/atchops/base64.h | 0 .../include/atchops/rsa.h | 0 .../include/atchops/sha.h | 0 .../include/atclient/at_logger.h | 0 .../include/atclient/atkeys_filereader.h | 0 .../include/atclient/connection.h | 0 .../atclient_esp32_source/lib/libatchops.a | Bin 0 -> 74694 bytes .../atclient_esp32_source/lib/libatclient.a | Bin 0 -> 81640 bytes .../atclient_esp32_source/main/CMakeLists.txt | 4 + examples/atclient_esp32_source/main/main.c | 28 +++++ .../CMakeLists.txt | 5 + .../README.md | 91 ++++++++++++++ .../components/atchops/CMakeLists.txt | 7 ++ .../atchops/include/atchops/aes_ctr.h | 31 +++++ .../atchops/include/atchops/base64.h | 25 ++++ .../components/atchops/include/atchops/rsa.h | 84 +++++++++++++ .../components/atchops/include/atchops/sha.h | 14 +++ .../components/atchops}/lib/libatchops.a | Bin .../components/atclient/CMakeLists.txt | 7 ++ .../atclient/include/atclient/at_logger.h | 9 ++ .../include/atclient/atkeys_filereader.h | 59 +++++++++ .../atclient/include/atclient/connection.h | 59 +++++++++ .../components/atclient}/lib/libatclient.a | Bin 81616 -> 81616 bytes .../main/CMakeLists.txt | 2 +- .../main/main.c | 28 +++++ .../CMakeLists.txt | 5 + .../main/CMakeLists.txt | 11 ++ .../main/atchops/CMakeLists.txt | 7 ++ .../main/atchops/include/atchops/aes_ctr.h | 31 +++++ .../main/atchops/include/atchops/base64.h | 25 ++++ .../main/atchops/include/atchops/rsa.h | 84 +++++++++++++ .../main/atchops/include/atchops/sha.h | 14 +++ .../main/atchops/lib/libatchops.a | Bin 0 -> 74662 bytes .../main/atclient/CMakeLists.txt | 7 ++ .../atclient/include/atclient/at_logger.h | 9 ++ .../include/atclient/atkeys_filereader.h | 59 +++++++++ .../atclient/include/atclient/connection.h | 59 +++++++++ .../main/atclient/lib/libatclient.a | Bin 0 -> 81616 bytes .../main/main.c | 28 +++++ 45 files changed, 844 insertions(+), 196 deletions(-) delete mode 100644 examples/atclient_esp32/CMakeLists.txt delete mode 100644 examples/atclient_esp32/main/main.c create mode 100644 examples/atclient_esp32_source/CMakeLists.txt create mode 100644 examples/atclient_esp32_source/README.md rename examples/{atclient_esp32 => atclient_esp32_source}/include/atchops/aes_ctr.h (100%) rename examples/{atclient_esp32 => atclient_esp32_source}/include/atchops/base64.h (100%) rename examples/{atclient_esp32 => atclient_esp32_source}/include/atchops/rsa.h (100%) rename examples/{atclient_esp32 => atclient_esp32_source}/include/atchops/sha.h (100%) rename examples/{atclient_esp32 => atclient_esp32_source}/include/atclient/at_logger.h (100%) rename examples/{atclient_esp32 => atclient_esp32_source}/include/atclient/atkeys_filereader.h (100%) rename examples/{atclient_esp32 => atclient_esp32_source}/include/atclient/connection.h (100%) create mode 100644 examples/atclient_esp32_source/lib/libatchops.a create mode 100644 examples/atclient_esp32_source/lib/libatclient.a create mode 100644 examples/atclient_esp32_source/main/CMakeLists.txt create mode 100644 examples/atclient_esp32_source/main/main.c create mode 100644 examples/atclient_esp32_static_components/CMakeLists.txt create mode 100644 examples/atclient_esp32_static_components/README.md create mode 100644 examples/atclient_esp32_static_components/components/atchops/CMakeLists.txt create mode 100644 examples/atclient_esp32_static_components/components/atchops/include/atchops/aes_ctr.h create mode 100644 examples/atclient_esp32_static_components/components/atchops/include/atchops/base64.h create mode 100644 examples/atclient_esp32_static_components/components/atchops/include/atchops/rsa.h create mode 100644 examples/atclient_esp32_static_components/components/atchops/include/atchops/sha.h rename examples/{atclient_esp32 => atclient_esp32_static_components/components/atchops}/lib/libatchops.a (100%) create mode 100644 examples/atclient_esp32_static_components/components/atclient/CMakeLists.txt create mode 100644 examples/atclient_esp32_static_components/components/atclient/include/atclient/at_logger.h create mode 100644 examples/atclient_esp32_static_components/components/atclient/include/atclient/atkeys_filereader.h create mode 100644 examples/atclient_esp32_static_components/components/atclient/include/atclient/connection.h rename examples/{atclient_esp32 => atclient_esp32_static_components/components/atclient}/lib/libatclient.a (95%) rename examples/{atclient_esp32 => atclient_esp32_static_components}/main/CMakeLists.txt (58%) create mode 100644 examples/atclient_esp32_static_components/main/main.c create mode 100644 examples/atclient_esp32_static_no_components/CMakeLists.txt create mode 100644 examples/atclient_esp32_static_no_components/main/CMakeLists.txt create mode 100644 examples/atclient_esp32_static_no_components/main/atchops/CMakeLists.txt create mode 100644 examples/atclient_esp32_static_no_components/main/atchops/include/atchops/aes_ctr.h create mode 100644 examples/atclient_esp32_static_no_components/main/atchops/include/atchops/base64.h create mode 100644 examples/atclient_esp32_static_no_components/main/atchops/include/atchops/rsa.h create mode 100644 examples/atclient_esp32_static_no_components/main/atchops/include/atchops/sha.h create mode 100644 examples/atclient_esp32_static_no_components/main/atchops/lib/libatchops.a create mode 100644 examples/atclient_esp32_static_no_components/main/atclient/CMakeLists.txt create mode 100644 examples/atclient_esp32_static_no_components/main/atclient/include/atclient/at_logger.h create mode 100644 examples/atclient_esp32_static_no_components/main/atclient/include/atclient/atkeys_filereader.h create mode 100644 examples/atclient_esp32_static_no_components/main/atclient/include/atclient/connection.h create mode 100644 examples/atclient_esp32_static_no_components/main/atclient/lib/libatclient.a create mode 100644 examples/atclient_esp32_static_no_components/main/main.c diff --git a/README.md b/README.md index 6c13db72..ac25df45 100644 --- a/README.md +++ b/README.md @@ -8,124 +8,19 @@ ## Packages -- `atchops` stands for cryptographic and hashing operations catered for the atProtocol, uses [MbedTLS crypto](https://github.com/Mbed-TLS/mbedtls) as a dependency. -- `atclient` is the core dependency for anything Atsign technology related. atclient depends on [atchops](./packages/atchops/README.md) and [MbedTLS](https://github.com/Mbed-TLS/mbedtls) -- `repl` is a demo application using atclient +- [atchops](./packages/atchops/README.md) stands for cryptographic and hashing operations catered for the atProtocol, uses [MbedTLS crypto](https://github.com/Mbed-TLS/mbedtls) as a dependency. +- [atclient](./packages/atclient/README.md) is the core dependency for anything Atsign technology related. atclient depends on [atchops](./packages/atchops/README.md) and [MbedTLS](https://github.com/Mbed-TLS/mbedtls) +- [atclient_espidf](./packages/atclient_espidf/README.md) -## Building Source +## Examples -To build the source code you will need to have [CMake](https://cmake.org/) installed. - -Most of the following steps will work with `atchops` and `atclient`: - -- [Installing on Linux/MacOS](#installing-on-linuxmacos) -- [Running Tests on Linux/MacOS](#running-tests-on-linuxmacos) -- [Installing on Windows](#installing-on-windows) - -### Installing on Linux/MacOS - -1. Get ahold of the source code either via git clone or from downloading the source from our releases: - -```sh -git clone https://github.com/atsign-foundation/at_c.git -cd at_c/packages/atclient -``` - -2. CMake configure - -```sh -cmake -S . -B build -``` - -Alternatively, if you have installed MbedTLS and/or AtChops from source already, you can avoid fetching it everytime with `ATCLIENT_FETCH_MBEDTLS=OFF` and `ATCLIENT_FETCH_ATCHOPS=OFF` respectively. Doing this drastically reduces the time it takes to configure the project: - -```sh -cmake -S . -B build -DATCLIENT_FETCH_MBEDTLS=OFF -DATCLIENT_FETCH_ATCHOPS=OFF -``` - -3. Install - -```sh -cmake --build build --target install -``` - -4. Building the source code will allow you to use the `atclient` library in your own CMake projects: - -```cmake -find_package(atclient REQUIRED CONFIG) -target_link_libraries(myproj PRIVATE atclient::atclient) -``` - -### Running Tests on Linux/MacOS - -1. Get ahold of the source code either via git clone or from downloading the source from our releases: - -```sh -git clone https://github.com/atsign-foundation/at_c.git -cd at_c/packages/atclient -``` - -2. CMake configure with `-DATCLIENT_BUILD_TESTS=ON` - -```sh -cmake -S . -B build -DATCLIENT_BUILD_TESTS=ON -``` - -3. Build (target is all by default) - -```sh -cmake --build build -``` - -4. Run tests - -```sh -cd build/tests && ctest -V --output-on-failure --timeout 10 -``` - -`--timeout 10` times out tests after 10 seconds - -### Installing on Windows - -Coming Soon! +- [repl](./examples/repl/README.md) is a command line interface for interacting with the atProtocol. Works on Desktop Linux/MacOS. ## Contributing Read [CONTRIBUTING.md](./CONTRIBUTING.md) for information on how to properly fork and open a pull request. -When creating - -- [Creating Tests](#creating-tests) -- [Adding New Source Files](#adding-new-source-files) -- [Adding New Include Headers](#adding-new-include-headers) - -### Creating Tests - -If you want to add a test in atclient, simply add a `test_*.c` file in the `tests` directory. CMake will automatically detect it and add it to the test suite. Ensure that the test file is named `test_*.c` or else it will not be detected. - -Ensure the file has a `int main(int argc, char **argv)` function and returns 0 on success and not 0 on failure. - -### Adding New Source Files - -This one is a little more tricky. Adding a new source file to the project requires a few steps: - -Add the source file to the `CMakeLists.txt` file in the `src` directory. This is so that CMake knows to compile the file. - -Example: - -```cmake -target_sources(atclient PRIVATE - ... - ${CMAKE_CURRENT_LIST_DIR}/src/folder/new_file.c - ... -) -``` - -### Adding New Include Headers - -Simply add the header inside of the `include/` directory. CMake will automatically detect it and add it to the include path. - -If it is added in a subdirectory (like `include/atclient/`), then the include path will be `atclient/` (e.g. `#include `) +When creating source files, include headers, or tests to certain packages, please follow the documentation in their according README files. ## Maintainers diff --git a/examples/atclient_esp32/CMakeLists.txt b/examples/atclient_esp32/CMakeLists.txt deleted file mode 100644 index e98bb22e..00000000 --- a/examples/atclient_esp32/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -cmake_minimum_required(VERSION 3.19) - -set(EXTRA_COMPONENT_DIRS - ${CMAKE_SOURCE_DIR}/../../packages/atclient - ${CMAKE_SOURCE_DIR}/../../packages/atchops -) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) - -project(atclient_esp32) \ No newline at end of file diff --git a/examples/atclient_esp32/main/main.c b/examples/atclient_esp32/main/main.c deleted file mode 100644 index 7caafa31..00000000 --- a/examples/atclient_esp32/main/main.c +++ /dev/null @@ -1,74 +0,0 @@ - -#include -#include -#include -#include -#include "atclient/connection.h" - -#define ATSIGN "@jeremy_0" - -static void *without_at_symbol(const char *atsign, char *buf) -{ - int i = 0; - while (atsign[i] != '\0') - { - buf[i] = atsign[i + 1]; - i++; - } - buf[i] = '\0'; - return buf; -} - -void app_main(void) -{ - esp_wifi_set_mode(WIFI_MODE_STA); - - // 1. initialize buffer to use throughout program - size_t recvlen = 32768; - unsigned char *recv = malloc(sizeof(unsigned char) * recvlen); - size_t olen = 0; - - // 2. connect to root and find secondary address - - // 2a. establish connection to root - atclient_connection_ctx root_connection; - atclient_connection_init(&root_connection); - atclient_connection_connect(&root_connection, "root.atsign.org", 64); - printf("Connected to root\n"); - - // 2b. send atsign without @ symbol to root - - char *atsign_without_at = malloc(sizeof(char) * 100); - memset(atsign_without_at, 0, 100); - without_at_symbol(ATSIGN, atsign_without_at); - strcat(atsign_without_at, "\r\n"); - size_t atsign_without_atlen = strlen(atsign_without_at); - - printf("Sending to root: \"%s\"\n", atsign_without_at); - atclient_connection_send(&root_connection, recv, recvlen, &olen, (unsigned char *)atsign_without_at, atsign_without_atlen); - printf("Received from root: \"%.*s\"\n", (int)olen, recv); - - // 2c. parse secondary address - const size_t secondary_len = 100; - char *secondary_host = malloc(sizeof(char) * secondary_len); - char *secondary_port = malloc(sizeof(char) * secondary_len); - - int i = 0, c; - while ((c = recv[i]) != ':' && i < olen) - { - secondary_host[i] = c; - i++; - } - secondary_host[i] = '\0'; - i++; - int j = 0; - while ((c = recv[i]) != '\0' && i < olen) - { - secondary_port[j] = c; - i++; - j++; - } - - printf("secondary_host: %s\n", secondary_host); - printf("secondary_port: %s\n", secondary_port); -} \ No newline at end of file diff --git a/examples/atclient_esp32_source/CMakeLists.txt b/examples/atclient_esp32_source/CMakeLists.txt new file mode 100644 index 00000000..33043421 --- /dev/null +++ b/examples/atclient_esp32_source/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.19) + +set(EXTRA_COMPONENT_DIRS + ${CMAKE_SOURCE_DIR}/../../packages/atclient # match this to be the path to the root CMakeLists.txt of atclient package + ${CMAKE_SOURCE_DIR}/../../packages/atchops # match this to be the path to the root CMakeLists.txt of atchops package +) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(atclient_esp32_source) \ No newline at end of file diff --git a/examples/atclient_esp32_source/README.md b/examples/atclient_esp32_source/README.md new file mode 100644 index 00000000..69f5c2bb --- /dev/null +++ b/examples/atclient_esp32_source/README.md @@ -0,0 +1,37 @@ +# atclient_esp32_source + +This example shows you how to use atclient/atchops in your own ESP-IDF project by providing the path to the source code. + +## How to Consume Via Source Code + +In `make/CMakeLists.txt`, be sure to add the atclient and atchops components to the REQUIRES list: + +```cmake +idf_component_register( + SRCS "main.c" + REQUIRES mbedtls atclient atchops +) +``` + +In `./CMakeLists.txt`, add the path to the atclient and atchops source code via the EXTRA_COMPONENT_DIRS variable: + +```cmake +set(EXTRA_COMPONENT_DIRS + ${CMAKE_SOURCE_DIR}/../../packages/atclient # match this to be the path to the root CMakeLists.txt of atclient package + ${CMAKE_SOURCE_DIR}/../../packages/atchops # match this to be the path to the root CMakeLists.txt of atchops package +) +``` + +## Running the Example + +To run the example, you will need the ESP-IDF toolchain installed. See [ESP-IDF's Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) for more information. Ensure that your ESP32 is plugged into your computer with a micro USB data cable. + +Running the example via `get_idf && idf.py build && idf.py flash monitor` will give you something similar to: + +```sh +atchops_base64_encode: 0 +src: Lemonade! +dst: TGVtb25hZGUh +dst bytes: +54 47 56 74 62 32 35 68 5a 47 55 68 +``` \ No newline at end of file diff --git a/examples/atclient_esp32/include/atchops/aes_ctr.h b/examples/atclient_esp32_source/include/atchops/aes_ctr.h similarity index 100% rename from examples/atclient_esp32/include/atchops/aes_ctr.h rename to examples/atclient_esp32_source/include/atchops/aes_ctr.h diff --git a/examples/atclient_esp32/include/atchops/base64.h b/examples/atclient_esp32_source/include/atchops/base64.h similarity index 100% rename from examples/atclient_esp32/include/atchops/base64.h rename to examples/atclient_esp32_source/include/atchops/base64.h diff --git a/examples/atclient_esp32/include/atchops/rsa.h b/examples/atclient_esp32_source/include/atchops/rsa.h similarity index 100% rename from examples/atclient_esp32/include/atchops/rsa.h rename to examples/atclient_esp32_source/include/atchops/rsa.h diff --git a/examples/atclient_esp32/include/atchops/sha.h b/examples/atclient_esp32_source/include/atchops/sha.h similarity index 100% rename from examples/atclient_esp32/include/atchops/sha.h rename to examples/atclient_esp32_source/include/atchops/sha.h diff --git a/examples/atclient_esp32/include/atclient/at_logger.h b/examples/atclient_esp32_source/include/atclient/at_logger.h similarity index 100% rename from examples/atclient_esp32/include/atclient/at_logger.h rename to examples/atclient_esp32_source/include/atclient/at_logger.h diff --git a/examples/atclient_esp32/include/atclient/atkeys_filereader.h b/examples/atclient_esp32_source/include/atclient/atkeys_filereader.h similarity index 100% rename from examples/atclient_esp32/include/atclient/atkeys_filereader.h rename to examples/atclient_esp32_source/include/atclient/atkeys_filereader.h diff --git a/examples/atclient_esp32/include/atclient/connection.h b/examples/atclient_esp32_source/include/atclient/connection.h similarity index 100% rename from examples/atclient_esp32/include/atclient/connection.h rename to examples/atclient_esp32_source/include/atclient/connection.h diff --git a/examples/atclient_esp32_source/lib/libatchops.a b/examples/atclient_esp32_source/lib/libatchops.a new file mode 100644 index 0000000000000000000000000000000000000000..d7f89a82b1f77ad7897a9497ad2849684acfc06c GIT binary patch literal 74694 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 F{4Ylh@VNj0 literal 0 HcmV?d00001 diff --git a/examples/atclient_esp32_source/lib/libatclient.a b/examples/atclient_esp32_source/lib/libatclient.a new file mode 100644 index 0000000000000000000000000000000000000000..052923dd306883710e9116032d7e1f6c576cd0ea GIT binary patch literal 81640 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 literal 0 HcmV?d00001 diff --git a/examples/atclient_esp32_source/main/CMakeLists.txt b/examples/atclient_esp32_source/main/CMakeLists.txt new file mode 100644 index 00000000..9759a0d3 --- /dev/null +++ b/examples/atclient_esp32_source/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register( + SRCS "main.c" + REQUIRES mbedtls atclient atchops +) \ No newline at end of file diff --git a/examples/atclient_esp32_source/main/main.c b/examples/atclient_esp32_source/main/main.c new file mode 100644 index 00000000..da808d31 --- /dev/null +++ b/examples/atclient_esp32_source/main/main.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include "atchops/base64.h" + +void app_main(void) +{ + const char *src = "Lemonade!"; + unsigned long srclen = strlen(src); + + const unsigned long dstlen = 2048; + const unsigned char *dst = malloc(sizeof(unsigned char) * dstlen); + memset(dst, 0, dstlen); + unsigned long dstolen = 0; // written length + + int ret = atchops_base64_encode((const unsigned char *) src, srclen, dst, dstlen, &dstolen); + + printf("atchops_base64_encode: %d\n", ret); + + printf("src: %s\n", src); + printf("dst: %.*s\n", (int) dstolen, dst); + printf("dst bytes: \n"); + for(int i = 0; i < dstolen; i++) + { + printf("%02x ", *(dst + i)); + } + printf("\n"); +} \ No newline at end of file diff --git a/examples/atclient_esp32_static_components/CMakeLists.txt b/examples/atclient_esp32_static_components/CMakeLists.txt new file mode 100644 index 00000000..2f7f87a5 --- /dev/null +++ b/examples/atclient_esp32_static_components/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.19) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(atclient_esp32_static_components) \ No newline at end of file diff --git a/examples/atclient_esp32_static_components/README.md b/examples/atclient_esp32_static_components/README.md new file mode 100644 index 00000000..9aa42a1f --- /dev/null +++ b/examples/atclient_esp32_static_components/README.md @@ -0,0 +1,91 @@ +# atclient_esp32_static + +This is an example of how to use the built static libraries from [atclient_espidf](../../packages/atclient_espidf/README.md). + +## Consuming AtClient/AtChops as Static Libraries + +You will need to have built the static libraries from [atclient_espidf](../../packages/atclient_espidf/README.md) before you can consume them in your own project. + +Once you have that, be sure to create the following directories in your project: + +- `components/atclient` +- `components/atchops` + +And in each directory, create a CMakeLists.txt. + +`components/atclient/CMakeLists.txt`: + +```cmake +# register this directory as a component +idf_component_register() + +add_prebuilt_library(atclient ${CMAKE_CURRENT_LIST_DIR}/lib/libatclient.a REQUIRES mbedtls atchops) + +target_include_directories(atclient INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) +target_link_libraries(${COMPONENT_LIB} INTERFACE atclient) # add it to the component library +``` + +`components/atchops/CMakeLists.txt`: + +```cmake +# register this directory as a component +idf_component_register() + +add_prebuilt_library(atchops ${CMAKE_CURRENT_LIST_DIR}/lib/libatchops.a REQUIRES mbedtls) + +target_include_directories(atchops INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) +target_link_libraries(${COMPONENT_LIB} INTERFACE atchops) # add it to the component library +``` + +Then in your `main/CMakeLists.txt`, be sure to REQUIRE the atclient and atchops components: + +```cmake +idf_component_register( + SRCS "main.c" + REQUIRES atclient atchops +) +``` + +Your root project `./CMakeLists.txt` can remain the same as any regular ESP-IDF root CMakeLists.txt. + +```cmake +cmake_minimum_required(VERSION 3.19) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(atclient_esp32) +``` + +## Running this example + +This example requires the ESP-IDF toolchain to be installed. See [ESP-IDF's Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html) for more information. + +Ensure that your ESP32 is plugged into your computer with a micro USB data cable. + +1. Get IDF + +```sh +get_idf +``` + +2. Build + +```sh +idf.py build +``` + +3. Flash and Monitor to your ESP32 + +```sh +idf.py flash monitor +``` + +4. Your output will be similar to the following: + +```sh +atchops_base64_encode: 0 +src: Lemonade! +dst: TGVtb25hZGUh +dst bytes: +54 47 56 74 62 32 35 68 5a 47 55 68 +``` \ No newline at end of file diff --git a/examples/atclient_esp32_static_components/components/atchops/CMakeLists.txt b/examples/atclient_esp32_static_components/components/atchops/CMakeLists.txt new file mode 100644 index 00000000..c8b1c2dd --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atchops/CMakeLists.txt @@ -0,0 +1,7 @@ +# register this directory as a component +idf_component_register() + +add_prebuilt_library(atchops ${CMAKE_CURRENT_LIST_DIR}/lib/libatchops.a REQUIRES mbedtls) + +target_include_directories(atchops INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) +target_link_libraries(${COMPONENT_LIB} INTERFACE atchops) # add it to the component library \ No newline at end of file diff --git a/examples/atclient_esp32_static_components/components/atchops/include/atchops/aes_ctr.h b/examples/atclient_esp32_static_components/components/atchops/include/atchops/aes_ctr.h new file mode 100644 index 00000000..ca9eb607 --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atchops/include/atchops/aes_ctr.h @@ -0,0 +1,31 @@ +#pragma once + +typedef enum AESKeySize { + AES_128 = 128, // not tested + AES_192 = 192, // not tested + AES_256 = 256, +} AESKeySize; + +int atchops_aes_ctr_encrypt( + const char *keybase64, + const unsigned long keybase64len, + const AESKeySize keybits, + const unsigned char *iv, + const unsigned long ivlen, + const unsigned char *plaintext, + const unsigned long plaintextlen, + unsigned char *ciphertextbase64, + const unsigned long ciphertextbase64len, + unsigned long *ciphertextbase64olen); + +int atchops_aes_ctr_decrypt( + const char *keybase64, + const unsigned long keybase64len, + const AESKeySize keybits, + const unsigned char *iv, + const unsigned long ivlen, + const unsigned char *ciphertextbase64, + const unsigned long ciphertextbase64len, + unsigned char *plaintext, + const unsigned long plaintextlen, + unsigned long *plaintextolen); diff --git a/examples/atclient_esp32_static_components/components/atchops/include/atchops/base64.h b/examples/atclient_esp32_static_components/components/atchops/include/atchops/base64.h new file mode 100644 index 00000000..d1a9c227 --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atchops/include/atchops/base64.h @@ -0,0 +1,25 @@ +#pragma once + +/** + * @brief Base64 encode some bytes + * + * @param src src bytes that you want to encode + * @param srclen the length of the src bytes + * @param dst the buffer where the base64 encoded result will be + * @param dstlen the buffer length + * @param writtenlen the length of the result after operation + * @return int 0 on success + */ +int atchops_base64_encode(const unsigned char *src, const unsigned long srclen, unsigned char *dst, unsigned long dstlen, unsigned long *writtenlen); + +/** + * @brief Base64 decode some bytes + * + * @param src src bytes that you want to decode + * @param srclen the length of the src bytes + * @param dst the buffer where the base64 decoded result will be + * @param dstlen the buffer length + * @param writtenlen the length of the result after operation + * @return int 0 on success + */ +int atchops_base64_decode(const unsigned char *src, const unsigned long srclen, unsigned char *dst, unsigned long dstlen, unsigned long *writtenlen); diff --git a/examples/atclient_esp32_static_components/components/atchops/include/atchops/rsa.h b/examples/atclient_esp32_static_components/components/atchops/include/atchops/rsa.h new file mode 100644 index 00000000..bffb64b4 --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atchops/include/atchops/rsa.h @@ -0,0 +1,84 @@ +#pragma once + +#include "sha.h" + +typedef struct rsa_param +{ + unsigned long len; // length of the number in bytes + unsigned char *value; // hex byte array of the number +} rsa_param; + +typedef struct atchops_rsa_publickey +{ + rsa_param n; // modulus + rsa_param e; // public exponent +} atchops_rsa_publickey; + +typedef struct atchops_rsa_privatekey +{ + rsa_param n; // modulus + rsa_param e; // public exponent + rsa_param d; // private exponent + rsa_param p; // prime 1 + rsa_param q; // prime 2 +} atchops_rsa_privatekey; + +/** + * @brief Populate a public key struct from a base64 string + * + * @param publickeybase64 a base64 string representing an RSA 2048 Public Key + * @param publickeybase64len the length of the base64 string + * @param publickeystruct the public key struct to populate + * @return int 0 on success + */ +int atchops_rsa_populate_publickey(const char *publickeybase64, const unsigned long publickeybase64len, atchops_rsa_publickey *publickeystruct); + +/** + * @brief Populate a private key struct from a base64 string + * + * @param privatekeybase64 the base64 string representing an RSA 2048 Private Key + * @param privatekeybase64len the length of the base64 string + * @param privatekeystruct the private key struct to populate + * @return int 0 on success + */ +int atchops_rsa_populate_privatekey(const char *privatekeybase64, const unsigned long privatekeybase64len, atchops_rsa_privatekey *privatekeystruct); + +/** + * @brief Sign a message with an RSA private key + * + * @param privatekeystruct the private key struct to use for signing, see atchops_rsa_populate_privatekey + * @param mdtype the hash type to use, see atchops_md_type, e.g. ATCHOPS_MD_SHA256 + * @param message the message to sign + * @param messagelen the length of the message, most people use strlen() to find this length + * @param signature the signature buffer to populate + * @param signaturelen the length of the signature buffer + * @param signatureolen the length of the signature buffer after signing + * @return int 0 on success + */ +int atchops_rsa_sign(atchops_rsa_privatekey privatekeystruct, atchops_md_type mdtype, const unsigned char *message, const unsigned long messagelen, unsigned char *signature, const unsigned long signaturelen, unsigned long *signatureolen); + +/** + * @brief Encrypt bytes with an RSA public key + * + * @param publickeystruct the public key struct to use for encryption, see atchops_rsa_populate_publickey + * @param plaintext the plaintext to encrypt + * @param plaintextlen the length of the plaintext, most people use strlen() to find this length + * @param ciphertext the ciphertext buffer to populate + * @param ciphertextlen the length of the ciphertext buffer + * @param ciphertextolen the length of the ciphertext buffer after encryption + * @return int 0 on success + */ +int atchops_rsa_encrypt(atchops_rsa_publickey publickeystruct, const unsigned char *plaintext, const unsigned long plaintextlen, unsigned char *ciphertext, const unsigned long ciphertextlen, unsigned long *ciphertextolen); + +/** + * @brief Decrypt bytes with an RSA private key + * + * @param privatekeystruct the private key struct to use for decryption, see atchops_rsa_populate_privatekey + * @param ciphertextbase64 the ciphertext to decrypt, base64 encoded + * @param ciphertextbase64len the length of the ciphertext, most people use strlen() to find this length + * @param plaintext the plaintext buffer to populate + * @param plaintextlen the length of the plaintext buffer + * @param plaintextolen the length of the plaintext buffer after decryption + * @return int 0 on success + */ +int atchops_rsa_decrypt(atchops_rsa_privatekey privatekeystruct, const unsigned char *ciphertextbase64, const unsigned long ciphertextbase64len, unsigned char *plaintext, const unsigned long plaintextlen, unsigned long *plaintextolen); diff --git a/examples/atclient_esp32_static_components/components/atchops/include/atchops/sha.h b/examples/atclient_esp32_static_components/components/atchops/include/atchops/sha.h new file mode 100644 index 00000000..786522e5 --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atchops/include/atchops/sha.h @@ -0,0 +1,14 @@ +#pragma once + +typedef enum { + ATCHOPS_MD_NONE=0, /**< None. */ + ATCHOPS_MD_MD5, /**< The MD5 message digest. */ + ATCHOPS_MD_SHA1, /**< The SHA-1 message digest. */ + ATCHOPS_MD_SHA224, /**< The SHA-224 message digest. */ + ATCHOPS_MD_SHA256, /**< The SHA-256 message digest. */ + ATCHOPS_MD_SHA384, /**< The SHA-384 message digest. */ + ATCHOPS_MD_SHA512, /**< The SHA-512 message digest. */ + ATCHOPS_MD_RIPEMD160, +} atchops_md_type; + +int atchops_sha_hash(atchops_md_type mdtype, const unsigned char *input, const unsigned long inputlen, unsigned char *output, unsigned long outputlen, unsigned long *outputolen); diff --git a/examples/atclient_esp32/lib/libatchops.a b/examples/atclient_esp32_static_components/components/atchops/lib/libatchops.a similarity index 100% rename from examples/atclient_esp32/lib/libatchops.a rename to examples/atclient_esp32_static_components/components/atchops/lib/libatchops.a diff --git a/examples/atclient_esp32_static_components/components/atclient/CMakeLists.txt b/examples/atclient_esp32_static_components/components/atclient/CMakeLists.txt new file mode 100644 index 00000000..aa5eea58 --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atclient/CMakeLists.txt @@ -0,0 +1,7 @@ +# register this directory as a component +idf_component_register() + +add_prebuilt_library(atclient ${CMAKE_CURRENT_LIST_DIR}/lib/libatclient.a REQUIRES mbedtls atchops) + +target_include_directories(atclient INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) +target_link_libraries(${COMPONENT_LIB} INTERFACE atclient) # add it to the component library \ No newline at end of file diff --git a/examples/atclient_esp32_static_components/components/atclient/include/atclient/at_logger.h b/examples/atclient_esp32_static_components/components/atclient/include/atclient/at_logger.h new file mode 100644 index 00000000..c6be04fc --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atclient/include/atclient/at_logger.h @@ -0,0 +1,9 @@ +#ifndef ATLOGGER_H +#define ATLOGGER_H + +#include + +int atlogger_log(const char *title, const char *message); +int atlogger_logx(const char *title, const unsigned char *bytes, size_t byteslen); + +#endif // ATLOGGER_H diff --git a/examples/atclient_esp32_static_components/components/atclient/include/atclient/atkeys_filereader.h b/examples/atclient_esp32_static_components/components/atclient/include/atclient/atkeys_filereader.h new file mode 100644 index 00000000..e02fba54 --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atclient/include/atclient/atkeys_filereader.h @@ -0,0 +1,59 @@ +#pragma once + +#define TOKEN_AES_PKAM_PUBLIC_KEY "aesPkamPublicKey" +#define TOKEN_AES_PKAM_PUBLIC_KEY_LEN 16 + +#define TOKEN_AES_PKAM_PRIVATE_KEY "aesPkamPrivateKey" +#define TOKEN_AES_PKAM_PRIVATE_KEY_LEN 17 + +#define TOKEN_AES_ENCRYPT_PUBLIC_KEY "aesEncryptPublicKey" +#define TOKEN_AES_ENCRYPT_PUBLIC_KEY_LEN 19 + +#define TOKEN_AES_ENCRYPT_PRIVATE_KEY "aesEncryptPrivateKey" +#define TOKEN_AES_ENCRYPT_PRIVATE_KEY_LEN 20 + +#define TOKEN_SELF_ENCRYPTION_KEY "selfEncryptionKey" +#define TOKEN_SELF_ENCRYPTION_KEY_LEN 17 + +typedef struct atclient_atkeysfile_entry{ + size_t len; + char *key; +} atclient_atkeysfile_entry; + +typedef struct atclient_atkeysfile { + atclient_atkeysfile_entry *aes_pkam_public_key; + atclient_atkeysfile_entry *aes_pkam_private_key; + atclient_atkeysfile_entry *aes_encrypt_public_key; + atclient_atkeysfile_entry *aes_encrypt_private_key; + atclient_atkeysfile_entry *self_encryption_key; +} atclient_atkeysfile; + +void atclient_atkeysfile_init(atclient_atkeysfile *atkeysfile); +int atclient_atkeysfile_read(const char *path, atclient_atkeysfile *atkeysfile); +int atclient_atkeysfile_write(const char *path, const char *atsign, atclient_atkeysfile *atkeysfile); +void atclient_atkeysfile_free(atclient_atkeysfile *atkeysfile); + +/** + * Usage example + * atclient_atkeysfile atkeysfile; + * atclient_atkeysfile_init(&atkeysfile); + * printf("done init...\n") + * + ret = atclient_atkeysfile_read(path, &atkeysfile); + if (ret != 0) + { + goto exit; + } + + printf("done read...\n"); + printf("aes_pkam_public_key: %s\n", atkeysfile.aes_pkam_public_key->key); + printf("aes_pkam_private_key: %s\n", atkeysfile.aes_pkam_private_key->key); + printf("aes_encrypt_public_key: %s\n", atkeysfile.aes_encrypt_public_key->key); + printf("aes_encrypt_private_key: %s\n", atkeysfile.aes_encrypt_private_key->key); + printf("self_encryption_key: %s\n", atkeysfile.self_encryption_key->key); + + printf("writing...\n"); + + ret = atclient_atkeysfile_write("/Users/jeremytubongbanua/.atsign/temp/@smoothalligator_key.atKeys", ATSIGN, &atkeysfile); + * + */ \ No newline at end of file diff --git a/examples/atclient_esp32_static_components/components/atclient/include/atclient/connection.h b/examples/atclient_esp32_static_components/components/atclient/include/atclient/connection.h new file mode 100644 index 00000000..4d0d2351 --- /dev/null +++ b/examples/atclient_esp32_static_components/components/atclient/include/atclient/connection.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +#define HOST "root.atsign.org" +#define PORT 64 + +// #define HOST "245b44d4-a4bd-5f33-b077-c559f956486a.swarm0001.atsign.zone" +// #define PORT 1722 + +#define ROOT_CERT \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw\n" \ + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" \ + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw\n" \ + "WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg\n" \ + "RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n" \ + "AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP\n" \ + "R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx\n" \ + "sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm\n" \ + "NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg\n" \ + "Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG\n" \ + "/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC\n" \ + "AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB\n" \ + "Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA\n" \ + "FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw\n" \ + "AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw\n" \ + "Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB\n" \ + "gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W\n" \ + "PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl\n" \ + "ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz\n" \ + "CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm\n" \ + "lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4\n" \ + "avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2\n" \ + "yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O\n" \ + "yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids\n" \ + "hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+\n" \ + "HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv\n" \ + "MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX\n" \ + "nLRbwHOoq7hHwg==\n" \ + "-----END CERTIFICATE-----\n" + +typedef struct atclient_connection_ctx { + char *host; // assume null terminated, example: "root.atsign.org" + int port; // example: 64 + char *cert_pem; // assume null terminated, example: "-----BEGIN CERTIFICATE-----\nMIIF..." + void *server_fd; + void *ssl; + void *conf; + void *cacert; + void *entropy; + void *ctr_drbg; + void *saved_session; +} atclient_connection_ctx; + +void atclient_connection_init(atclient_connection_ctx *ctx); +int atclient_connection_connect(atclient_connection_ctx *ctx, const char *host, const int port); +int atclient_connection_send(atclient_connection_ctx *ctx, unsigned char *recv, const size_t recvlen, size_t *olen, const unsigned char *src, const size_t srclen); +void atclient_connection_free(atclient_connection_ctx *ctx); diff --git a/examples/atclient_esp32/lib/libatclient.a b/examples/atclient_esp32_static_components/components/atclient/lib/libatclient.a similarity index 95% rename from examples/atclient_esp32/lib/libatclient.a rename to examples/atclient_esp32_static_components/components/atclient/lib/libatclient.a index baef866a43fa24a363a30fc69a00d4f1b67f6d85..4cf4208d2c5929e658aff6a4dab133b923101381 100644 GIT binary patch delta 2074 zcmZ9M3rt)^6o${--DP*V3+1s0Mc55&i-{XrSm?H5>!YdF1dP~%8j4t{MrfO;Ek0su z)@s3q5KWx=s!dv&t|EyRT$Q3UF59A!@Mxog@zJ8hN;QqxRO6!%|8p6(S0*_#-<2D2+9TD6j(E#bEky3aZrf5Kx|mCpWpq5t zig%Q34P+1%G}?$VvW21bc%(h*6E{eI)GO*_c{E2f%Z6xfwQrXTs@;aD(}Ofd*O~w_ zI?jrOpJgLqFFJQD+0YKLcG+Sjqk``sb8od9u_<{pnwe(vB4}*yd6v}*l4qhhT8UR) zj$UoAoQq0N|5evE#FfTs*Ys-0HSS7ij{Dc7Aj2)$B#-ugt6j{MZ84wL>5<(ruecyj z$1>3W9IFY1jpcdAFTuotTl0yQZ)tjxM0lk$kI2Cxv?5n3!r}70I8Cv!_=L{0x;2Qb zhplDBQ#b(;et3N%hU(=zcWl9|wF0wkh(5%MFR)7yKEO|jy8}BOY@$2FTTXt1S72?h zl0CQvF=cxJT)LR$-A4Q@=Hsxyb`tNoia}mMlnGk_rr)vCKqHBmTy%0O?~v^o1WHG7 zhT^$2Uab|G_QFc1GvV7Kvj*BikHXK#^|FtsP;9c{#TaTWi9S08pT&d^xx-(b$iBo_T-yof z8AO}mD~S8B8|^V9xEIU&|3tWsAGYGB*O zC_i@_MrNIB3=J1UZWKFL)GlUdDljtZ0d#0BF!om})=St+Bw_5YQmmJ4v6Q4J60=~2PoarVmo#QlP;X6%%#-4XPBHdc^Hoi%LyX4kq;sFznnD{4V z{M5MpYVuz)v11A6d^Oo8JUy#?qS6`SiYc-am0>03pyJ2Ds}=L#Wv${iaJgdspKLVo zCdFJa^@`iU+Z1hZdD)c~x z(|PWNjv|Zv=EUmah#mUcRPwm(N1`F3IMKO4G9KIf$tiEfE(=j^zOa-K(Y?j8y5A?V z<(7W$V}Sx9PlJHlkPcUcJe6Ir61i8~tj}?B$%3TfwR})ByEoyev=82$$k2#i+XjWW!ETv-`kq>UBGjq!zP|IBJ+V|;!%&zscqhN-Mi zL!A+)wI&r`H4lol`ZlsmNOrjOZG=(+zR;6$Q#7S$6%uUks_kX9W8rFM3>nMiENz0 z@H?}Rj;=q94T`6$2JkXOblWOq*1>97@fJ29qK)hD?#1TH=B6E3MffCMMRq4EzQd!7 zXggmewgj49YN02^Njq=%eb^CL^}$@^#w|y|H49jNM$g~IdIT2OO`^-mC+o#I=fReO z=`MB}*hS)k%)IzZVY_8N5;cQ39udywyG2mxFs$bHJjC`(&!r>bCd3cn?Y-wCsu1-S zJQzcRDczSw!9!T^0d&u1wPsFft?*lgpMoDE%?CI%n-+d#+3CqnB>B|G^(5jH>_&*2 z;t!<{P+fT(u`$HTF9W&(!J7bXyV7FbNl0sfR~w`9F(g}Abr-&06jbfO^Y!Y^tbPYc*A0N&&n>2fl92{ON=F8lX z%OV=PJ>t@|2_d)J-7)R^U}5+u>Lv%elsf0EFV0!tnzNpqv!0o=&cUH12iGt8|5~Gm zVts#QX>!|)M@D8A$*a@v$f;4M+&ANleLAzmTy+)~xjjVqBIsMiTo1 zT1+BGgmmVc09;Yq90%! ze?_rlIY-f$v<3%)mVcP8j$n0~0>0WPQ&pXX`g!YDm=go+%JH<|lgau?ajSkLw2h z*}zi<7RCSR(+yn6Z2chLCkn)x-U^?nw}-h;{AolhP@j3Z;yvJ61Fu)yhIpNUwF|Dde2sf{H%Wg2%<$< diff --git a/examples/atclient_esp32/main/CMakeLists.txt b/examples/atclient_esp32_static_components/main/CMakeLists.txt similarity index 58% rename from examples/atclient_esp32/main/CMakeLists.txt rename to examples/atclient_esp32_static_components/main/CMakeLists.txt index 709b75c8..cb56fe94 100644 --- a/examples/atclient_esp32/main/CMakeLists.txt +++ b/examples/atclient_esp32_static_components/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register( SRCS "main.c" - REQUIRES atclient esp_wifi + REQUIRES atclient atchops ) diff --git a/examples/atclient_esp32_static_components/main/main.c b/examples/atclient_esp32_static_components/main/main.c new file mode 100644 index 00000000..da808d31 --- /dev/null +++ b/examples/atclient_esp32_static_components/main/main.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include "atchops/base64.h" + +void app_main(void) +{ + const char *src = "Lemonade!"; + unsigned long srclen = strlen(src); + + const unsigned long dstlen = 2048; + const unsigned char *dst = malloc(sizeof(unsigned char) * dstlen); + memset(dst, 0, dstlen); + unsigned long dstolen = 0; // written length + + int ret = atchops_base64_encode((const unsigned char *) src, srclen, dst, dstlen, &dstolen); + + printf("atchops_base64_encode: %d\n", ret); + + printf("src: %s\n", src); + printf("dst: %.*s\n", (int) dstolen, dst); + printf("dst bytes: \n"); + for(int i = 0; i < dstolen; i++) + { + printf("%02x ", *(dst + i)); + } + printf("\n"); +} \ No newline at end of file diff --git a/examples/atclient_esp32_static_no_components/CMakeLists.txt b/examples/atclient_esp32_static_no_components/CMakeLists.txt new file mode 100644 index 00000000..02baa343 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.19) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(atclient_esp32_static_no_components) \ No newline at end of file diff --git a/examples/atclient_esp32_static_no_components/main/CMakeLists.txt b/examples/atclient_esp32_static_no_components/main/CMakeLists.txt new file mode 100644 index 00000000..5e990671 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/CMakeLists.txt @@ -0,0 +1,11 @@ +idf_component_register( + SRCS "main.c" + INCLUDE_DIRS "atchops/include" "atclient/include" "." + REQUIRES mbedtls +) + +add_prebuilt_library(atchops "${CMAKE_CURRENT_LIST_DIR}/atchops/lib/libatchops.a" REQUIRES mbedtls) +target_link_libraries(${COMPONENT_LIB} INTERFACE atchops) + +add_prebuilt_library(atclient "${CMAKE_CURRENT_LIST_DIR}/atclient/lib/libatclient.a" REQUIRES mbedtls atchops) +target_link_libraries(${COMPONENT_LIB} INTERFACE atclient) \ No newline at end of file diff --git a/examples/atclient_esp32_static_no_components/main/atchops/CMakeLists.txt b/examples/atclient_esp32_static_no_components/main/atchops/CMakeLists.txt new file mode 100644 index 00000000..c8b1c2dd --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atchops/CMakeLists.txt @@ -0,0 +1,7 @@ +# register this directory as a component +idf_component_register() + +add_prebuilt_library(atchops ${CMAKE_CURRENT_LIST_DIR}/lib/libatchops.a REQUIRES mbedtls) + +target_include_directories(atchops INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) +target_link_libraries(${COMPONENT_LIB} INTERFACE atchops) # add it to the component library \ No newline at end of file diff --git a/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/aes_ctr.h b/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/aes_ctr.h new file mode 100644 index 00000000..ca9eb607 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/aes_ctr.h @@ -0,0 +1,31 @@ +#pragma once + +typedef enum AESKeySize { + AES_128 = 128, // not tested + AES_192 = 192, // not tested + AES_256 = 256, +} AESKeySize; + +int atchops_aes_ctr_encrypt( + const char *keybase64, + const unsigned long keybase64len, + const AESKeySize keybits, + const unsigned char *iv, + const unsigned long ivlen, + const unsigned char *plaintext, + const unsigned long plaintextlen, + unsigned char *ciphertextbase64, + const unsigned long ciphertextbase64len, + unsigned long *ciphertextbase64olen); + +int atchops_aes_ctr_decrypt( + const char *keybase64, + const unsigned long keybase64len, + const AESKeySize keybits, + const unsigned char *iv, + const unsigned long ivlen, + const unsigned char *ciphertextbase64, + const unsigned long ciphertextbase64len, + unsigned char *plaintext, + const unsigned long plaintextlen, + unsigned long *plaintextolen); diff --git a/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/base64.h b/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/base64.h new file mode 100644 index 00000000..d1a9c227 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/base64.h @@ -0,0 +1,25 @@ +#pragma once + +/** + * @brief Base64 encode some bytes + * + * @param src src bytes that you want to encode + * @param srclen the length of the src bytes + * @param dst the buffer where the base64 encoded result will be + * @param dstlen the buffer length + * @param writtenlen the length of the result after operation + * @return int 0 on success + */ +int atchops_base64_encode(const unsigned char *src, const unsigned long srclen, unsigned char *dst, unsigned long dstlen, unsigned long *writtenlen); + +/** + * @brief Base64 decode some bytes + * + * @param src src bytes that you want to decode + * @param srclen the length of the src bytes + * @param dst the buffer where the base64 decoded result will be + * @param dstlen the buffer length + * @param writtenlen the length of the result after operation + * @return int 0 on success + */ +int atchops_base64_decode(const unsigned char *src, const unsigned long srclen, unsigned char *dst, unsigned long dstlen, unsigned long *writtenlen); diff --git a/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/rsa.h b/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/rsa.h new file mode 100644 index 00000000..bffb64b4 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/rsa.h @@ -0,0 +1,84 @@ +#pragma once + +#include "sha.h" + +typedef struct rsa_param +{ + unsigned long len; // length of the number in bytes + unsigned char *value; // hex byte array of the number +} rsa_param; + +typedef struct atchops_rsa_publickey +{ + rsa_param n; // modulus + rsa_param e; // public exponent +} atchops_rsa_publickey; + +typedef struct atchops_rsa_privatekey +{ + rsa_param n; // modulus + rsa_param e; // public exponent + rsa_param d; // private exponent + rsa_param p; // prime 1 + rsa_param q; // prime 2 +} atchops_rsa_privatekey; + +/** + * @brief Populate a public key struct from a base64 string + * + * @param publickeybase64 a base64 string representing an RSA 2048 Public Key + * @param publickeybase64len the length of the base64 string + * @param publickeystruct the public key struct to populate + * @return int 0 on success + */ +int atchops_rsa_populate_publickey(const char *publickeybase64, const unsigned long publickeybase64len, atchops_rsa_publickey *publickeystruct); + +/** + * @brief Populate a private key struct from a base64 string + * + * @param privatekeybase64 the base64 string representing an RSA 2048 Private Key + * @param privatekeybase64len the length of the base64 string + * @param privatekeystruct the private key struct to populate + * @return int 0 on success + */ +int atchops_rsa_populate_privatekey(const char *privatekeybase64, const unsigned long privatekeybase64len, atchops_rsa_privatekey *privatekeystruct); + +/** + * @brief Sign a message with an RSA private key + * + * @param privatekeystruct the private key struct to use for signing, see atchops_rsa_populate_privatekey + * @param mdtype the hash type to use, see atchops_md_type, e.g. ATCHOPS_MD_SHA256 + * @param message the message to sign + * @param messagelen the length of the message, most people use strlen() to find this length + * @param signature the signature buffer to populate + * @param signaturelen the length of the signature buffer + * @param signatureolen the length of the signature buffer after signing + * @return int 0 on success + */ +int atchops_rsa_sign(atchops_rsa_privatekey privatekeystruct, atchops_md_type mdtype, const unsigned char *message, const unsigned long messagelen, unsigned char *signature, const unsigned long signaturelen, unsigned long *signatureolen); + +/** + * @brief Encrypt bytes with an RSA public key + * + * @param publickeystruct the public key struct to use for encryption, see atchops_rsa_populate_publickey + * @param plaintext the plaintext to encrypt + * @param plaintextlen the length of the plaintext, most people use strlen() to find this length + * @param ciphertext the ciphertext buffer to populate + * @param ciphertextlen the length of the ciphertext buffer + * @param ciphertextolen the length of the ciphertext buffer after encryption + * @return int 0 on success + */ +int atchops_rsa_encrypt(atchops_rsa_publickey publickeystruct, const unsigned char *plaintext, const unsigned long plaintextlen, unsigned char *ciphertext, const unsigned long ciphertextlen, unsigned long *ciphertextolen); + +/** + * @brief Decrypt bytes with an RSA private key + * + * @param privatekeystruct the private key struct to use for decryption, see atchops_rsa_populate_privatekey + * @param ciphertextbase64 the ciphertext to decrypt, base64 encoded + * @param ciphertextbase64len the length of the ciphertext, most people use strlen() to find this length + * @param plaintext the plaintext buffer to populate + * @param plaintextlen the length of the plaintext buffer + * @param plaintextolen the length of the plaintext buffer after decryption + * @return int 0 on success + */ +int atchops_rsa_decrypt(atchops_rsa_privatekey privatekeystruct, const unsigned char *ciphertextbase64, const unsigned long ciphertextbase64len, unsigned char *plaintext, const unsigned long plaintextlen, unsigned long *plaintextolen); diff --git a/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/sha.h b/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/sha.h new file mode 100644 index 00000000..786522e5 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atchops/include/atchops/sha.h @@ -0,0 +1,14 @@ +#pragma once + +typedef enum { + ATCHOPS_MD_NONE=0, /**< None. */ + ATCHOPS_MD_MD5, /**< The MD5 message digest. */ + ATCHOPS_MD_SHA1, /**< The SHA-1 message digest. */ + ATCHOPS_MD_SHA224, /**< The SHA-224 message digest. */ + ATCHOPS_MD_SHA256, /**< The SHA-256 message digest. */ + ATCHOPS_MD_SHA384, /**< The SHA-384 message digest. */ + ATCHOPS_MD_SHA512, /**< The SHA-512 message digest. */ + ATCHOPS_MD_RIPEMD160, +} atchops_md_type; + +int atchops_sha_hash(atchops_md_type mdtype, const unsigned char *input, const unsigned long inputlen, unsigned char *output, unsigned long outputlen, unsigned long *outputolen); diff --git a/examples/atclient_esp32_static_no_components/main/atchops/lib/libatchops.a b/examples/atclient_esp32_static_no_components/main/atchops/lib/libatchops.a new file mode 100644 index 0000000000000000000000000000000000000000..c32da5492bf0c27ea82cbe5d99e25d7378dbc1d6 GIT binary patch literal 74662 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 HNW%XBLnG!D literal 0 HcmV?d00001 diff --git a/examples/atclient_esp32_static_no_components/main/atclient/CMakeLists.txt b/examples/atclient_esp32_static_no_components/main/atclient/CMakeLists.txt new file mode 100644 index 00000000..05516682 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atclient/CMakeLists.txt @@ -0,0 +1,7 @@ +# register this directory as a component +idf_component_register() + +add_prebuilt_library(atclient ${CMAKE_CURRENT_LIST_DIR}/lib/libatclient.a REQUIRES mbedtls) + +target_include_directories(atclient INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) +target_link_libraries(${COMPONENT_LIB} INTERFACE atclient) # add it to the component library \ No newline at end of file diff --git a/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/at_logger.h b/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/at_logger.h new file mode 100644 index 00000000..c6be04fc --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/at_logger.h @@ -0,0 +1,9 @@ +#ifndef ATLOGGER_H +#define ATLOGGER_H + +#include + +int atlogger_log(const char *title, const char *message); +int atlogger_logx(const char *title, const unsigned char *bytes, size_t byteslen); + +#endif // ATLOGGER_H diff --git a/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/atkeys_filereader.h b/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/atkeys_filereader.h new file mode 100644 index 00000000..e02fba54 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/atkeys_filereader.h @@ -0,0 +1,59 @@ +#pragma once + +#define TOKEN_AES_PKAM_PUBLIC_KEY "aesPkamPublicKey" +#define TOKEN_AES_PKAM_PUBLIC_KEY_LEN 16 + +#define TOKEN_AES_PKAM_PRIVATE_KEY "aesPkamPrivateKey" +#define TOKEN_AES_PKAM_PRIVATE_KEY_LEN 17 + +#define TOKEN_AES_ENCRYPT_PUBLIC_KEY "aesEncryptPublicKey" +#define TOKEN_AES_ENCRYPT_PUBLIC_KEY_LEN 19 + +#define TOKEN_AES_ENCRYPT_PRIVATE_KEY "aesEncryptPrivateKey" +#define TOKEN_AES_ENCRYPT_PRIVATE_KEY_LEN 20 + +#define TOKEN_SELF_ENCRYPTION_KEY "selfEncryptionKey" +#define TOKEN_SELF_ENCRYPTION_KEY_LEN 17 + +typedef struct atclient_atkeysfile_entry{ + size_t len; + char *key; +} atclient_atkeysfile_entry; + +typedef struct atclient_atkeysfile { + atclient_atkeysfile_entry *aes_pkam_public_key; + atclient_atkeysfile_entry *aes_pkam_private_key; + atclient_atkeysfile_entry *aes_encrypt_public_key; + atclient_atkeysfile_entry *aes_encrypt_private_key; + atclient_atkeysfile_entry *self_encryption_key; +} atclient_atkeysfile; + +void atclient_atkeysfile_init(atclient_atkeysfile *atkeysfile); +int atclient_atkeysfile_read(const char *path, atclient_atkeysfile *atkeysfile); +int atclient_atkeysfile_write(const char *path, const char *atsign, atclient_atkeysfile *atkeysfile); +void atclient_atkeysfile_free(atclient_atkeysfile *atkeysfile); + +/** + * Usage example + * atclient_atkeysfile atkeysfile; + * atclient_atkeysfile_init(&atkeysfile); + * printf("done init...\n") + * + ret = atclient_atkeysfile_read(path, &atkeysfile); + if (ret != 0) + { + goto exit; + } + + printf("done read...\n"); + printf("aes_pkam_public_key: %s\n", atkeysfile.aes_pkam_public_key->key); + printf("aes_pkam_private_key: %s\n", atkeysfile.aes_pkam_private_key->key); + printf("aes_encrypt_public_key: %s\n", atkeysfile.aes_encrypt_public_key->key); + printf("aes_encrypt_private_key: %s\n", atkeysfile.aes_encrypt_private_key->key); + printf("self_encryption_key: %s\n", atkeysfile.self_encryption_key->key); + + printf("writing...\n"); + + ret = atclient_atkeysfile_write("/Users/jeremytubongbanua/.atsign/temp/@smoothalligator_key.atKeys", ATSIGN, &atkeysfile); + * + */ \ No newline at end of file diff --git a/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/connection.h b/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/connection.h new file mode 100644 index 00000000..4d0d2351 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/atclient/include/atclient/connection.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +#define HOST "root.atsign.org" +#define PORT 64 + +// #define HOST "245b44d4-a4bd-5f33-b077-c559f956486a.swarm0001.atsign.zone" +// #define PORT 1722 + +#define ROOT_CERT \ + "-----BEGIN CERTIFICATE-----\n" \ + "MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw\n" \ + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" \ + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw\n" \ + "WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg\n" \ + "RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n" \ + "AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP\n" \ + "R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx\n" \ + "sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm\n" \ + "NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg\n" \ + "Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG\n" \ + "/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC\n" \ + "AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB\n" \ + "Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA\n" \ + "FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw\n" \ + "AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw\n" \ + "Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB\n" \ + "gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W\n" \ + "PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl\n" \ + "ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz\n" \ + "CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm\n" \ + "lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4\n" \ + "avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2\n" \ + "yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O\n" \ + "yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids\n" \ + "hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+\n" \ + "HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv\n" \ + "MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX\n" \ + "nLRbwHOoq7hHwg==\n" \ + "-----END CERTIFICATE-----\n" + +typedef struct atclient_connection_ctx { + char *host; // assume null terminated, example: "root.atsign.org" + int port; // example: 64 + char *cert_pem; // assume null terminated, example: "-----BEGIN CERTIFICATE-----\nMIIF..." + void *server_fd; + void *ssl; + void *conf; + void *cacert; + void *entropy; + void *ctr_drbg; + void *saved_session; +} atclient_connection_ctx; + +void atclient_connection_init(atclient_connection_ctx *ctx); +int atclient_connection_connect(atclient_connection_ctx *ctx, const char *host, const int port); +int atclient_connection_send(atclient_connection_ctx *ctx, unsigned char *recv, const size_t recvlen, size_t *olen, const unsigned char *src, const size_t srclen); +void atclient_connection_free(atclient_connection_ctx *ctx); diff --git a/examples/atclient_esp32_static_no_components/main/atclient/lib/libatclient.a b/examples/atclient_esp32_static_no_components/main/atclient/lib/libatclient.a new file mode 100644 index 0000000000000000000000000000000000000000..4cf4208d2c5929e658aff6a4dab133b923101381 GIT binary patch literal 81616 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 literal 0 HcmV?d00001 diff --git a/examples/atclient_esp32_static_no_components/main/main.c b/examples/atclient_esp32_static_no_components/main/main.c new file mode 100644 index 00000000..da808d31 --- /dev/null +++ b/examples/atclient_esp32_static_no_components/main/main.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include "atchops/base64.h" + +void app_main(void) +{ + const char *src = "Lemonade!"; + unsigned long srclen = strlen(src); + + const unsigned long dstlen = 2048; + const unsigned char *dst = malloc(sizeof(unsigned char) * dstlen); + memset(dst, 0, dstlen); + unsigned long dstolen = 0; // written length + + int ret = atchops_base64_encode((const unsigned char *) src, srclen, dst, dstlen, &dstolen); + + printf("atchops_base64_encode: %d\n", ret); + + printf("src: %s\n", src); + printf("dst: %.*s\n", (int) dstolen, dst); + printf("dst bytes: \n"); + for(int i = 0; i < dstolen; i++) + { + printf("%02x ", *(dst + i)); + } + printf("\n"); +} \ No newline at end of file