shufflecake/shufflecake-userland/include/header.h
2024-09-01 17:16:57 +02:00

186 lines
6.9 KiB
C

/*
* Copyright The Shufflecake Project Authors (2022)
* Copyright The Shufflecake Project Contributors (2022)
* Copyright Contributors to the The Shufflecake Project.
*
* See the AUTHORS file at the top-level directory of this distribution and at
* <https://www.shufflecake.net/permalinks/shufflecake-userland/AUTHORS>
*
* This file is part of the program shufflecake-c, which is part of the
* Shufflecake Project. Shufflecake is a plausible deniability (hidden storage)
* layer for Linux. See <https://www.shufflecake.net>.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 2 of the License, or (at your option)
* any later version. This program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the
* GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _HEADER_H_
#define _HEADER_H_
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <stdint.h>
#include <stddef.h>
#include "utils/crypto.h"
#include "utils/math.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
/* The DMB contains one IV + one VMB key + one MAC for each volume */
#define SFLC_DMB_CELL_SIZE (SFLC_AESGCM_PADDED_IVLEN + SFLC_STANDARD_KEYLEN + SFLC_AESGCM_TAGLEN)
/* Let us enforce that the one DMB can fit cells for all volumes */
#if SFLC_ARGON_SALTLEN + (SFLC_DEV_MAX_VOLUMES * SFLC_DMB_CELL_SIZE) > SFLC_BLOCK_SIZE
#error "Invalid combination of parameters: probably SFLITE_DEV_MAX_VOLUMES is too big"
#endif
// The VMB cleartext occupies the last 4064 bytes on-disk (4096 bytes minus IV and MAC)
#define SFLC_CLEAR_VMB_LEN (SFLC_BLOCK_SIZE - \
SFLC_AESGCM_PADDED_IVLEN - \
SFLC_AESGCM_TAGLEN)
/*****************************************************
* STRUCTS *
*****************************************************/
/**
* The on-disk master block of a device contains lots of crypto stuff
* (a KDF salt, IVs, MACs...) used to properly hide the VMB keys.
* This struct only contains such useful info, in the clear.
*/
typedef struct {
// Each volume's VMB key
char vmb_keys[SFLC_DEV_MAX_VOLUMES][SFLC_STANDARD_KEYLEN];
// How many of these need actually be encrypted
size_t nr_vols;
} sflc_Dmb;
/**
* When unsealing a DMB, only one VMB key can be unlocked with a password.
* An invalid value for vol_idx means no VMB key could be unlocked (wrong pwd)
*/
typedef struct {
// The unlocked VMB key
char vmb_key[SFLC_STANDARD_KEYLEN];
// The index of the volume opened by this VMB key
size_t vol_idx;
} sflc_DmbCell;
/**
* The on-disk master block of a volume contains crypto stuff
* (an IV) used to properly hide the useful info. This struct
* only contains the useful info, in the clear.
*/
typedef struct {
int mode;
// The key that encrypts the volume's data section
union {
char volume_key_lite[SFLC_AESXTS_KEYLEN];
char volume_key_legacy[SFLC_STANDARD_KEYLEN];
};
// The key that encrypts the previous volume's master block
char prev_vmb_key[SFLC_STANDARD_KEYLEN];
// The total number of logical slices virtually available to this volume
size_t nr_slices;
} sflc_Vmb;
/**
* This struct represents an encrypted empty position map. LEGACY version.
* On-disk, the layout interleaves one IV block with 256 PosMap blocks (each
* encrypted by an IV in the IV block). Many such "runs" can be concatenated,
* until the position map is big enough to index the desired number of slices.
* The last "run" might be incomplete, in that it could have less than 256
* PosMap blocks, if not all of them are needed.
* In the struct, there are as many IV blocks as there are PosMapBlock arrays
* (equal to the number of "runs"). The m-th IV of the n-th IV block encrypts
* the m-th block of the n-th array. The PosMapBlocks in an array are stored
* contiguously in RAM, so a PosMapBlock array is just a char array of length
* multiple of 4096. All the arrays are full (256 PosMapBlocks, 1 MiB) except
* for the last one, which may hold fewer blocks.
*/
typedef struct {
// The number of PosMapBlock arrays (and of IV blocks)
size_t nr_arrays;
// The sequence of IV blocks
char **iv_blocks;
// The sequence of (encrypted) PosMapBlock arrays
char **pmb_arrays;
// The number of PosMapBlocks in the last array
size_t nr_last_pmbs;
} sflegc_EncPosMap;
/*****************************************************
* INLINE FUNCTIONS *
*****************************************************/
// Starting block of a volume's position map. LITE version
static inline uint64_t sflite_pmStartBlock(size_t vol_idx, size_t nr_slices)
{
return 1 +
SFLC_DEV_MAX_VOLUMES +
vol_idx*ceil(nr_slices, SFLC_SLICE_IDX_PER_BLOCK);
}
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* "Encrypt" each VMB key with its pwd, so the DMB is ready to be written on-disk */
int sflc_dmb_seal(sflc_Dmb *dmb, char **pwds, size_t *pwd_lens, char *disk_block);
/* "Decrypt" a single VMB key from the on-disk DMB, using its password (perform the KDF) */
int sflc_dmb_unseal(char *disk_block, char *pwd, size_t pwd_len, sflc_DmbCell *dmb_cell);
/* Re-encrypt the content of a single DMB cell */
int sflc_dmb_setCell(char *disk_block, sflc_DmbCell *dmb_cell, char *pwd, size_t pwd_len);
/* "Encrypt" a VMB with a VMB key, so it's ready to be written on-disk. LITE version */
int sflite_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block);
/* "Decrypt" a VMB coming from the disk, directly using its key. LITE version */
int sflite_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb);
/* "Encrypt" a VMB with a VMB key, so it's ready to be written on-disk. LEGACY version */
int sflegc_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block);
/* "Decrypt" a VMB coming from the disk, directly using its key. LEGACY version */
int sflegc_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb);
/* Create an encrypted empty position map for the given number of slices (allocates memory). LITE version */
void *sflite_epm_create(size_t nr_slices, size_t vol_idx, char *volume_key);
/* Create an encrypted empty position map for the given number of slices (allocates memory). LEGACY version */
int sflegc_epm_create(size_t nr_slices, char *volume_key, sflegc_EncPosMap *epm);
#endif /* _HEADER_H_ */