From: Patrick Date: Mon, 13 Nov 2023 21:33:49 +0000 (+0100) Subject: changes to olm and esp X-Git-Url: https://gitweb.ps.run/matrix_esp_thesis/commitdiff_plain/a2b4308fa5bdc55cafa73aa0d70a00528f069ab7 changes to olm and esp --- diff --git a/esp32/esp_project/components/matrix/CMakeLists.txt b/esp32/esp_project/components/matrix/CMakeLists.txt index 2387948..bf7da7a 100644 --- a/esp32/esp_project/components/matrix/CMakeLists.txt +++ b/esp32/esp_project/components/matrix/CMakeLists.txt @@ -1,16 +1,16 @@ -idf_component_register(SRCS - "../../../../src/matrix.c" - "../../../../src/matrix_http_esp32.c" - "../../../../ext/mjson/src/mjson.c" - INCLUDE_DIRS - "../../../../ext/olm/include" - "../../../../ext/olm/lib" - "../../../../ext/mjson/src" - "../../../../src" - REQUIRES - esp-tls - esp_http_client - esp_netif - nvs_flash) - -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") +idf_component_register(SRCS + "../../../../src/matrix.c" + "../../../../src/matrix_http_esp32.c" + "../../../../ext/mjson/src/mjson.c" + INCLUDE_DIRS + "../../../../ext/olm/include" + "../../../../ext/olm/lib" + "../../../../ext/mjson/src" + "../../../../src" + REQUIRES + esp-tls + esp_http_client + esp_netif + nvs_flash) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") diff --git a/esp32/esp_project/main/SendEncrypted.c b/esp32/esp_project/main/SendEncrypted.c index 8d813ad..11e9e0d 100644 --- a/esp32/esp_project/main/SendEncrypted.c +++ b/esp32/esp_project/main/SendEncrypted.c @@ -1,65 +1,65 @@ -#define OLMLIB_VERSION_MAJOR 3 -#define OLMLIB_VERSION_MINOR 2 -#define OLMLIB_VERSION_PATCH 15 - -#define OLM_STATIC_DEFINE - -#include -#include - -#define SERVER "https://matrix.org" -#define USER_ID "@pscho:matrix.org" -#define ROOM_ID "!XKFUjAsGrSSrpDFIxB:matrix.org" - -int -main(void) -{ - MatrixClient client; - MatrixClientInit(&client); - - MatrixHttpInit(&client.hc, SERVER); - - MatrixClientSetUserId(&client, USER_ID); - - MatrixClientLoginPassword(&client, - "pscho", - "Wc23EbmB9G3faMq", - "Test1"); - - MatrixClientUploadDeviceKeys(&client); - MatrixClientGenerateOnetimeKeys(&client, 10); - MatrixClientUploadOnetimeKeys(&client); - - // create megolmsession - MatrixMegolmOutSession * megolmOutSession; - MatrixClientNewMegolmOutSession(&client, - ROOM_ID, - &megolmOutSession); - printf("megolm session id: %.10s... key: %.10s...\n", megolmOutSession->id, megolmOutSession->key); - - MatrixClientShareMegolmOutSession(&client, - USER_ID, - "ULZZOKJBYN", - megolmOutSession); - - MatrixClientSendEventEncrypted(&client, - ROOM_ID, - "m.room.message", - "{\"body\":\"Hello\",\"msgtype\":\"m.text\"}"); - - MatrixClientDeleteDevice(&client); - - MatrixHttpDeinit(&client.hc); - - return 0; -} - -#include "wifi.h" - -void -app_main(void) -{ - wifi_init("Hundehuette", "Affensicherespw55"); - - main(); -} +#define OLMLIB_VERSION_MAJOR 3 +#define OLMLIB_VERSION_MINOR 2 +#define OLMLIB_VERSION_PATCH 15 + +#define OLM_STATIC_DEFINE + +#include +#include + +#define SERVER "https://matrix.org" +#define USER_ID "@pscho:matrix.org" +#define ROOM_ID "!XKFUjAsGrSSrpDFIxB:matrix.org" + +int +main(void) +{ + MatrixClient client; + MatrixClientInit(&client); + + MatrixHttpInit(&client.hc, SERVER); + + MatrixClientSetUserId(&client, USER_ID); + + MatrixClientLoginPassword(&client, + "pscho", + "Wc23EbmB9G3faMq", + "Test1"); + + MatrixClientUploadDeviceKeys(&client); + MatrixClientGenerateOnetimeKeys(&client, 10); + MatrixClientUploadOnetimeKeys(&client); + + // create megolmsession + MatrixMegolmOutSession * megolmOutSession; + MatrixClientNewMegolmOutSession(&client, + ROOM_ID, + &megolmOutSession); + printf("megolm session id: %.10s... key: %.10s...\n", megolmOutSession->id, megolmOutSession->key); + + MatrixClientShareMegolmOutSession(&client, + USER_ID, + "ULZZOKJBYN", + megolmOutSession); + + MatrixClientSendEventEncrypted(&client, + ROOM_ID, + "m.room.message", + "{\"body\":\"Hello\",\"msgtype\":\"m.text\"}"); + + MatrixClientDeleteDevice(&client); + + MatrixHttpDeinit(&client.hc); + + return 0; +} + +#include "wifi.h" + +void +app_main(void) +{ + wifi_init("Hundehuette", "Affensicherespw55"); + + main(); +} diff --git a/esp32/esp_project/main/Verify.c b/esp32/esp_project/main/Verify.c index 91f9be8..cda5709 100644 --- a/esp32/esp_project/main/Verify.c +++ b/esp32/esp_project/main/Verify.c @@ -1,119 +1,119 @@ -#include -#include -#include - -#if !CONFIG_IDF_TARGET_LINUX -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_system.h" -#include "driver/gpio.h" -#endif - -#include - -#define SERVER "https://matrix.org" -#define USER_ID "@pscho:matrix.org" - -#define DEVICE_ID "ULZZOKJBYN" -#define SENDER_KEY "cjP41XzRlY+pd8DoiBuKQJj9o15mrx6gkrpqTkAPZ2c" -#define ROOM_ID "!XKFUjAsGrSSrpDFIxB:matrix.org" -#define EVENT_ID "$vOS09eUaI0CduqAcaIU5ZVk6ljLQfLspz7UThP8vaUM" -#define SESSION_ID "90UbGLue3ADVhvW7hFjoA2c6yg0JJKs/lPdMDZXnZAk" - -// main stack size: 3584 - -#define STATIC static - - - -int -main(void) -{ - MatrixClient * client = (MatrixClient*)malloc(sizeof(MatrixClient)); - MatrixClientInit(client); - - MatrixHttpInit(&client->hc, SERVER); - MatrixClientSetUserId(client, USER_ID); - - MatrixClientLoginPassword(client, - "pscho", - "Wc23EbmB9G3faMq", - "Test1"); - printf("deviceId: %s\n", client->deviceId); - MatrixClientGenerateOnetimeKeys(client, 10); - MatrixClientUploadOnetimeKeys(client); - MatrixClientUploadDeviceKeys(client); - - STATIC char eventBuffer[1024]; - MatrixClientGetRoomEvent(client, - ROOM_ID, - EVENT_ID, - eventBuffer, 1024); - printf("event: %s\n", eventBuffer); - - #define SYNC_BUFFER_SIZE 1024*10 - - // char * syncBuffer = (char*)malloc(SYNC_BUFFER_SIZE); - STATIC char syncBuffer[SYNC_BUFFER_SIZE]; - STATIC char nextBatch[1024]; - - while (! client->verified) { - MatrixClientSync(client, syncBuffer, SYNC_BUFFER_SIZE, nextBatch, 1024); - } - - printf("verified!\n"); - - // create and share megolm out session - MatrixMegolmOutSession * megolmOutSession; - MatrixClientNewMegolmOutSession(client, - ROOM_ID, - &megolmOutSession); - printf("megolm session id: %.10s... key: %.10s...\n", megolmOutSession->id, megolmOutSession->key); - MatrixClientShareMegolmOutSession(client, - USER_ID, - "ULZZOKJBYN", - megolmOutSession); - - // send 10 random messages - for (int i = 0; i < 10; i++) { - static const char * msgs[] = { "A", "B", "C" }; - static char msg[128]; - snprintf(msg, 128, "{\"body\":\"%s\",\"msgtype\":\"m.text\"}", msgs[rand()%(sizeof(msgs)/sizeof(msgs[0]))]); - - MatrixClientSendEventEncrypted(client, - ROOM_ID, - "m.room.message", - msg); - } - - MatrixClientDeleteDevice(client); - - MatrixHttpDeinit(&client->hc); - - return 0; -} - -#include "wifi.h" -#include - -void -app_main(void) -{ - // wifi_init("Pixel_7762", "affeaffe"); - // wifi_init("Hundehuette", "Affensicherespw55"); - wifi_init("test", "/O801i25"); - - esp_netif_ip_info_t ip_info; - esp_netif_get_ip_info(IP_EVENT_STA_GOT_IP,&ip_info); - printf("My IP: " IPSTR "\n", IP2STR(&ip_info.ip)); - printf("My GW: " IPSTR "\n", IP2STR(&ip_info.gw)); - printf("My NETMASK: " IPSTR "\n", IP2STR(&ip_info.netmask)); - - // uint64_t bitmask = 0xffffffffffffffff; - // bitmask = bitmask & SOC_GPIO_VALID_GPIO_MASK; - // gpio_dump_io_configuration(stdout, bitmask); - gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT); - // gpio_dump_io_configuration(stdout, bitmask); - - main(); -} +#include +#include +#include + +#if !CONFIG_IDF_TARGET_LINUX +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "driver/gpio.h" +#endif + +#include + +#define SERVER "https://matrix.org" +#define USER_ID "@pscho:matrix.org" + +#define DEVICE_ID "ULZZOKJBYN" +#define SENDER_KEY "cjP41XzRlY+pd8DoiBuKQJj9o15mrx6gkrpqTkAPZ2c" +#define ROOM_ID "!XKFUjAsGrSSrpDFIxB:matrix.org" +#define EVENT_ID "$vOS09eUaI0CduqAcaIU5ZVk6ljLQfLspz7UThP8vaUM" +#define SESSION_ID "90UbGLue3ADVhvW7hFjoA2c6yg0JJKs/lPdMDZXnZAk" + +// main stack size: 3584 + +#define STATIC static + + + +int +main(void) +{ + MatrixClient * client = (MatrixClient*)malloc(sizeof(MatrixClient)); + MatrixClientInit(client); + + MatrixHttpInit(&client->hc, SERVER); + MatrixClientSetUserId(client, USER_ID); + + MatrixClientLoginPassword(client, + "pscho", + "Wc23EbmB9G3faMq", + "Test1"); + printf("deviceId: %s\n", client->deviceId); + MatrixClientGenerateOnetimeKeys(client, 10); + MatrixClientUploadOnetimeKeys(client); + MatrixClientUploadDeviceKeys(client); + + STATIC char eventBuffer[1024]; + MatrixClientGetRoomEvent(client, + ROOM_ID, + EVENT_ID, + eventBuffer, 1024); + printf("event: %s\n", eventBuffer); + + #define SYNC_BUFFER_SIZE 1024*10 + + // char * syncBuffer = (char*)malloc(SYNC_BUFFER_SIZE); + STATIC char syncBuffer[SYNC_BUFFER_SIZE]; + STATIC char nextBatch[1024]; + + while (! client->verified) { + MatrixClientSync(client, syncBuffer, SYNC_BUFFER_SIZE, nextBatch, 1024); + } + + printf("verified!\n"); + + // create and share megolm out session + MatrixMegolmOutSession * megolmOutSession; + MatrixClientNewMegolmOutSession(client, + ROOM_ID, + &megolmOutSession); + printf("megolm session id: %.10s... key: %.10s...\n", megolmOutSession->id, megolmOutSession->key); + MatrixClientShareMegolmOutSession(client, + USER_ID, + "ULZZOKJBYN", + megolmOutSession); + + // send 10 random messages + for (int i = 0; i < 10; i++) { + static const char * msgs[] = { "A", "B", "C" }; + static char msg[128]; + snprintf(msg, 128, "{\"body\":\"%s\",\"msgtype\":\"m.text\"}", msgs[rand()%(sizeof(msgs)/sizeof(msgs[0]))]); + + MatrixClientSendEventEncrypted(client, + ROOM_ID, + "m.room.message", + msg); + } + + MatrixClientDeleteDevice(client); + + MatrixHttpDeinit(&client->hc); + + return 0; +} + +#include "wifi.h" +#include + +void +app_main(void) +{ + // wifi_init("Pixel_7762", "affeaffe"); + // wifi_init("Hundehuette", "Affensicherespw55"); + wifi_init("test", "/O801i25"); + + esp_netif_ip_info_t ip_info; + esp_netif_get_ip_info(IP_EVENT_STA_GOT_IP,&ip_info); + printf("My IP: " IPSTR "\n", IP2STR(&ip_info.ip)); + printf("My GW: " IPSTR "\n", IP2STR(&ip_info.gw)); + printf("My NETMASK: " IPSTR "\n", IP2STR(&ip_info.netmask)); + + // uint64_t bitmask = 0xffffffffffffffff; + // bitmask = bitmask & SOC_GPIO_VALID_GPIO_MASK; + // gpio_dump_io_configuration(stdout, bitmask); + gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT); + // gpio_dump_io_configuration(stdout, bitmask); + + main(); +} diff --git a/ext/olm/include/olm/olm_export.h b/ext/olm/include/olm/olm_export.h index d7197a2..e3daaeb 100644 --- a/ext/olm/include/olm/olm_export.h +++ b/ext/olm/include/olm/olm_export.h @@ -1,42 +1,42 @@ - -#ifndef OLM_EXPORT_H -#define OLM_EXPORT_H - -#ifdef OLM_STATIC_DEFINE -# define OLM_EXPORT -# define OLM_NO_EXPORT -#else -# ifndef OLM_EXPORT -# ifdef olm_EXPORTS - /* We are building this library */ -# define OLM_EXPORT -# else - /* We are using this library */ -# define OLM_EXPORT -# endif -# endif - -# ifndef OLM_NO_EXPORT -# define OLM_NO_EXPORT -# endif -#endif - -#ifndef OLM_DEPRECATED -# define OLM_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef OLM_DEPRECATED_EXPORT -# define OLM_DEPRECATED_EXPORT OLM_EXPORT OLM_DEPRECATED -#endif - -#ifndef OLM_DEPRECATED_NO_EXPORT -# define OLM_DEPRECATED_NO_EXPORT OLM_NO_EXPORT OLM_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef OLM_NO_DEPRECATED -# define OLM_NO_DEPRECATED -# endif -#endif - -#endif /* OLM_EXPORT_H */ + +#ifndef OLM_EXPORT_H +#define OLM_EXPORT_H + +#ifdef OLM_STATIC_DEFINE +# define OLM_EXPORT +# define OLM_NO_EXPORT +#else +# ifndef OLM_EXPORT +# ifdef olm_EXPORTS + /* We are building this library */ +# define OLM_EXPORT +# else + /* We are using this library */ +# define OLM_EXPORT +# endif +# endif + +# ifndef OLM_NO_EXPORT +# define OLM_NO_EXPORT +# endif +#endif + +#ifndef OLM_DEPRECATED +# define OLM_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef OLM_DEPRECATED_EXPORT +# define OLM_DEPRECATED_EXPORT OLM_EXPORT OLM_DEPRECATED +#endif + +#ifndef OLM_DEPRECATED_NO_EXPORT +# define OLM_DEPRECATED_NO_EXPORT OLM_NO_EXPORT OLM_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef OLM_NO_DEPRECATED +# define OLM_NO_DEPRECATED +# endif +#endif + +#endif /* OLM_EXPORT_H */ diff --git a/ext/olm/include/olm/session.hh b/ext/olm/include/olm/session.hh index 41300db..a5d6f3e 100644 --- a/ext/olm/include/olm/session.hh +++ b/ext/olm/include/olm/session.hh @@ -1,168 +1,168 @@ -/* Copyright 2015 OpenMarket Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef OLM_SESSION_HH_ -#define OLM_SESSION_HH_ - -#include "olm/ratchet.hh" - -// Note: exports in this file are only for unit tests. Nobody else should be -// using this externally -#include "olm/olm_export.h" - -namespace olm { - -struct Account; - -enum struct MessageType { - PRE_KEY = 0, - MESSAGE = 1, -}; - -struct OLM_EXPORT Session { - - Session(); - - Ratchet ratchet; - OlmErrorCode last_error; - - bool received_message; - - _olm_curve25519_public_key alice_identity_key; - _olm_curve25519_public_key alice_base_key; - _olm_curve25519_public_key bob_one_time_key; - - /** The number of random bytes that are needed to create a new outbound - * session. This will be 64 bytes since two ephemeral keys are needed. */ - std::size_t new_outbound_session_random_length() const; - - /** Start a new outbound session. Returns std::size_t(-1) on failure. On - * failure last_error will be set with an error code. The last_error will be - * NOT_ENOUGH_RANDOM if the number of random bytes was too small. */ - std::size_t new_outbound_session( - Account const & local_account, - _olm_curve25519_public_key const & identity_key, - _olm_curve25519_public_key const & one_time_key, - std::uint8_t const * random, std::size_t random_length - ); - - /** Start a new inbound session from a pre-key message. - * Returns std::size_t(-1) on failure. On failure last_error will be set - * with an error code. The last_error will be BAD_MESSAGE_FORMAT if - * the message headers could not be decoded. */ - std::size_t new_inbound_session( - Account & local_account, - _olm_curve25519_public_key const * their_identity_key, - std::uint8_t const * pre_key_message, std::size_t message_length - ); - - /** The number of bytes written by session_id() */ - std::size_t session_id_length() const; - - /** An identifier for this session. Generated by hashing the public keys - * used to create the session. Returns the length of the session id on - * success or std::size_t(-1) on failure. On failure last_error will be set - * with an error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if - * the id buffer was too small. */ - std::size_t session_id( - std::uint8_t * id, std::size_t id_length - ); - - /** True if this session can be used to decode an inbound pre-key message. - * This can be used to test whether a pre-key message should be decoded - * with an existing session or if a new session will need to be created. - * Returns true if the session is the same. Returns false if either the - * session does not match or the pre-key message could not be decoded. - */ - bool matches_inbound_session( - _olm_curve25519_public_key const * their_identity_key, - std::uint8_t const * pre_key_message, std::size_t message_length - ) const; - - /** Whether the next message will be a pre-key message or a normal message. - * An outbound session will send pre-key messages until it receives a - * message with a ratchet key. */ - MessageType encrypt_message_type() const; - - std::size_t encrypt_message_length( - std::size_t plaintext_length - ) const; - - /** The number of bytes of random data the encrypt method will need to - * encrypt a message. This will be 32 bytes if the session needs to - * generate a new ephemeral key, or will be 0 bytes otherwise. */ - std::size_t encrypt_random_length() const; - - /** Encrypt some plain-text. Returns the length of the encrypted message - * or std::size_t(-1) on failure. On failure last_error will be set with - * an error code. The last_error will be NOT_ENOUGH_RANDOM if the number - * of random bytes is too small. The last_error will be - * OUTPUT_BUFFER_TOO_SMALL if the output buffer is too small. */ - std::size_t encrypt( - std::uint8_t const * plaintext, std::size_t plaintext_length, - std::uint8_t const * random, std::size_t random_length, - std::uint8_t * message, std::size_t message_length - ); - - /** An upper bound on the number of bytes of plain-text the decrypt method - * will write for a given input message length. */ - std::size_t decrypt_max_plaintext_length( - MessageType message_type, - std::uint8_t const * message, std::size_t message_length - ); - - /** Decrypt a message. Returns the length of the decrypted plain-text or - * std::size_t(-1) on failure. On failure last_error will be set with an - * error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if the - * plain-text buffer is too small. The last_error will be - * BAD_MESSAGE_VERSION if the message was encrypted with an unsupported - * version of the protocol. The last_error will be BAD_MESSAGE_FORMAT if - * the message headers could not be decoded. The last_error will be - * BAD_MESSAGE_MAC if the message could not be verified */ - std::size_t decrypt( - MessageType message_type, - std::uint8_t const * message, std::size_t message_length, - std::uint8_t * plaintext, std::size_t max_plaintext_length - ); - - /** - * Write a string describing this session and its state (not including the - * private key) into the buffer provided. - * - * Takes a buffer to write to and the length of that buffer - */ - void describe(char *buf, size_t buflen); -}; - - -std::size_t pickle_length( - Session const & value -); - - -std::uint8_t * pickle( - std::uint8_t * pos, - Session const & value -); - - -OLM_EXPORT std::uint8_t const * unpickle( - std::uint8_t const * pos, std::uint8_t const * end, - Session & value -); - - -} // namespace olm - -#endif /* OLM_SESSION_HH_ */ +/* Copyright 2015 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OLM_SESSION_HH_ +#define OLM_SESSION_HH_ + +#include "olm/ratchet.hh" + +// Note: exports in this file are only for unit tests. Nobody else should be +// using this externally +#include "olm/olm_export.h" + +namespace olm { + +struct Account; + +enum struct MessageType { + PRE_KEY = 0, + MESSAGE = 1, +}; + +struct OLM_EXPORT Session { + + Session(); + + Ratchet ratchet; + OlmErrorCode last_error; + + bool received_message; + + _olm_curve25519_public_key alice_identity_key; + _olm_curve25519_public_key alice_base_key; + _olm_curve25519_public_key bob_one_time_key; + + /** The number of random bytes that are needed to create a new outbound + * session. This will be 64 bytes since two ephemeral keys are needed. */ + std::size_t new_outbound_session_random_length() const; + + /** Start a new outbound session. Returns std::size_t(-1) on failure. On + * failure last_error will be set with an error code. The last_error will be + * NOT_ENOUGH_RANDOM if the number of random bytes was too small. */ + std::size_t new_outbound_session( + Account const & local_account, + _olm_curve25519_public_key const & identity_key, + _olm_curve25519_public_key const & one_time_key, + std::uint8_t const * random, std::size_t random_length + ); + + /** Start a new inbound session from a pre-key message. + * Returns std::size_t(-1) on failure. On failure last_error will be set + * with an error code. The last_error will be BAD_MESSAGE_FORMAT if + * the message headers could not be decoded. */ + std::size_t new_inbound_session( + Account & local_account, + _olm_curve25519_public_key const * their_identity_key, + std::uint8_t const * pre_key_message, std::size_t message_length + ); + + /** The number of bytes written by session_id() */ + std::size_t session_id_length() const; + + /** An identifier for this session. Generated by hashing the public keys + * used to create the session. Returns the length of the session id on + * success or std::size_t(-1) on failure. On failure last_error will be set + * with an error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if + * the id buffer was too small. */ + std::size_t session_id( + std::uint8_t * id, std::size_t id_length + ); + + /** True if this session can be used to decode an inbound pre-key message. + * This can be used to test whether a pre-key message should be decoded + * with an existing session or if a new session will need to be created. + * Returns true if the session is the same. Returns false if either the + * session does not match or the pre-key message could not be decoded. + */ + bool matches_inbound_session( + _olm_curve25519_public_key const * their_identity_key, + std::uint8_t const * pre_key_message, std::size_t message_length + ) const; + + /** Whether the next message will be a pre-key message or a normal message. + * An outbound session will send pre-key messages until it receives a + * message with a ratchet key. */ + MessageType encrypt_message_type() const; + + std::size_t encrypt_message_length( + std::size_t plaintext_length + ) const; + + /** The number of bytes of random data the encrypt method will need to + * encrypt a message. This will be 32 bytes if the session needs to + * generate a new ephemeral key, or will be 0 bytes otherwise. */ + std::size_t encrypt_random_length() const; + + /** Encrypt some plain-text. Returns the length of the encrypted message + * or std::size_t(-1) on failure. On failure last_error will be set with + * an error code. The last_error will be NOT_ENOUGH_RANDOM if the number + * of random bytes is too small. The last_error will be + * OUTPUT_BUFFER_TOO_SMALL if the output buffer is too small. */ + std::size_t encrypt( + std::uint8_t const * plaintext, std::size_t plaintext_length, + std::uint8_t const * random, std::size_t random_length, + std::uint8_t * message, std::size_t message_length + ); + + /** An upper bound on the number of bytes of plain-text the decrypt method + * will write for a given input message length. */ + std::size_t decrypt_max_plaintext_length( + MessageType message_type, + std::uint8_t const * message, std::size_t message_length + ); + + /** Decrypt a message. Returns the length of the decrypted plain-text or + * std::size_t(-1) on failure. On failure last_error will be set with an + * error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if the + * plain-text buffer is too small. The last_error will be + * BAD_MESSAGE_VERSION if the message was encrypted with an unsupported + * version of the protocol. The last_error will be BAD_MESSAGE_FORMAT if + * the message headers could not be decoded. The last_error will be + * BAD_MESSAGE_MAC if the message could not be verified */ + std::size_t decrypt( + MessageType message_type, + std::uint8_t const * message, std::size_t message_length, + std::uint8_t * plaintext, std::size_t max_plaintext_length + ); + + /** + * Write a string describing this session and its state (not including the + * private key) into the buffer provided. + * + * Takes a buffer to write to and the length of that buffer + */ + void describe(char *buf, size_t buflen); +}; + + +std::size_t pickle_length( + Session const & value +); + + +std::uint8_t * pickle( + std::uint8_t * pos, + Session const & value +); + + +OLM_EXPORT std::uint8_t const * unpickle( + std::uint8_t const * pos, std::uint8_t const * end, + Session & value +); + + +} // namespace olm + +#endif /* OLM_SESSION_HH_ */ diff --git a/ext/olm/lib/crypto-algorithms/aes.h b/ext/olm/lib/crypto-algorithms/aes.h index 84e5355..6d570f4 100644 --- a/ext/olm/lib/crypto-algorithms/aes.h +++ b/ext/olm/lib/crypto-algorithms/aes.h @@ -1,123 +1,123 @@ -/********************************************************************* -* Filename: aes.h -* Author: Brad Conte (brad AT bradconte.com) -* Copyright: -* Disclaimer: This code is presented "as is" without any guarantees. -* Details: Defines the API for the corresponding AES implementation. -*********************************************************************/ - -#ifndef AES_H -#define AES_H - -/*************************** HEADER FILES ***************************/ -#include - -/****************************** MACROS ******************************/ -#define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time - -/**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte -typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines - -/*********************** FUNCTION DECLARATIONS **********************/ -/////////////////// -// AES -/////////////////// -// Key setup must be done before any AES en/de-cryption functions can be used. -void _olm_aes_key_setup(const BYTE key[], // The key, must be 128, 192, or 256 bits - WORD w[], // Output key schedule to be used later - int keysize); // Bit length of the key, 128, 192, or 256 - -void _olm_aes_encrypt(const BYTE in[], // 16 bytes of plaintext - BYTE out[], // 16 bytes of ciphertext - const WORD key[], // From the key setup - int keysize); // Bit length of the key, 128, 192, or 256 - -void _olm_aes_decrypt(const BYTE in[], // 16 bytes of ciphertext - BYTE out[], // 16 bytes of plaintext - const WORD key[], // From the key setup - int keysize); // Bit length of the key, 128, 192, or 256 - -/////////////////// -// AES - CBC -/////////////////// -int _olm_aes_encrypt_cbc(const BYTE in[], // Plaintext - size_t in_len, // Must be a multiple of AES_BLOCK_SIZE - BYTE out[], // Ciphertext, same length as plaintext - const WORD key[], // From the key setup - int keysize, // Bit length of the key, 128, 192, or 256 - const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long - -// Only output the CBC-MAC of the input. -int _olm_aes_encrypt_cbc_mac(const BYTE in[], // plaintext - size_t in_len, // Must be a multiple of AES_BLOCK_SIZE - BYTE out[], // Output MAC - const WORD key[], // From the key setup - int keysize, // Bit length of the key, 128, 192, or 256 - const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long - -/////////////////// -// AES - CTR -/////////////////// -void increment_iv(BYTE iv[], // Must be a multiple of AES_BLOCK_SIZE - int counter_size); // Bytes of the IV used for counting (low end) - -void _olm_aes_encrypt_ctr(const BYTE in[], // Plaintext - size_t in_len, // Any byte length - BYTE out[], // Ciphertext, same length as plaintext - const WORD key[], // From the key setup - int keysize, // Bit length of the key, 128, 192, or 256 - const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long - -void _olm_aes_decrypt_ctr(const BYTE in[], // Ciphertext - size_t in_len, // Any byte length - BYTE out[], // Plaintext, same length as ciphertext - const WORD key[], // From the key setup - int keysize, // Bit length of the key, 128, 192, or 256 - const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long - -/////////////////// -// AES - CCM -/////////////////// -// Returns True if the input parameters do not violate any constraint. -int _olm_aes_encrypt_ccm(const BYTE plaintext[], // IN - Plaintext. - WORD plaintext_len, // IN - Plaintext length. - const BYTE associated_data[], // IN - Associated Data included in authentication, but not encryption. - unsigned short associated_data_len, // IN - Associated Data length in bytes. - const BYTE nonce[], // IN - The Nonce to be used for encryption. - unsigned short nonce_len, // IN - Nonce length in bytes. - BYTE ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC. - WORD *ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len. - WORD mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16. - const BYTE key[], // IN - The AES key for encryption. - int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256. - -// Returns True if the input parameters do not violate any constraint. -// Use mac_auth to ensure decryption/validation was preformed correctly. -// If authentication does not succeed, the plaintext is zeroed out. To overwride -// this, call with mac_auth = NULL. The proper proceedure is to decrypt with -// authentication enabled (mac_auth != NULL) and make a second call to that -// ignores authentication explicitly if the first call failes. -int _olm_aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC. - WORD ciphertext_len, // IN - Ciphertext length in bytes. - const BYTE assoc[], // IN - The Associated Data, required for authentication. - unsigned short assoc_len, // IN - Associated Data length in bytes. - const BYTE nonce[], // IN - The Nonce to use for decryption, same one as for encryption. - unsigned short nonce_len, // IN - Nonce length in bytes. - BYTE plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len - mac_len. - WORD *plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len . - WORD mac_len, // IN - The length of the MAC that was calculated. - int *mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the authentication. - const BYTE key[], // IN - The AES key for decryption. - int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256. - -/////////////////// -// Test functions -/////////////////// -int aes_test(); -int aes_ecb_test(); -int aes_cbc_test(); -int aes_ctr_test(); -int aes_ccm_test(); - -#endif // AES_H +/********************************************************************* +* Filename: aes.h +* Author: Brad Conte (brad AT bradconte.com) +* Copyright: +* Disclaimer: This code is presented "as is" without any guarantees. +* Details: Defines the API for the corresponding AES implementation. +*********************************************************************/ + +#ifndef AES_H +#define AES_H + +/*************************** HEADER FILES ***************************/ +#include + +/****************************** MACROS ******************************/ +#define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time + +/**************************** DATA TYPES ****************************/ +typedef unsigned char BYTE; // 8-bit byte +typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines + +/*********************** FUNCTION DECLARATIONS **********************/ +/////////////////// +// AES +/////////////////// +// Key setup must be done before any AES en/de-cryption functions can be used. +void _olm_aes_key_setup(const BYTE key[], // The key, must be 128, 192, or 256 bits + WORD w[], // Output key schedule to be used later + int keysize); // Bit length of the key, 128, 192, or 256 + +void _olm_aes_encrypt(const BYTE in[], // 16 bytes of plaintext + BYTE out[], // 16 bytes of ciphertext + const WORD key[], // From the key setup + int keysize); // Bit length of the key, 128, 192, or 256 + +void _olm_aes_decrypt(const BYTE in[], // 16 bytes of ciphertext + BYTE out[], // 16 bytes of plaintext + const WORD key[], // From the key setup + int keysize); // Bit length of the key, 128, 192, or 256 + +/////////////////// +// AES - CBC +/////////////////// +int _olm_aes_encrypt_cbc(const BYTE in[], // Plaintext + size_t in_len, // Must be a multiple of AES_BLOCK_SIZE + BYTE out[], // Ciphertext, same length as plaintext + const WORD key[], // From the key setup + int keysize, // Bit length of the key, 128, 192, or 256 + const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long + +// Only output the CBC-MAC of the input. +int _olm_aes_encrypt_cbc_mac(const BYTE in[], // plaintext + size_t in_len, // Must be a multiple of AES_BLOCK_SIZE + BYTE out[], // Output MAC + const WORD key[], // From the key setup + int keysize, // Bit length of the key, 128, 192, or 256 + const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long + +/////////////////// +// AES - CTR +/////////////////// +void increment_iv(BYTE iv[], // Must be a multiple of AES_BLOCK_SIZE + int counter_size); // Bytes of the IV used for counting (low end) + +void _olm_aes_encrypt_ctr(const BYTE in[], // Plaintext + size_t in_len, // Any byte length + BYTE out[], // Ciphertext, same length as plaintext + const WORD key[], // From the key setup + int keysize, // Bit length of the key, 128, 192, or 256 + const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long + +void _olm_aes_decrypt_ctr(const BYTE in[], // Ciphertext + size_t in_len, // Any byte length + BYTE out[], // Plaintext, same length as ciphertext + const WORD key[], // From the key setup + int keysize, // Bit length of the key, 128, 192, or 256 + const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long + +/////////////////// +// AES - CCM +/////////////////// +// Returns True if the input parameters do not violate any constraint. +int _olm_aes_encrypt_ccm(const BYTE plaintext[], // IN - Plaintext. + WORD plaintext_len, // IN - Plaintext length. + const BYTE associated_data[], // IN - Associated Data included in authentication, but not encryption. + unsigned short associated_data_len, // IN - Associated Data length in bytes. + const BYTE nonce[], // IN - The Nonce to be used for encryption. + unsigned short nonce_len, // IN - Nonce length in bytes. + BYTE ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC. + WORD *ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len. + WORD mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16. + const BYTE key[], // IN - The AES key for encryption. + int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256. + +// Returns True if the input parameters do not violate any constraint. +// Use mac_auth to ensure decryption/validation was preformed correctly. +// If authentication does not succeed, the plaintext is zeroed out. To overwride +// this, call with mac_auth = NULL. The proper proceedure is to decrypt with +// authentication enabled (mac_auth != NULL) and make a second call to that +// ignores authentication explicitly if the first call failes. +int _olm_aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC. + WORD ciphertext_len, // IN - Ciphertext length in bytes. + const BYTE assoc[], // IN - The Associated Data, required for authentication. + unsigned short assoc_len, // IN - Associated Data length in bytes. + const BYTE nonce[], // IN - The Nonce to use for decryption, same one as for encryption. + unsigned short nonce_len, // IN - Nonce length in bytes. + BYTE plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len - mac_len. + WORD *plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len . + WORD mac_len, // IN - The length of the MAC that was calculated. + int *mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the authentication. + const BYTE key[], // IN - The AES key for decryption. + int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256. + +/////////////////// +// Test functions +/////////////////// +int aes_test(); +int aes_ecb_test(); +int aes_cbc_test(); +int aes_ctr_test(); +int aes_ccm_test(); + +#endif // AES_H diff --git a/ext/olm/lib/crypto-algorithms/aes_test.c b/ext/olm/lib/crypto-algorithms/aes_test.c index b679477..d49726d 100644 --- a/ext/olm/lib/crypto-algorithms/aes_test.c +++ b/ext/olm/lib/crypto-algorithms/aes_test.c @@ -1,276 +1,276 @@ -/********************************************************************* -* Filename: aes_test.c -* Author: Brad Conte (brad AT bradconte.com) -* Copyright: -* Disclaimer: This code is presented "as is" without any guarantees. -* Details: Performs known-answer tests on the corresponding AES - implementation. These tests do not encompass the full - range of available test vectors and are not sufficient - for FIPS-140 certification. However, if the tests pass - it is very, very likely that the code is correct and was - compiled properly. This code also serves as - example usage of the functions. -*********************************************************************/ - -/*************************** HEADER FILES ***************************/ -#include -#include -#include "aes.h" - -/*********************** FUNCTION DEFINITIONS ***********************/ -void print_hex(BYTE str[], int len) -{ - int idx; - - for(idx = 0; idx < len; idx++) - printf("%02x", str[idx]); -} - -int aes_ecb_test() -{ - WORD key_schedule[60], idx; - BYTE enc_buf[128]; - BYTE plaintext[2][16] = { - {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a}, - {0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} - }; - BYTE ciphertext[2][16] = { - {0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c,0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8}, - {0x59,0x1c,0xcb,0x10,0xd4,0x10,0xed,0x26,0xdc,0x5b,0xa7,0x4a,0x31,0x36,0x28,0x70} - }; - BYTE key[1][32] = { - {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} - }; - int pass = 1; - - // Raw ECB mode. - //printf("* ECB mode:\n"); - aes_key_setup(key[0], key_schedule, 256); - //printf( "Key : "); - //print_hex(key[0], 32); - - for(idx = 0; idx < 2; idx++) { - aes_encrypt(plaintext[idx], enc_buf, key_schedule, 256); - //printf("\nPlaintext : "); - //print_hex(plaintext[idx], 16); - //printf("\n-encrypted to: "); - //print_hex(enc_buf, 16); - pass = pass && !memcmp(enc_buf, ciphertext[idx], 16); - - aes_decrypt(ciphertext[idx], enc_buf, key_schedule, 256); - //printf("\nCiphertext : "); - //print_hex(ciphertext[idx], 16); - //printf("\n-decrypted to: "); - //print_hex(enc_buf, 16); - pass = pass && !memcmp(enc_buf, plaintext[idx], 16); - - //printf("\n\n"); - } - - return(pass); -} - -int aes_cbc_test() -{ - WORD key_schedule[60]; - BYTE enc_buf[128]; - BYTE plaintext[1][32] = { - {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} - }; - BYTE ciphertext[2][32] = { - {0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba,0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6,0x9c,0xfc,0x4e,0x96,0x7e,0xdb,0x80,0x8d,0x67,0x9f,0x77,0x7b,0xc6,0x70,0x2c,0x7d} - }; - BYTE iv[1][16] = { - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f} - }; - BYTE key[1][32] = { - {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} - }; - int pass = 1; - - //printf("* CBC mode:\n"); - aes_key_setup(key[0], key_schedule, 256); - - //printf( "Key : "); - //print_hex(key[0], 32); - //printf("\nIV : "); - //print_hex(iv[0], 16); - - aes_encrypt_cbc(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]); - //printf("\nPlaintext : "); - //print_hex(plaintext[0], 32); - //printf("\n-encrypted to: "); - //print_hex(enc_buf, 32); - //printf("\nCiphertext : "); - //print_hex(ciphertext[0], 32); - pass = pass && !memcmp(enc_buf, ciphertext[0], 32); - - //printf("\n\n"); - return(pass); -} - -int aes_ctr_test() -{ - WORD key_schedule[60]; - BYTE enc_buf[128]; - BYTE plaintext[1][32] = { - {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} - }; - BYTE ciphertext[1][32] = { - {0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5,0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28,0xf4,0x43,0xe3,0xca,0x4d,0x62,0xb5,0x9a,0xca,0x84,0xe9,0x90,0xca,0xca,0xf5,0xc5} - }; - BYTE iv[1][16] = { - {0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff}, - }; - BYTE key[1][32] = { - {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} - }; - int pass = 1; - - //printf("* CTR mode:\n"); - aes_key_setup(key[0], key_schedule, 256); - - //printf( "Key : "); - //print_hex(key[0], 32); - //printf("\nIV : "); - //print_hex(iv[0], 16); - - aes_encrypt_ctr(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]); - //printf("\nPlaintext : "); - //print_hex(plaintext[0], 32); - //printf("\n-encrypted to: "); - //print_hex(enc_buf, 32); - pass = pass && !memcmp(enc_buf, ciphertext[0], 32); - - aes_decrypt_ctr(ciphertext[0], 32, enc_buf, key_schedule, 256, iv[0]); - //printf("\nCiphertext : "); - //print_hex(ciphertext[0], 32); - //printf("\n-decrypted to: "); - //print_hex(enc_buf, 32); - pass = pass && !memcmp(enc_buf, plaintext[0], 32); - - //printf("\n\n"); - return(pass); -} - -int aes_ccm_test() -{ - int mac_auth; - WORD enc_buf_len; - BYTE enc_buf[128]; - BYTE plaintext[3][32] = { - {0x20,0x21,0x22,0x23}, - {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f}, - {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37} - }; - BYTE assoc[3][32] = { - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}, - {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13} - }; - BYTE ciphertext[3][32 + 16] = { - {0x71,0x62,0x01,0x5b,0x4d,0xac,0x25,0x5d}, - {0xd2,0xa1,0xf0,0xe0,0x51,0xea,0x5f,0x62,0x08,0x1a,0x77,0x92,0x07,0x3d,0x59,0x3d,0x1f,0xc6,0x4f,0xbf,0xac,0xcd}, - {0xe3,0xb2,0x01,0xa9,0xf5,0xb7,0x1a,0x7a,0x9b,0x1c,0xea,0xec,0xcd,0x97,0xe7,0x0b,0x61,0x76,0xaa,0xd9,0xa4,0x42,0x8a,0xa5,0x48,0x43,0x92,0xfb,0xc1,0xb0,0x99,0x51} - }; - BYTE iv[3][16] = { - {0x10,0x11,0x12,0x13,0x14,0x15,0x16}, - {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17}, - {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b} - }; - BYTE key[1][32] = { - {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f} - }; - int pass = 1; - - //printf("* CCM mode:\n"); - //printf("Key : "); - //print_hex(key[0], 16); - - //print_hex(plaintext[0], 4); - //print_hex(assoc[0], 8); - //print_hex(ciphertext[0], 8); - //print_hex(iv[0], 7); - //print_hex(key[0], 16); - - aes_encrypt_ccm(plaintext[0], 4, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, key[0], 128); - //printf("\nNONCE : "); - //print_hex(iv[0], 7); - //printf("\nAssoc. Data : "); - //print_hex(assoc[0], 8); - //printf("\nPayload : "); - //print_hex(plaintext[0], 4); - //printf("\n-encrypted to: "); - //print_hex(enc_buf, enc_buf_len); - pass = pass && !memcmp(enc_buf, ciphertext[0], enc_buf_len); - - aes_decrypt_ccm(ciphertext[0], 8, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, &mac_auth, key[0], 128); - //printf("\n-Ciphertext : "); - //print_hex(ciphertext[0], 8); - //printf("\n-decrypted to: "); - //print_hex(enc_buf, enc_buf_len); - //printf("\nAuthenticated: %d ", mac_auth); - pass = pass && !memcmp(enc_buf, plaintext[0], enc_buf_len) && mac_auth; - - - aes_encrypt_ccm(plaintext[1], 16, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, key[0], 128); - //printf("\n\nNONCE : "); - //print_hex(iv[1], 8); - //printf("\nAssoc. Data : "); - //print_hex(assoc[1], 16); - //printf("\nPayload : "); - //print_hex(plaintext[1], 16); - //printf("\n-encrypted to: "); - //print_hex(enc_buf, enc_buf_len); - pass = pass && !memcmp(enc_buf, ciphertext[1], enc_buf_len); - - aes_decrypt_ccm(ciphertext[1], 22, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, &mac_auth, key[0], 128); - //printf("\n-Ciphertext : "); - //print_hex(ciphertext[1], 22); - //printf("\n-decrypted to: "); - //print_hex(enc_buf, enc_buf_len); - //printf("\nAuthenticated: %d ", mac_auth); - pass = pass && !memcmp(enc_buf, plaintext[1], enc_buf_len) && mac_auth; - - - aes_encrypt_ccm(plaintext[2], 24, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, key[0], 128); - //printf("\n\nNONCE : "); - //print_hex(iv[2], 12); - //printf("\nAssoc. Data : "); - //print_hex(assoc[2], 20); - //printf("\nPayload : "); - //print_hex(plaintext[2], 24); - //printf("\n-encrypted to: "); - //print_hex(enc_buf, enc_buf_len); - pass = pass && !memcmp(enc_buf, ciphertext[2], enc_buf_len); - - aes_decrypt_ccm(ciphertext[2], 32, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, &mac_auth, key[0], 128); - //printf("\n-Ciphertext : "); - //print_hex(ciphertext[2], 32); - //printf("\n-decrypted to: "); - //print_hex(enc_buf, enc_buf_len); - //printf("\nAuthenticated: %d ", mac_auth); - pass = pass && !memcmp(enc_buf, plaintext[2], enc_buf_len) && mac_auth; - - //printf("\n\n"); - return(pass); -} - -int aes_test() -{ - int pass = 1; - - pass = pass && aes_ecb_test(); - pass = pass && aes_cbc_test(); - pass = pass && aes_ctr_test(); - pass = pass && aes_ccm_test(); - - return(pass); -} - -int main(int argc, char *argv[]) -{ - printf("AES Tests: %s\n", aes_test() ? "SUCCEEDED" : "FAILED"); - - return(0); -} +/********************************************************************* +* Filename: aes_test.c +* Author: Brad Conte (brad AT bradconte.com) +* Copyright: +* Disclaimer: This code is presented "as is" without any guarantees. +* Details: Performs known-answer tests on the corresponding AES + implementation. These tests do not encompass the full + range of available test vectors and are not sufficient + for FIPS-140 certification. However, if the tests pass + it is very, very likely that the code is correct and was + compiled properly. This code also serves as + example usage of the functions. +*********************************************************************/ + +/*************************** HEADER FILES ***************************/ +#include +#include +#include "aes.h" + +/*********************** FUNCTION DEFINITIONS ***********************/ +void print_hex(BYTE str[], int len) +{ + int idx; + + for(idx = 0; idx < len; idx++) + printf("%02x", str[idx]); +} + +int aes_ecb_test() +{ + WORD key_schedule[60], idx; + BYTE enc_buf[128]; + BYTE plaintext[2][16] = { + {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a}, + {0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} + }; + BYTE ciphertext[2][16] = { + {0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c,0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8}, + {0x59,0x1c,0xcb,0x10,0xd4,0x10,0xed,0x26,0xdc,0x5b,0xa7,0x4a,0x31,0x36,0x28,0x70} + }; + BYTE key[1][32] = { + {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} + }; + int pass = 1; + + // Raw ECB mode. + //printf("* ECB mode:\n"); + aes_key_setup(key[0], key_schedule, 256); + //printf( "Key : "); + //print_hex(key[0], 32); + + for(idx = 0; idx < 2; idx++) { + aes_encrypt(plaintext[idx], enc_buf, key_schedule, 256); + //printf("\nPlaintext : "); + //print_hex(plaintext[idx], 16); + //printf("\n-encrypted to: "); + //print_hex(enc_buf, 16); + pass = pass && !memcmp(enc_buf, ciphertext[idx], 16); + + aes_decrypt(ciphertext[idx], enc_buf, key_schedule, 256); + //printf("\nCiphertext : "); + //print_hex(ciphertext[idx], 16); + //printf("\n-decrypted to: "); + //print_hex(enc_buf, 16); + pass = pass && !memcmp(enc_buf, plaintext[idx], 16); + + //printf("\n\n"); + } + + return(pass); +} + +int aes_cbc_test() +{ + WORD key_schedule[60]; + BYTE enc_buf[128]; + BYTE plaintext[1][32] = { + {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} + }; + BYTE ciphertext[2][32] = { + {0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba,0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6,0x9c,0xfc,0x4e,0x96,0x7e,0xdb,0x80,0x8d,0x67,0x9f,0x77,0x7b,0xc6,0x70,0x2c,0x7d} + }; + BYTE iv[1][16] = { + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f} + }; + BYTE key[1][32] = { + {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} + }; + int pass = 1; + + //printf("* CBC mode:\n"); + aes_key_setup(key[0], key_schedule, 256); + + //printf( "Key : "); + //print_hex(key[0], 32); + //printf("\nIV : "); + //print_hex(iv[0], 16); + + aes_encrypt_cbc(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]); + //printf("\nPlaintext : "); + //print_hex(plaintext[0], 32); + //printf("\n-encrypted to: "); + //print_hex(enc_buf, 32); + //printf("\nCiphertext : "); + //print_hex(ciphertext[0], 32); + pass = pass && !memcmp(enc_buf, ciphertext[0], 32); + + //printf("\n\n"); + return(pass); +} + +int aes_ctr_test() +{ + WORD key_schedule[60]; + BYTE enc_buf[128]; + BYTE plaintext[1][32] = { + {0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51} + }; + BYTE ciphertext[1][32] = { + {0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5,0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28,0xf4,0x43,0xe3,0xca,0x4d,0x62,0xb5,0x9a,0xca,0x84,0xe9,0x90,0xca,0xca,0xf5,0xc5} + }; + BYTE iv[1][16] = { + {0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff}, + }; + BYTE key[1][32] = { + {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4} + }; + int pass = 1; + + //printf("* CTR mode:\n"); + aes_key_setup(key[0], key_schedule, 256); + + //printf( "Key : "); + //print_hex(key[0], 32); + //printf("\nIV : "); + //print_hex(iv[0], 16); + + aes_encrypt_ctr(plaintext[0], 32, enc_buf, key_schedule, 256, iv[0]); + //printf("\nPlaintext : "); + //print_hex(plaintext[0], 32); + //printf("\n-encrypted to: "); + //print_hex(enc_buf, 32); + pass = pass && !memcmp(enc_buf, ciphertext[0], 32); + + aes_decrypt_ctr(ciphertext[0], 32, enc_buf, key_schedule, 256, iv[0]); + //printf("\nCiphertext : "); + //print_hex(ciphertext[0], 32); + //printf("\n-decrypted to: "); + //print_hex(enc_buf, 32); + pass = pass && !memcmp(enc_buf, plaintext[0], 32); + + //printf("\n\n"); + return(pass); +} + +int aes_ccm_test() +{ + int mac_auth; + WORD enc_buf_len; + BYTE enc_buf[128]; + BYTE plaintext[3][32] = { + {0x20,0x21,0x22,0x23}, + {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f}, + {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37} + }; + BYTE assoc[3][32] = { + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13} + }; + BYTE ciphertext[3][32 + 16] = { + {0x71,0x62,0x01,0x5b,0x4d,0xac,0x25,0x5d}, + {0xd2,0xa1,0xf0,0xe0,0x51,0xea,0x5f,0x62,0x08,0x1a,0x77,0x92,0x07,0x3d,0x59,0x3d,0x1f,0xc6,0x4f,0xbf,0xac,0xcd}, + {0xe3,0xb2,0x01,0xa9,0xf5,0xb7,0x1a,0x7a,0x9b,0x1c,0xea,0xec,0xcd,0x97,0xe7,0x0b,0x61,0x76,0xaa,0xd9,0xa4,0x42,0x8a,0xa5,0x48,0x43,0x92,0xfb,0xc1,0xb0,0x99,0x51} + }; + BYTE iv[3][16] = { + {0x10,0x11,0x12,0x13,0x14,0x15,0x16}, + {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17}, + {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b} + }; + BYTE key[1][32] = { + {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f} + }; + int pass = 1; + + //printf("* CCM mode:\n"); + //printf("Key : "); + //print_hex(key[0], 16); + + //print_hex(plaintext[0], 4); + //print_hex(assoc[0], 8); + //print_hex(ciphertext[0], 8); + //print_hex(iv[0], 7); + //print_hex(key[0], 16); + + aes_encrypt_ccm(plaintext[0], 4, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, key[0], 128); + //printf("\nNONCE : "); + //print_hex(iv[0], 7); + //printf("\nAssoc. Data : "); + //print_hex(assoc[0], 8); + //printf("\nPayload : "); + //print_hex(plaintext[0], 4); + //printf("\n-encrypted to: "); + //print_hex(enc_buf, enc_buf_len); + pass = pass && !memcmp(enc_buf, ciphertext[0], enc_buf_len); + + aes_decrypt_ccm(ciphertext[0], 8, assoc[0], 8, iv[0], 7, enc_buf, &enc_buf_len, 4, &mac_auth, key[0], 128); + //printf("\n-Ciphertext : "); + //print_hex(ciphertext[0], 8); + //printf("\n-decrypted to: "); + //print_hex(enc_buf, enc_buf_len); + //printf("\nAuthenticated: %d ", mac_auth); + pass = pass && !memcmp(enc_buf, plaintext[0], enc_buf_len) && mac_auth; + + + aes_encrypt_ccm(plaintext[1], 16, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, key[0], 128); + //printf("\n\nNONCE : "); + //print_hex(iv[1], 8); + //printf("\nAssoc. Data : "); + //print_hex(assoc[1], 16); + //printf("\nPayload : "); + //print_hex(plaintext[1], 16); + //printf("\n-encrypted to: "); + //print_hex(enc_buf, enc_buf_len); + pass = pass && !memcmp(enc_buf, ciphertext[1], enc_buf_len); + + aes_decrypt_ccm(ciphertext[1], 22, assoc[1], 16, iv[1], 8, enc_buf, &enc_buf_len, 6, &mac_auth, key[0], 128); + //printf("\n-Ciphertext : "); + //print_hex(ciphertext[1], 22); + //printf("\n-decrypted to: "); + //print_hex(enc_buf, enc_buf_len); + //printf("\nAuthenticated: %d ", mac_auth); + pass = pass && !memcmp(enc_buf, plaintext[1], enc_buf_len) && mac_auth; + + + aes_encrypt_ccm(plaintext[2], 24, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, key[0], 128); + //printf("\n\nNONCE : "); + //print_hex(iv[2], 12); + //printf("\nAssoc. Data : "); + //print_hex(assoc[2], 20); + //printf("\nPayload : "); + //print_hex(plaintext[2], 24); + //printf("\n-encrypted to: "); + //print_hex(enc_buf, enc_buf_len); + pass = pass && !memcmp(enc_buf, ciphertext[2], enc_buf_len); + + aes_decrypt_ccm(ciphertext[2], 32, assoc[2], 20, iv[2], 12, enc_buf, &enc_buf_len, 8, &mac_auth, key[0], 128); + //printf("\n-Ciphertext : "); + //print_hex(ciphertext[2], 32); + //printf("\n-decrypted to: "); + //print_hex(enc_buf, enc_buf_len); + //printf("\nAuthenticated: %d ", mac_auth); + pass = pass && !memcmp(enc_buf, plaintext[2], enc_buf_len) && mac_auth; + + //printf("\n\n"); + return(pass); +} + +int aes_test() +{ + int pass = 1; + + pass = pass && aes_ecb_test(); + pass = pass && aes_cbc_test(); + pass = pass && aes_ctr_test(); + pass = pass && aes_ccm_test(); + + return(pass); +} + +int main(int argc, char *argv[]) +{ + printf("AES Tests: %s\n", aes_test() ? "SUCCEEDED" : "FAILED"); + + return(0); +} diff --git a/src/matrix_http_esp32.c b/src/matrix_http_esp32.c index 2bdfb50..2cc4cfe 100644 --- a/src/matrix_http_esp32.c +++ b/src/matrix_http_esp32.c @@ -1,315 +1,315 @@ -#include -#include -#include -#include -#include "esp_log.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -// #include "protocol_examples_common.h" -// #include "protocol_examples_utils.h" -#include "esp_tls.h" -#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE -#include "esp_crt_bundle.h" -#endif - -#if !CONFIG_IDF_TARGET_LINUX -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_system.h" -#endif - -#include "esp_http_client.h" - -/* Root cert for howsmyssl.com, taken from howsmyssl_com_root_cert.pem - - The PEM file was extracted from the output of this command: - openssl s_client -showcerts -connect www.howsmyssl.com:443 user_data; - switch(evt->event_id) { - case HTTP_EVENT_ERROR: - ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); - break; - case HTTP_EVENT_ON_CONNECTED: - ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); - break; - case HTTP_EVENT_HEADER_SENT: - ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); - break; - case HTTP_EVENT_ON_HEADER: - ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); - break; - case HTTP_EVENT_ON_DATA: - ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); - /* - * Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data. - * However, event handler can also be used in case chunked encoding is used. - */ - if (!esp_http_client_is_chunked_response(evt->client)) { - ESP_LOGD(TAG, "Non-Chunked Encoding"); - } - else { - ESP_LOGD(TAG, "Chunked Encoding"); - } - - int copy_len = 0; - - // const int64_t buffer_len = esp_http_client_get_content_length(evt->client); - // if (buffer_len < hc->dataCap) { - // ESP_LOGE(TAG, "Output buffer too small: %" PRIu64 ", data_len: %d", buffer_len, evt->data_len); - // return ESP_FAIL; - // } - copy_len = MIN(evt->data_len, (hc->dataCap - hc->dataLen)); - if (copy_len) { - memcpy(hc->data + hc->dataLen, evt->data, copy_len); - hc->data[hc->dataLen + copy_len] = '\0'; - } - - hc->dataLen += copy_len; - - break; - case HTTP_EVENT_ON_FINISH: - ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); - break; - case HTTP_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED"); - int mbedtls_err = 0; - esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL); - if (err != 0) { - ESP_LOGI(TAG, "Last esp error code: 0x%x", err); - ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err); - } - break; - case HTTP_EVENT_REDIRECT: - ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT"); - // esp_http_client_set_header(evt->client, "From", "user@example.com"); - // esp_http_client_set_header(evt->client, "Accept", "text/html"); - // esp_http_client_set_redirection(evt->client); - break; - } - return ESP_OK; -} - -void -MatrixHttpConnect( - MatrixHttpConnection * hc) -{ - esp_http_client_config_t config = { - .url = hc->host, - // .query = "esp", - .event_handler = _http_event_handler, - .user_data = hc, - .disable_auto_redirect = true, - .crt_bundle_attach = esp_crt_bundle_attach, - }; - - hc->client = esp_http_client_init(&config); - - esp_http_client_set_timeout_ms(hc->client, 20000); -} - -void -MatrixHttpDisconnect( - MatrixHttpConnection * hc) -{ - esp_http_client_cleanup(hc->client); - hc->client = NULL; -} - -bool -MatrixHttpInit( - MatrixHttpConnection ** hc, - const char * host) -{ - *hc = (MatrixHttpConnection *)calloc(1, sizeof(MatrixHttpConnection)); - - (*hc)->host = host; - - MatrixHttpConnect(*hc); - - return true; -} - -bool -MatrixHttpDeinit( - MatrixHttpConnection ** hc) -{ - MatrixHttpDisconnect(*hc); - - free(*hc); - *hc = NULL; - - return true; -} - -bool -MatrixHttpSetAccessToken( - MatrixHttpConnection * hc, - const char * accessToken) -{ - hc->accessToken = accessToken; - - return true; -} - -bool -MatrixHttpGet( - MatrixHttpConnection * hc, - const char * url, - char * outResponseBuffer, int outResponseCap, - bool authenticated) -{ - static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; - if (authenticated) - snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, - "Bearer %s", hc->accessToken); - else - authorizationHeader[0] = '\0'; - - printf("GET %s%s\n", hc->host, url); - - hc->data = outResponseBuffer; - hc->dataCap = outResponseCap; - hc->dataLen = 0; - - static char hostAndUrl[MAX_URL_LEN]; - snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); - - esp_http_client_set_url(hc->client, hostAndUrl); - esp_http_client_set_method(hc->client, HTTP_METHOD_GET); - if (authenticated) - esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); - esp_err_t err = esp_http_client_perform(hc->client); - if (err == ESP_OK) { - ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRIu64, - esp_http_client_get_status_code(hc->client), - esp_http_client_get_content_length(hc->client)); - } else { - ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); - } - // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); - - return true; -} - -bool -MatrixHttpPost( - MatrixHttpConnection * hc, - const char * url, - const char * requestBuffer, - char * outResponseBuffer, int outResponseCap, - bool authenticated) -{ - static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; - if (authenticated) - snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, - "Bearer %s", hc->accessToken); - else - authorizationHeader[0] = '\0'; - - printf("POST %s%s\n%s\n", hc->host, url, requestBuffer); - - hc->data = outResponseBuffer; - hc->dataCap = outResponseCap; - hc->dataLen = 0; - - static char hostAndUrl[MAX_URL_LEN]; - snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); - - esp_http_client_set_url(hc->client, hostAndUrl); - esp_http_client_set_method(hc->client, HTTP_METHOD_POST); - if (authenticated) - esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); - esp_http_client_set_header(hc->client, "Content-Type", "application/json"); - esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer)); - esp_err_t err = esp_http_client_perform(hc->client); - if (err == ESP_OK) { - ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %"PRIu64, - esp_http_client_get_status_code(hc->client), - esp_http_client_get_content_length(hc->client)); - } else { - ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err)); - } - // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); - - return true; -} - -bool -MatrixHttpPut( - MatrixHttpConnection * hc, - const char * url, - const char * requestBuffer, - char * outResponseBuffer, int outResponseCap, - bool authenticated) -{ - static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; - if (authenticated) - snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, - "Bearer %s", hc->accessToken); - else - authorizationHeader[0] = '\0'; - - printf("PUT %s%s\n%s\n", hc->host, url, requestBuffer); - - hc->data = outResponseBuffer; - hc->dataCap = outResponseCap; - hc->dataLen = 0; - - static char hostAndUrl[MAX_URL_LEN]; - snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); - - esp_http_client_set_url(hc->client, hostAndUrl); - esp_http_client_set_method(hc->client, HTTP_METHOD_PUT); - if (authenticated) - esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); - esp_http_client_set_header(hc->client, "Content-Type", "application/json"); - esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer)); - esp_err_t err = esp_http_client_perform(hc->client); - if (err == ESP_OK) { - ESP_LOGI(TAG, "HTTP PUT Status = %d, content_length = %"PRIu64, - esp_http_client_get_status_code(hc->client), - esp_http_client_get_content_length(hc->client)); - } else { - ESP_LOGE(TAG, "HTTP PUT request failed: %s", esp_err_to_name(err)); - } - // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); - - return true; -} +#include +#include +#include +#include +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_event.h" +#include "esp_netif.h" +// #include "protocol_examples_common.h" +// #include "protocol_examples_utils.h" +#include "esp_tls.h" +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + +#if !CONFIG_IDF_TARGET_LINUX +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#endif + +#include "esp_http_client.h" + +/* Root cert for howsmyssl.com, taken from howsmyssl_com_root_cert.pem + + The PEM file was extracted from the output of this command: + openssl s_client -showcerts -connect www.howsmyssl.com:443 user_data; + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + /* + * Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data. + * However, event handler can also be used in case chunked encoding is used. + */ + if (!esp_http_client_is_chunked_response(evt->client)) { + ESP_LOGD(TAG, "Non-Chunked Encoding"); + } + else { + ESP_LOGD(TAG, "Chunked Encoding"); + } + + int copy_len = 0; + + // const int64_t buffer_len = esp_http_client_get_content_length(evt->client); + // if (buffer_len < hc->dataCap) { + // ESP_LOGE(TAG, "Output buffer too small: %" PRIu64 ", data_len: %d", buffer_len, evt->data_len); + // return ESP_FAIL; + // } + copy_len = MIN(evt->data_len, (hc->dataCap - hc->dataLen)); + if (copy_len) { + memcpy(hc->data + hc->dataLen, evt->data, copy_len); + hc->data[hc->dataLen + copy_len] = '\0'; + } + + hc->dataLen += copy_len; + + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED"); + int mbedtls_err = 0; + esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL); + if (err != 0) { + ESP_LOGI(TAG, "Last esp error code: 0x%x", err); + ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err); + } + break; + case HTTP_EVENT_REDIRECT: + ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT"); + // esp_http_client_set_header(evt->client, "From", "user@example.com"); + // esp_http_client_set_header(evt->client, "Accept", "text/html"); + // esp_http_client_set_redirection(evt->client); + break; + } + return ESP_OK; +} + +void +MatrixHttpConnect( + MatrixHttpConnection * hc) +{ + esp_http_client_config_t config = { + .url = hc->host, + // .query = "esp", + .event_handler = _http_event_handler, + .user_data = hc, + .disable_auto_redirect = true, + .crt_bundle_attach = esp_crt_bundle_attach, + }; + + hc->client = esp_http_client_init(&config); + + esp_http_client_set_timeout_ms(hc->client, 20000); +} + +void +MatrixHttpDisconnect( + MatrixHttpConnection * hc) +{ + esp_http_client_cleanup(hc->client); + hc->client = NULL; +} + +bool +MatrixHttpInit( + MatrixHttpConnection ** hc, + const char * host) +{ + *hc = (MatrixHttpConnection *)calloc(1, sizeof(MatrixHttpConnection)); + + (*hc)->host = host; + + MatrixHttpConnect(*hc); + + return true; +} + +bool +MatrixHttpDeinit( + MatrixHttpConnection ** hc) +{ + MatrixHttpDisconnect(*hc); + + free(*hc); + *hc = NULL; + + return true; +} + +bool +MatrixHttpSetAccessToken( + MatrixHttpConnection * hc, + const char * accessToken) +{ + hc->accessToken = accessToken; + + return true; +} + +bool +MatrixHttpGet( + MatrixHttpConnection * hc, + const char * url, + char * outResponseBuffer, int outResponseCap, + bool authenticated) +{ + static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; + if (authenticated) + snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, + "Bearer %s", hc->accessToken); + else + authorizationHeader[0] = '\0'; + + printf("GET %s%s\n", hc->host, url); + + hc->data = outResponseBuffer; + hc->dataCap = outResponseCap; + hc->dataLen = 0; + + static char hostAndUrl[MAX_URL_LEN]; + snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); + + esp_http_client_set_url(hc->client, hostAndUrl); + esp_http_client_set_method(hc->client, HTTP_METHOD_GET); + if (authenticated) + esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); + esp_err_t err = esp_http_client_perform(hc->client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRIu64, + esp_http_client_get_status_code(hc->client), + esp_http_client_get_content_length(hc->client)); + } else { + ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); + } + // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); + + return true; +} + +bool +MatrixHttpPost( + MatrixHttpConnection * hc, + const char * url, + const char * requestBuffer, + char * outResponseBuffer, int outResponseCap, + bool authenticated) +{ + static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; + if (authenticated) + snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, + "Bearer %s", hc->accessToken); + else + authorizationHeader[0] = '\0'; + + printf("POST %s%s\n%s\n", hc->host, url, requestBuffer); + + hc->data = outResponseBuffer; + hc->dataCap = outResponseCap; + hc->dataLen = 0; + + static char hostAndUrl[MAX_URL_LEN]; + snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); + + esp_http_client_set_url(hc->client, hostAndUrl); + esp_http_client_set_method(hc->client, HTTP_METHOD_POST); + if (authenticated) + esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); + esp_http_client_set_header(hc->client, "Content-Type", "application/json"); + esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer)); + esp_err_t err = esp_http_client_perform(hc->client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %"PRIu64, + esp_http_client_get_status_code(hc->client), + esp_http_client_get_content_length(hc->client)); + } else { + ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err)); + } + // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); + + return true; +} + +bool +MatrixHttpPut( + MatrixHttpConnection * hc, + const char * url, + const char * requestBuffer, + char * outResponseBuffer, int outResponseCap, + bool authenticated) +{ + static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; + if (authenticated) + snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, + "Bearer %s", hc->accessToken); + else + authorizationHeader[0] = '\0'; + + printf("PUT %s%s\n%s\n", hc->host, url, requestBuffer); + + hc->data = outResponseBuffer; + hc->dataCap = outResponseCap; + hc->dataLen = 0; + + static char hostAndUrl[MAX_URL_LEN]; + snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); + + esp_http_client_set_url(hc->client, hostAndUrl); + esp_http_client_set_method(hc->client, HTTP_METHOD_PUT); + if (authenticated) + esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); + esp_http_client_set_header(hc->client, "Content-Type", "application/json"); + esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer)); + esp_err_t err = esp_http_client_perform(hc->client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP PUT Status = %d, content_length = %"PRIu64, + esp_http_client_get_status_code(hc->client), + esp_http_client_get_content_length(hc->client)); + } else { + ESP_LOGE(TAG, "HTTP PUT request failed: %s", esp_err_to_name(err)); + } + // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); + + return true; +}