EncryptedStorage/main.c (116 lines of code) (raw):
/* Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License. */
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <applibs/log.h>
#include <applibs/storage.h>
#include "wolfssl/wolfcrypt/chacha20_poly1305.h"
static const char* MAGIC = "ENC0";
typedef struct {
uint32_t counter;
} State;
typedef struct {
char magic[4];
byte data[sizeof(State)];
byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
} Storage;
_Static_assert(sizeof(Storage) == 4 + sizeof(State) + CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE);
// ************************** IMPORTANT ************************************
// This project uses hard-coded encryption Key and IV values.
//
// THIS IS NOT SECURE. YOU SHOULD NOT DO THIS IN PRODUCTION CODE
// ************************** IMPORTANT ************************************
const byte Key[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
const byte IV[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b
};
_Static_assert(sizeof(Key) == CHACHA20_POLY1305_AEAD_KEYSIZE);
_Static_assert(sizeof(IV) == CHACHA20_POLY1305_AEAD_IV_SIZE);
// Additional authentication data for validating decryption
const char AAD[] = "Encrypted storage demo";
static State state;
static Storage storage;
enum {
SaveState_Ok = 0,
SaveState_Open = -1,
SaveState_Encrypt = -2,
SaveState_Save = -3
};
int SaveState(void )
{
memcpy(&storage.magic, MAGIC, sizeof(storage.magic));
if (wc_ChaCha20Poly1305_Encrypt(
Key, IV, AAD, sizeof(AAD),
(byte*)&state, sizeof(State),
(byte*)&storage.data, (byte*)&storage.authTag) != 0) {
Log_Debug("ERROR: Failed to encrypt state\n");
return SaveState_Encrypt;
};
int fd = Storage_OpenMutableFile();
if (fd == -1) {
Log_Debug("ERROR: Cannot open mutable storage: %s (%d)\n", strerror(errno), errno);
return SaveState_Open;
}
if (write(fd, &storage, sizeof(Storage)) != sizeof(Storage)) {
Log_Debug("ERROR: Failed to save state to mutable storage.\n");
close(fd);
return SaveState_Save;
}
close(fd);
return SaveState_Ok;
}
enum {
LoadState_Ok = 0,
LoadState_Open = -1,
LoadState_NotInit = -2,
LoadState_Magic = -3,
LoadState_Decrypt = -4,
};
int LoadState(void)
{
int fd = Storage_OpenMutableFile();
if (fd == -1) {
Log_Debug("ERROR: Cannot open mutable storage: %s (%d)\n", strerror(errno), errno);
return LoadState_Open;
}
memset(&storage, 0, sizeof(Storage));
ssize_t bytes = read(fd, &storage, sizeof(Storage));
close(fd);
if (bytes != sizeof(Storage)) {
Log_Debug("INFO: Storage not initialized\n");
return LoadState_NotInit;
}
if (memcmp(storage.magic, MAGIC, sizeof(storage.magic)) != 0) {
Log_Debug("ERROR: Storage corrupt/unreadable\n");
return LoadState_Magic;
}
if (wc_ChaCha20Poly1305_Decrypt(
Key, IV, AAD, sizeof(AAD),
storage.data, sizeof(State), storage.authTag,
(byte*)&state) != 0) {
Log_Debug("ERROR: Failed to decrypt state\n");
return LoadState_Decrypt;
}
return LoadState_Ok;
}
void LogState(void)
{
Log_Debug("Counter = %d\n", state.counter);
}
int main(void)
{
Log_Debug("Encrypted storage project\n");
Log_Debug("Loading state...\n");
int result = LoadState();
if (result == LoadState_NotInit) {
Log_Debug("Initializing state to default\n");
memset(&state, 0, sizeof(State));
}
Log_Debug("State on entry:\n");
LogState();
state.counter ++;
Log_Debug("State on exit:\n");
LogState();
Log_Debug("Saving state...\n");
return SaveState();
}