Skip to content

Commit

Permalink
Merge pull request #33 from atsign-foundation/jeremy-refactor
Browse files Browse the repository at this point in the history
feat: atchops refactor, ESP-IDF build static libraries, ESP-IDF project examples, repl example, lots of docs
  • Loading branch information
JeremyTubongbanua authored Aug 28, 2023
2 parents 8ac1f76 + da9f3b6 commit f7faf50
Show file tree
Hide file tree
Showing 102 changed files with 2,490 additions and 1,271 deletions.
3 changes: 2 additions & 1 deletion .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"includePath": [
"${default}",
"${workspaceFolder}/**",
"/usr/local/include"
"/usr/local/include",
"~/esp/esp-idf/components/**"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c99",
Expand Down
120 changes: 9 additions & 111 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,124 +8,22 @@

## 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) build atclient for ESP-IDF

## 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
```

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:

```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!
- [atclient_esp32_source](./examples/atclient_esp32_source/README.md) is an example of how to use atclient in your ESP-IDF with the source code.
- [atclient_esp32_static_components](./examples/atclient_esp32_static_components/README.md) is an example of how to use atclient in your ESP-IDF project with static libraries in separated components built from [atclient_espidf](./packages/atclient_espidf/README.md).
- [atclient_esp32_static_no_components](./examples/atclient_esp32_static_no_components/) is an example of how to use atclient in your ESP-IDF project with static libraries without components built from [atclient_espidf](./packages/atclient_espidf/README.md).
- [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 <atclient/new_header.h>`)
When creating source files, include headers, or tests to certain packages, please follow the documentation in their according README files (for example [atclient Contributing](./packages/atclient/README.md)).

## Maintainers

Expand Down
10 changes: 10 additions & 0 deletions examples/atclient_esp32_source/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
37 changes: 37 additions & 0 deletions examples/atclient_esp32_source/README.md
Original file line number Diff line number Diff line change
@@ -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
```
31 changes: 31 additions & 0 deletions examples/atclient_esp32_source/include/atchops/aes_ctr.h
Original file line number Diff line number Diff line change
@@ -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);
25 changes: 25 additions & 0 deletions examples/atclient_esp32_source/include/atchops/base64.h
Original file line number Diff line number Diff line change
@@ -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);
84 changes: 84 additions & 0 deletions examples/atclient_esp32_source/include/atchops/rsa.h
Original file line number Diff line number Diff line change
@@ -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);
14 changes: 14 additions & 0 deletions examples/atclient_esp32_source/include/atchops/sha.h
Original file line number Diff line number Diff line change
@@ -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);
9 changes: 9 additions & 0 deletions examples/atclient_esp32_source/include/atclient/at_logger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef ATLOGGER_H
#define ATLOGGER_H

#include <stddef.h>

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
Loading

0 comments on commit f7faf50

Please sign in to comment.