Skip to content

Instantly share code, notes, and snippets.

@VNovytskyi
Created March 12, 2022 12:00
Show Gist options
  • Save VNovytskyi/ecb3194c8593ce8c27ddba2877bd1051 to your computer and use it in GitHub Desktop.
Save VNovytskyi/ecb3194c8593ce8c27ddba2877bd1051 to your computer and use it in GitHub Desktop.
Arduino ESP32 AES-GCM decryption with Tag
#include "base64_app.h"
#include "mbedtls/gcm.h"
#define AES_GCM_APP_AES_TAG_SIZE_BYTES 16
const char *key_p = "u56TiiWSiQ76L/t6X5C98TbATFDeUvTh5PfJsZv7H84=";
const char *iv_p = "Zidvdg8Z0bvmzr6K/hd7UQ==";
const char *ciphertext_p = "70iQkg0mqML48Y1A0Mh5TROe+qD4jX7f5jjSwo0p/MVLuG4O";
const char *plaintext_test_p = "Hello world from JS!";
mbedtls_gcm_context aes;
void setup() {
int result = 0;
printf("1st Init GCM context\n");
mbedtls_gcm_init(&aes);
printf("2nd Decode key\n");
size_t key_bin_size = 0;
uint8_t *key_bin_p = base64_app_decode(key_p, &key_bin_size);
if (key_bin_p == NULL || key_bin_size == 0) {
printf("Failed decode key\n");
return;
}
printf("3rd Apply key\n");
result = mbedtls_gcm_setkey(&aes, MBEDTLS_CIPHER_ID_AES, key_bin_p, key_bin_size * 8);
if (result != 0) {
printf("Failed set key\n");
free(key_bin_p);
return;
}
printf("4th Decode IV\n");
size_t iv_bin_size = 0;
uint8_t *iv_bin_p = base64_app_decode(iv_p, &iv_bin_size);
if (iv_bin_p == NULL || iv_bin_size == 0) {
printf("Failed decode IV\n");
free(key_bin_p);
return;
}
printf("5th Decode data from BASE64\n");
size_t ciphertext_bin_size = 0;
uint8_t *ciphertext_bin_p = base64_app_decode(ciphertext_p, &ciphertext_bin_size);
if (ciphertext_bin_p == NULL || ciphertext_bin_size == 0) {
printf("Failed decode ciphertext\n");
free(key_bin_p);
free(iv_bin_p);
return;
}
printf("6th Allocate memory for plaintext (decrypted ciphertext)\n");
const size_t ciphertext_length = ciphertext_bin_size - AES_GCM_APP_AES_TAG_SIZE_BYTES;
uint8_t *plaintext_p = (uint8_t*)malloc(ciphertext_length + 1);
if (plaintext_p == NULL) {
printf("Failed allocate memory for plaintext\n");
free(key_bin_p);
free(iv_bin_p);
return;
}
printf("7th Decryption operation\n");
result = mbedtls_gcm_auth_decrypt(&aes,
ciphertext_length,
iv_bin_p,
iv_bin_size,
NULL,
0,
ciphertext_bin_p + ciphertext_length,
AES_GCM_APP_AES_TAG_SIZE_BYTES,
ciphertext_bin_p,
plaintext_p);
if (result != 0) {
printf("Failed decrypt\n");
free(key_bin_p);
free(iv_bin_p);
free(plaintext_p);
return;
}
plaintext_p[ciphertext_length] = 0;
printf("8th Check the result\n");
if (strcmp((char*)plaintext_p, plaintext_test_p) != 0) {
printf("Failed decryption\n");
printf("%s\n", plaintext_test_p);
printf("%s\n", plaintext_p);
free(key_bin_p);
free(iv_bin_p);
free(plaintext_p);
return;
}
printf("Data: %s\n", plaintext_p);
printf("Decrypted successfully!\n");
free(key_bin_p);
free(iv_bin_p);
free(plaintext_p);
}
void loop() {
delay(1000);
}
#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