mirror of
https://codeberg.org/shufflecake/shufflecake-c.git
synced 2026-01-22 18:34:36 -05:00
186 lines
6.9 KiB
C
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_ */
|