Skip to content

Instantly share code, notes, and snippets.

@VNovytskyi
Created March 12, 2022 11:33
Show Gist options
  • Save VNovytskyi/cbd5bdf3c7e601903bb531855fd2c2d0 to your computer and use it in GitHub Desktop.
Save VNovytskyi/cbd5bdf3c7e601903bb531855fd2c2d0 to your computer and use it in GitHub Desktop.
Arduino ESP32 AES-GCM encryption with Tag
#include "base64_app.h"
#include "mbedtls/gcm.h"
#include "mbedtls/error.h"
#define AES_GCM_APP_AES_TAG_SIZE_BYTES 16
mbedtls_gcm_context aes;
const char *key_base64_p = "1BpsjPJ1Hiob0BZ1F491UpvPKiyxjRlUIibijcgEHPg=";
const char *iv_base64_p = "Zidvdg8Z0bvmzr6K/hd7UQ==";
const char *data_p = "Hello world from MBedTLS!";
const char *ciphertext_test_base64_p = "5bixXg+eh0BX/mw2UqCQFE4KxiO0eYEw5qjncqB1hWyG31i91DExsMs=";
void setup() {
int result = 0;
mbedtls_gcm_init(&aes);
printf("1: Decode key from BASE64\n");
size_t key_bin_size = 0;
uint8_t *key_bin_p = base64_app_decode(key_base64_p, &key_bin_size);
if (key_bin_p == NULL || key_bin_size == 0) {
printf("Failed decode key (%zu): %s\n", strlen(key_base64_p), key_base64_p);
return;
}
printf("2: Decode IV from BASE64\n");
size_t iv_bin_size = 0;
uint8_t *iv_bin_p = base64_app_decode(iv_base64_p, &iv_bin_size);
if (iv_bin_p == NULL || iv_bin_size == 0) {
printf("Failed decode IV (%zu): %s\n", strlen(iv_base64_p), iv_base64_p);
return;
}
printf("3: Apply key to aes-gcm context\n");
result = mbedtls_gcm_setkey(&aes,
MBEDTLS_CIPHER_ID_AES,
key_bin_p,
key_bin_size * 8);
if (result != 0) {
printf("Key[%zu]: ", key_bin_size);
for (size_t i = 0; i < key_bin_size; ++i) {
printf("%x ", key_bin_p[i]);
}
printf("\n");
return;
}
printf("4: Allocate memory for ciphertext\n");
const size_t data_length = strlen(data_p);
const size_t ciphertext_length = data_length + AES_GCM_APP_AES_TAG_SIZE_BYTES;
uint8_t *ciphertext_p = (uint8_t*)malloc(ciphertext_length);
if (ciphertext_p == NULL) {
printf("Failed allocate %zu bytes for ciphertext\n", ciphertext_length);
return;
}
printf("5: Encryption and authentication\n");
result = mbedtls_gcm_crypt_and_tag(&aes,
MBEDTLS_GCM_ENCRYPT,
data_length,
iv_bin_p,
iv_bin_size,
NULL,
0,
(const uint8_t*)data_p,
ciphertext_p,
AES_GCM_APP_AES_TAG_SIZE_BYTES,
ciphertext_p + data_length);
if (result != 0) {
printf("Encryption failed\n");
return;
}
//Encode data
char *encoded_ciphertext_p = NULL;
encoded_ciphertext_p = base64_app_encode(ciphertext_p, ciphertext_length);
if (encoded_ciphertext_p == NULL) {
printf("Failed encode ciphertext[%zu]:\n", ciphertext_length);
return;
}
printf("Result: %s\n", encoded_ciphertext_p);
if (strcmp(encoded_ciphertext_p, ciphertext_test_base64_p) != 0) {
printf("Wrong result!\n");
return;
}
printf("Successfully encrypted!\n");
}
void loop() {
delay(10);
}
#include "base64_app.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mbedtls/error.h"
#include "mbedtls/base64.h"
#define TAG "BASE64"
#define BASE64_APP_ERR_BUFF_LEN 128
void base64_app_print_err(const char *operation_title_p, int error_code);
size_t base64_app_get_encoded_size(size_t plain_data_size);
size_t base64_app_get_decoded_size(const char *base64_str_p);
void base64_app_print_err(const char *operation_title_p, int error_code) {
char *error_buff_p = (char *)malloc(BASE64_APP_ERR_BUFF_LEN);
if (error_buff_p == NULL) {
printf("Error: %d, operation: %s\n", error_code, operation_title_p);
return;
}
mbedtls_strerror(error_code, error_buff_p, BASE64_APP_ERR_BUFF_LEN);
printf("Error: %d, operation: %s, description: %s\n", error_code, operation_title_p, error_buff_p);
free(error_buff_p);
}
size_t base64_app_get_encoded_size(size_t plain_data_size) {
return (4 * ceil((double)plain_data_size / 3)) + 1;
}
size_t base64_app_get_decoded_size(const char *base64_str_p) {
if (base64_str_p == NULL) {
return 0;
}
size_t pad_char_count = 0;
size_t base64_str_len = strlen(base64_str_p);
if ((base64_str_len < 4) || (base64_str_len % 4 != 0)) {
return 0;
}
if (base64_str_p[base64_str_len - 1] == '=') {
pad_char_count++;
}
if (base64_str_p[base64_str_len - 2] == '=') {
pad_char_count++;
}
return (3 * (base64_str_len / 4)) - pad_char_count;
}
char *base64_app_encode(const uint8_t *data_p, size_t data_size) {
if (data_p == NULL || data_size == 0) {
printf("Wrong input params!\n");
return NULL;
}
size_t calc_encoded_size = base64_app_get_encoded_size(data_size);
char *encoded_data_p = (char *)malloc(calc_encoded_size);
if (encoded_data_p == NULL) {
return NULL;
}
size_t encode_data_length = 0;
int ret = mbedtls_base64_encode((uint8_t*)encoded_data_p,
calc_encoded_size,
&encode_data_length,
data_p,
data_size);
if (ret != 0) {
free(encoded_data_p);
base64_app_print_err("encode", ret);
return NULL;
}
return (char*)encoded_data_p;
}
uint8_t *base64_app_decode(const char *base64_str_p, size_t *decoded_data_size) {
if (decoded_data_size == NULL) {
printf("Argument (decoded_data_size): NULL\n");
return NULL;
}
if (base64_str_p == NULL) {
printf("Argument (base64_str_p): NULL!\n");
return NULL;
}
*decoded_data_size = 0;
size_t decode_buff_size = base64_app_get_decoded_size(base64_str_p);
if (decode_buff_size == 0) {
printf("BASE64 string has wrong length: %zu\n", strlen(base64_str_p));
return NULL;
}
uint8_t *decoded_buff_p = (uint8_t*)malloc(decode_buff_size);
if (decoded_buff_p == NULL) {
printf("Failed allocate memory for decode buffer\n");
return NULL;
}
size_t base64_str_len = strlen(base64_str_p);
int ret = mbedtls_base64_decode(decoded_buff_p,
decode_buff_size,
decoded_data_size,
(const uint8_t*)base64_str_p,
base64_str_len);
if (ret != 0) {
free(decoded_buff_p);
base64_app_print_err("decode", ret);
return NULL;
}
return decoded_buff_p;
}
#ifndef _BASE64_APP_H_
#define _BASE64_APP_H_
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
char *base64_app_encode(const uint8_t *data_p, size_t data_size);
uint8_t *base64_app_decode(const char *base64_str_p, size_t *decoded_data_size);
#endif // _BASE64_APP_H_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment