Merge pull request 'release/v0.4.2' (#74) from release/v0.4.2 into dev

Reviewed-on: https://codeberg.org/shufflecake/shufflecake-c/pulls/74
This commit is contained in:
Tommaso Gagliardoni 2023-11-28 16:19:58 +00:00
commit 73458f429f
45 changed files with 617 additions and 768 deletions

4
.gitignore vendored
View file

@ -59,3 +59,7 @@ dkms.conf
# Shufflecake binaries
shufflecake
# Temporary working directories
dm-vvz/
disks/

View file

@ -14,6 +14,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Global constants fully shared among components through `sflc_constants.h`.
## [0.4.2] - 2023-11-28
### Fixed
- Fixed persistent slice allocation ambiguity after a volume corruption by allocating fresh slices for the corrupted volume. This is done in order to help external recovery tools (e.g. RAID).
- Fixed a bug that made the last PSI in the shuffled slice array unassignable.
- Fixed a missed deallocation problem which caused a kernel bug on volume close after some I/O errors.
- Fixed a buggy swap procedure which made the permutation of PSIs not completely random.
### Changed
- All schematics and references now consistently map array indices of size N from 0 to N-1 rather than from 1 to N.
## [0.4.1] - 2023-07-30
### Fixed

View file

@ -1,7 +1,7 @@
[![Status](resources/images/badges/badge_status_active.png)](https://codeberg.org/shufflecake/shufflecake-c) 
[![Version](resources/images/badges/badge_version_0.4.1.png)](https://codeberg.org/shufflecake/shufflecake-c/releases/tag/v0.4.1) 
[![Version](resources/images/badges/badge_version_0.4.2.png)](https://codeberg.org/shufflecake/shufflecake-c/releases/tag/v0.4.2) 
[![License](resources/images/badges/badge_license_gplv2plus.png)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) 
[![Docs whitepaper](resources/images/badges/badge_docs_whitepaper.png)](https://infoscience.epfl.ch/record/297353) 
[![Docs whitepaper](resources/images/badges/badge_docs_whitepaper.png)](https://eprint.iacr.org/2023/1529) 
[![Website](resources/images/badges/badge_web_shufflecakedotnet.png)](https://shufflecake.net/) 
[![Issue tracker](resources/images/badges/badge_community_issuetracker.png)](https://codeberg.org/shufflecake/shufflecake-c/issues) 
[![Mastodon](resources/images/badges/badge_community_mastodon.png)](https://fosstodon.org/@shufflecake) 
@ -11,7 +11,7 @@
# Shufflecake - Full C Implementation - v0.4.1
# Shufflecake - Full C Implementation - v0.4.2
_Shufflecake_ is a plausible deniability (hidden storage) layer for Linux. You can consider Shufflecake a spiritual successor of tools like TrueCrypt and VeraCrypt, but vastly improved, both in terms of security and functionality. Official website: <https://www.shufflecake.net>.
@ -47,9 +47,9 @@ __WARNING__: Shufflecake is still experimental software, please do not rely on i
In the context of Shufflecake, a _device_, or _cake_, is the underlying raw block device (e.g., a disk) that is formatted to contain hidden data, while a _volume_, or _layer_, is the logical, encrypted and hidden "partition" within a device. The device can be a whole USB stick (or disk), a physical or logical partition, a file-backed loop device, etc. (you likely find it under `/dev`).
The three operating principles of Shufflecake are:
- 1 device = multiple volumes
- 1 volume = 1 password = 1 "secrecy level"
- unlocking a volume also unlocks all those of lesser secrecy level
- 1 device = multiple volumes;
- 1 volume = 1 password = 1 "secrecy level";
- unlocking a volume also unlocks all those of lesser secrecy level.
Volumes are password-protected, and embedded in the underlying device as data _slices_ which are indistinguishable from random noise without the proper password. Headers are also indistinguishable from random when not decrypted. A Shufflecake-initialized device does not have cleartext headers, and is indistinguishable from random noise when not decrypted.
@ -59,7 +59,7 @@ Up to 15 _ordered_ Shufflecake volumes can be created on a single device, with t
Opened volumes appear as block devices of the form `sflc_N_M` in `/dev/mapper`. It is up to the user to format them with an appropriate filesystem and mounting them before use. It is recommended to always unlock the most sensitive volume for daily use ("home alone" scenario), even if that volume is not being used or even mounted. Only open a subset of volumes (with a "decoy password") if under coercion. This is due to the high possibility of corrupting hidden volumes otherwise.
For security and consistency reasons, you cannot init/open/close nested volumes within the same device one at a time; the tool only allows to perform these operations on a _chain_ of volumes in a device.
For security and consistency reasons, you cannot init/open/close nested volumes within the same device one at a time; this tool only allows to perform these operations on a _chain_ of volumes in a device.
@ -67,7 +67,7 @@ For security and consistency reasons, you cannot init/open/close nested volumes
## Installation <a id="user-content-installation"></a>
This implementation of Shufflecake consists of two components: a module for the Linux kernel (`dm-sflc`), and a `shufflecake` userland tool. Both are necessary in order to use Shufflecake. They have been tested on Linux kernel versions 6.1 (LTS), 6.2 and 6.3. The following instructions are given for Debian/Ubuntu and similar derivatives.
This implementation of Shufflecake consists of two components: a module for the Linux kernel (`dm-sflc`), and a `shufflecake` userland tool. Both are necessary in order to use Shufflecake. They have been tested on Linux kernel versions 6.1 (LTS), up to 6.5. The following instructions are given for Debian/Ubuntu and similar derivatives.
First of all, you need the kernel headers, device-mapper userspace library, and libgcrypt to compile the source. Use:
@ -80,6 +80,7 @@ Important: you have to make sure to install an up-to-date version of `libgcrypt`
```
libgcrypt-config --version
```
Also, make sure that the Kconfig options `CONFIG_CRYPTO_DRBG_HASH` (and possibly `CONFIG_CRYPTO_DRBG_CTR`) are enabled, as they are not default options in the kernel's defconfig, although they are enabled by default on some distributions such as Debian and Ubuntu.
After that, just run `make`. All the compilation artifacts will go in the respective subdirectories, and a copy of the kernel module `dm_sflc.ko` and the userland tool `shufflecake` will appear in the root directory. You can clean (delete) all these artifacts with `make clean`.
@ -93,7 +94,7 @@ Limited tests are provided to check pre-install consistency, for now they only t
### Benchmarks <a id="user-content-benchmarks"></a>
A complete benchmark suite is provided in the `benchmark-suite` directory, to test the performance of Shufflecake on a given machine and against other tools such as LUKS and VeraCrypt. Please refer to the documentation in that directory for instructions on how to run the benchmark scripts.
A complete benchmark suite is provided in the `benchmark-suite` directory, to test the performance of Shufflecake on a given system and against other tools such as LUKS and VeraCrypt. Please refer to the documentation in that directory for instructions on how to run the benchmark scripts.
@ -124,13 +125,13 @@ You can only do this if no Shufflecake volume is open.
sudo shufflecake init <block_device>
```
This command creates __N__ volume headers on the given device, each sealed by the respective provided password, by properly formatting and encrypting the first __N__ volume header slots. The number of desired volumes __N__ and the related __N__ passwords will be interactively asked at prompt. Alternatively, you can pass __N__ by command line with:
This command creates __L__ volume headers on the given device, each sealed by the respective provided password, by properly formatting and encrypting the first __L__ volume header slots. The number of desired volumes __L__ and the related __L__ passwords will be interactively asked at prompt. Alternatively, you can pass __L__ by command line with:
```
sudo shufflecake --num-volumes=N init <block_device>
sudo shufflecake --num-volumes=L init <block_device>
```
WARNING: If the device is not empty, you will lose all data stored therein. Also, adding additional volumes after initialisation is not yet supported.
__WARNING__: If the device is not empty, you will lose all data stored therein. Also, adding additional volumes after initialisation is not yet supported.
This command does not open the volumes (it does not create the virtual devices under `/dev/mapper/`), it only overwrites the device with randomness and formats the encrypted headers.
@ -230,6 +231,11 @@ Both methods works with the `init` action, and we do not have current plans to c
Please see the file `CHANGELOG.md` for a detailed history of changes.
### [0.4.2] - 2023-11-28
- Fixed persistent slice allocation ambiguity after a volume corruption by allocating fresh slices for the corrupted volume. This is done in order to help external recovery tools (e.g. RAID).
- Various bugfixes.
### [0.4.1] - 2023-07-30
- Fixed and improved benchmark scripts.
@ -255,7 +261,8 @@ Bugs and other issues are tracked at <https://codeberg.org/shufflecake/shuffleca
Outstanding known bugs:
- There is no garbage collection currently implemented, so slices remain flagged as used even if the data therein is deleted. Work is in progress to fix this.
- There is no crash consistency implemented, so if a crash happens while some volumes are live there is the risk of data loss.
- There is no garbage collection currently implemented, so slices remain flagged as used even if the data therein is deleted.

View file

@ -208,12 +208,22 @@ sflc_Device * sflc_dev_create(struct dm_target * ti, char * real_dev_path, u32 t
goto err_sysfs;
}
/* Create dm_io_client */
dev->dmio_client = dm_io_client_create();
if (IS_ERR(dev->dmio_client)) {
err = PTR_ERR(dev->dmio_client);
pr_err("Could not create dm_io_client; error %d\n", err);
goto err_dmio;
}
/* Add to device list */
list_add_tail(&dev->list_node, &sflc_dev_list);
return dev;
err_dmio:
sflc_sysfs_putDev(dev->kobj);
err_sysfs:
kfree(dev->iv_cache);
err_alloc_iv_cache:
@ -266,6 +276,9 @@ bool sflc_dev_destroy(struct dm_target * ti, sflc_Device * dev)
/* List */
list_del(&dev->list_node);
/* dm_io */
dm_io_client_destroy(dev->dmio_client);
/* Sysfs */
sflc_sysfs_putDev(dev->kobj);

View file

@ -49,6 +49,7 @@ typedef struct sflc_dev_iv_cache_entry_s sflc_dev_IvCacheEntry;
*****************************************************/
#include <linux/device-mapper.h>
#include <linux/dm-io.h>
#include "volume/volume.h"
#include "crypto/symkey/symkey.h"
@ -138,11 +139,21 @@ struct sflc_device_s
/* Sysfs stuff */
sflc_sysfs_Device * kobj;
/* DM-io */
struct dm_io_client *dmio_client;
/* We keep all devices in a list */
struct list_head list_node;
};
/*****************************************************
* MACROS *
*****************************************************/
#define sflc_dev_psiToIvBlock(dev, psi) (dev->dev_header_size + (sector_t)(psi) * SFLC_DEV_PHYS_SLICE_SIZE)
/*****************************************************
* PUBLIC VARIABLES DECLARATIONS *
*****************************************************/
@ -195,9 +206,15 @@ bool sflc_dev_removeVolume(sflc_Device * dev, int vol_idx);
to/from the provided page */
int sflc_dev_rwSector(sflc_Device * dev, struct page * page, sector_t sector, int rw);
/* Synchronously read/write entire PSI (257 blocks) to/from VMA */
int sflc_dev_rwPsi(sflc_Device *dev, void *vma, u32 psi, int rw);
/* The caller needs to hold slices_lock to call these functions */
/* Checks if PSI is free */
bool sflc_dev_isPsiFree(sflc_Device *dev, u32 psi);
/* Sets the PSI as owned by the given volume (also decreases free_slices).
* Returns < 0 if already taken. */
int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx);

View file

@ -36,11 +36,6 @@
/* Capacity of IV cache */
#define SFLC_DEV_IV_CACHE_CAPACITY 1024
/*****************************************************
* MACROS *
*****************************************************/
#define sflc_dev_psiToIvBlockSector(dev, psi) (dev->dev_header_size + (sector_t)(psi) * SFLC_DEV_PHYS_SLICE_SIZE)
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
@ -276,7 +271,7 @@ static sflc_dev_IvCacheEntry * sflc_dev_newIvCacheEntry(sflc_Device * dev, u32 p
/* Read from disk */
/* Position on disk */
sector = sflc_dev_psiToIvBlockSector(dev, psi);
sector = sflc_dev_psiToIvBlock(dev, psi);
/* Read */
err = sflc_dev_rwSector(dev, entry->iv_page, sector, READ);
@ -305,7 +300,7 @@ static int sflc_dev_destroyIvCacheEntry(sflc_Device * dev, sflc_dev_IvCacheEntry
/* Write to disk */
/* Position on disk */
sector = sflc_dev_psiToIvBlockSector(dev, entry->psi);
sector = sflc_dev_psiToIvBlock(dev, entry->psi);
/* Write (if necessary) */
if (entry->dirtyness) {

View file

@ -30,6 +30,7 @@
#include "log/log.h"
#include <linux/bio.h>
#include <linux/dm-io.h>
#include <linux/errno.h>
/*****************************************************
@ -81,6 +82,30 @@ out:
return err;
}
/* Synchronously read/write entire PSI (257 blocks) to/from VMA */
int sflc_dev_rwPsi(sflc_Device *dev, void *vma, u32 psi, int rw)
{
struct dm_io_request io_req = {
.bi_opf = ((rw == READ) ? REQ_OP_READ : REQ_OP_WRITE) | REQ_SYNC,
.mem.type = DM_IO_VMA,
.mem.offset = 0,
.mem.ptr.vma = vma,
.notify.fn = NULL,
.client = dev->dmio_client
};
struct dm_io_region io_reg = {
.bdev = dev->bdev->bdev,
.sector = sflc_dev_psiToIvBlock(dev, psi) * SFLC_DEV_SECTOR_SCALE,
.count = SFLC_DEV_PHYS_SLICE_SIZE * SFLC_DEV_SECTOR_SCALE
};
return dm_io(&io_req, 1, &io_reg, NULL);
}
/*****************************************************
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/

View file

@ -41,12 +41,18 @@
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/* Checks if PSI is free */
bool sflc_dev_isPsiFree(sflc_Device *dev, u32 psi)
{
return ((psi < dev->tot_slices) &&
(dev->rmap[psi] == SFLC_DEV_RMAP_INVALID_VOL));
}
/* Sets the PSI as owned by the given volume (also decreases free_slices).
* Returns < 0 if already taken. */
int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx)
{
u8 prev_vol_idx;
/* Bounds check */
if (psi >= dev->tot_slices) {
pr_err("Requested to set ownership for invalid PSI\n");
@ -54,8 +60,7 @@ int sflc_dev_markPsiTaken(sflc_Device * dev, u32 psi, u8 vol_idx)
}
/* Check that it's free */
prev_vol_idx = dev->rmap[psi];
if (prev_vol_idx != SFLC_DEV_RMAP_INVALID_VOL) {
if (dev->rmap[psi] != SFLC_DEV_RMAP_INVALID_VOL) {
pr_err("Requested to set ownership for already-owned PSI\n");
return -EINVAL;
}
@ -82,13 +87,14 @@ s32 sflc_dev_getNextRandomFreePsi(sflc_Device * dev)
/* Repeatedly advance the counter in the shuffled array
* until you find a free one */
do {
psi = dev->shuffled_psi_array[dev->shuffled_psi_ctr];
dev->shuffled_psi_ctr += 1;
if (dev->shuffled_psi_ctr >= dev->tot_slices) {
pr_err("Double catastrophe! No free PSIs on the device, and didn't catch it before!\n");
pr_err("Double catastrophe! No free PSIs on the device, "
"and didn't catch it before!\n");
return -ENOSPC;
}
psi = dev->shuffled_psi_array[dev->shuffled_psi_ctr];
dev->shuffled_psi_ctr += 1;
} while (dev->rmap[psi] != SFLC_DEV_RMAP_INVALID_VOL);
return psi;

View file

@ -31,7 +31,7 @@
#define SFLC_VER_MAJOR 0
#define SFLC_VER_MINOR 4
#define SFLC_VER_REVISION 2
#define SFLC_VER_SPECIAL "rc1"
#define SFLC_VER_SPECIAL ""
#define STRINGIFY0(s) # s
#define STRINGIFY(s) STRINGIFY0(s)

View file

@ -51,10 +51,10 @@ int sflc_vec_u32shuffle(u32 *v, u32 len)
return j;
}
/* Swap v[i] and v[j] (without third variable 'cuz we're cool) */
v[i] ^= v[j]; // v[i] <- a XOR b
v[j] ^= v[i]; // v[j] <- b XOR (a XOR b) = a
v[i] ^= v[j]; // v[i] <- (a XOR b) XOR a = b
/* Swap v[i] and v[j] */
u32 tmp = v[i];
v[i] = v[j];
v[j] = tmp;
}
return 0;

View file

@ -29,6 +29,8 @@
* INCLUDE SECTION *
*****************************************************/
#include <linux/vmalloc.h>
#include "volume.h"
#include "crypto/rand/rand.h"
#include "utils/pools.h"
@ -43,6 +45,7 @@
*****************************************************/
static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op);
static int sflc_vol_reassignLsi(sflc_Volume *vol, u32 lsi, u32 old_psi);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
@ -178,16 +181,36 @@ int sflc_vol_loadFmap(sflc_Volume * vol)
__be32 * be_psi = (void *) (data_ptr + (k * sizeof(__be32)));
u32 psi = be32_to_cpu(*be_psi);
/* Add mapping to the volume's fmap */
vol->fmap[lsi] = psi;
/* Also add it to the device's rmap and to the count, if LSI is actually mapped */
if (psi != SFLC_VOL_FMAP_INVALID_PSI) {
sflc_dev_markPsiTaken(dev, psi, vol->vol_idx);
vol->mapped_slices += 1;
/* If unassigned, just move on */
if (psi == SFLC_VOL_FMAP_INVALID_PSI) {
vol->fmap[lsi] = psi;
/* Next iteration */
lsi += 1;
continue;
}
/* Next iteration */
lsi += 1;
/* If already assigned to lower-order volume, sample a new one */
if (!sflc_dev_isPsiFree(dev, psi)) {
pr_warn("Corruption of volume %d: LSI %u was evicted from PSI %u\n",
vol->vol_idx, lsi, psi);
err = sflc_vol_reassignLsi(vol, lsi, psi);
if (err) {
pr_err("Could not reassign evicted LSI; "
"error %d\n", err);
goto out;
}
/* Next iteration */
lsi += 1;
} else {
/* Just assign */
vol->fmap[lsi] = psi;
sflc_dev_markPsiTaken(dev, psi, vol->vol_idx);
vol->mapped_slices += 1;
/* Next iteration */
lsi += 1;
}
}
}
}
@ -374,3 +397,58 @@ static s32 sflc_vol_mapSlice(sflc_Volume * vol, u32 lsi, int op)
return psi;
}
static int sflc_vol_reassignLsi(sflc_Volume *vol, u32 lsi, u32 old_psi)
{
sflc_Device *dev = vol->dev;
s32 new_psi;
// void *vma;
int err;
// /* Allocate array holding the raw PSI */
// vma = vmalloc(SFLC_DEV_PHYS_SLICE_SIZE * SFLC_DEV_SECTOR_SIZE);
// if (!vma) {
// pr_err("Could not allocate VMA for raw PSI");
// return -ENOMEM;
// }
/* Sample new PSI */
new_psi = sflc_dev_getNextRandomFreePsi(dev);
if (new_psi < 0) {
err = new_psi;
pr_err("Could not sample new PSI for evicted LSI; "
"error %d\n", err);
goto out;
}
// /* Read PSI contents */
// err = sflc_dev_rwPsi(dev, vma, old_psi, READ);
// if (err) {
// pr_err("Could not read PSI; error %d", err);
// goto out;
// }
//
// /* Write them to new location */
// err = sflc_dev_rwPsi(dev, vma, new_psi, WRITE);
// if (err) {
// pr_err("Could not write PSI; error %d", err);
// goto out;
// }
/* Assign */
vol->fmap[lsi] = new_psi;
sflc_dev_markPsiTaken(dev, new_psi, vol->vol_idx);
vol->mapped_slices += 1;
pr_notice("Volume %d reassign LSI %u -> PSI %u",
vol->vol_idx, lsi, new_psi);
/* No prob */
err = 0;
out:
// vfree(vma);
return err;
}

View file

@ -119,6 +119,7 @@ err_alloc_phys_bio:
orig_bio->bi_status = BLK_STS_IOERR;
bio_endio(orig_bio);
mempool_free(write_work, sflc_pools_writeWorkPool);
return;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Before After
Before After

View file

@ -28,8 +28,8 @@
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.3719136"
inkscape:cx="472.69741"
inkscape:cy="228.14848"
inkscape:cx="531.73902"
inkscape:cy="354.24971"
inkscape:window-width="1920"
inkscape:window-height="979"
inkscape:window-x="0"
@ -294,11 +294,12 @@
<rect
style="fill:#ffb2b6;fill-opacity:1;stroke:none;stroke-width:0.145256;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
id="rect1410"
width="36.681602"
height="4.3625588"
width="34.647751"
height="4.1206689"
x="106.3613"
y="90.178604"
ry="2.1812794" />
ry="2.0600297"
rx="2.1743569" />
<path
style="fill:none;stroke:#000000;stroke-width:0.28408;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2)"
d="m 109.17799,81.537158 c 1.21161,0.968319 2.57918,1.741071 4.0338,2.279329 1.37317,0.508119 2.82345,0.807304 4.2856,0.8841"
@ -439,7 +440,7 @@
id="tspan3498"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="118.1378"
y="56.927811">1</tspan></text>
y="56.927811">0</tspan></text>
<rect
style="fill:#bda411;fill-opacity:1;stroke:none;stroke-width:0.103534;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect515-6-2-4"
@ -473,7 +474,7 @@
id="tspan3535"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="125.50976"
y="56.927811">1</tspan></text>
y="56.927811">0</tspan></text>
<text
xml:space="preserve"
style="font-size:2.64855px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.110355"
@ -513,7 +514,7 @@
id="tspan3549"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="133.44423"
y="56.927811">2</tspan></text>
y="56.927811">1</tspan></text>
<rect
style="fill:#bda411;fill-opacity:1;stroke:none;stroke-width:0.103534;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect3553"
@ -547,7 +548,7 @@
id="tspan3561"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="140.81618"
y="56.927811">2</tspan></text>
y="56.927811">1</tspan></text>
<rect
style="fill:#b9009c;fill-opacity:1;stroke:none;stroke-width:0.110622;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect3565"
@ -576,7 +577,7 @@
id="tspan3571"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="153.58623"
y="56.927811">15</tspan></text>
y="56.927811">14</tspan></text>
<rect
style="fill:#bda411;fill-opacity:1;stroke:none;stroke-width:0.103534;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect3575"
@ -610,7 +611,7 @@
id="tspan3583"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="160.90143"
y="56.927811">15</tspan></text>
y="56.927811">14</tspan></text>
<text
xml:space="preserve"
style="font-size:2.64855px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.110355"
@ -719,7 +720,7 @@
id="tspan5992"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="75.125397"
y="69.415131">15</tspan></text>
y="69.415131">14</tspan></text>
<rect
style="fill:#2692ab;fill-opacity:1;stroke:none;stroke-width:0.105515;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect5996"
@ -748,7 +749,7 @@
id="tspan6002"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="82.510414"
y="69.415131">15</tspan></text>
y="69.415131">14</tspan></text>
<text
xml:space="preserve"
style="font-size:3.42442px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.142684"
@ -835,7 +836,7 @@
id="tspan11132"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0442088"
x="67.830742"
y="86.697533">2</tspan></text>
y="86.697533">1</tspan></text>
<text
xml:space="preserve"
style="font-size:2.64855px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.110355"
@ -936,7 +937,7 @@
id="tspan11132-6"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0442088"
x="53.774185"
y="78.100777">2</tspan></text>
y="78.100777">1</tspan></text>
<text
xml:space="preserve"
style="font-size:2.1461px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0894191"
@ -947,7 +948,7 @@
id="tspan11132-5"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0894191"
x="48.133003"
y="88.452538">2</tspan></text>
y="88.452538">1</tspan></text>
<text
xml:space="preserve"
style="font-size:1.69304px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0705427"
@ -969,39 +970,39 @@
id="tspan2367"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0705427"
x="113.53406"
y="92.950294">VMBkey</tspan></text>
y="92.950294">VMK</tspan></text>
<text
xml:space="preserve"
style="font-size:1.3753px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
x="120.27604"
x="117.41192"
y="93.41362"
id="text2379"><tspan
sodipodi:role="line"
id="tspan2377"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
x="120.27604"
y="93.41362">1</tspan></text>
x="117.41192"
y="93.41362">0</tspan></text>
<text
xml:space="preserve"
style="font-size:1.69304px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0705427"
x="123.37743"
x="120.51331"
y="92.950294"
id="text2383"><tspan
sodipodi:role="line"
id="tspan2381"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0705427"
x="123.37743"
x="120.51331"
y="92.950294">NumSlices</tspan></text>
<text
xml:space="preserve"
style="font-size:1.69304px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0705427"
x="133.80531"
x="130.94119"
y="92.950294"
id="text2391"><tspan
sodipodi:role="line"
id="tspan2389"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0705427"
x="133.80531"
x="130.94119"
y="92.950294">Metadata</tspan></text>
<text
xml:space="preserve"
@ -1028,46 +1029,46 @@
<text
xml:space="preserve"
style="font-size:2.91175px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
x="121.6461"
x="118.78199"
y="93.040558"
id="text2415"><tspan
sodipodi:role="line"
id="tspan2413"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
x="121.6461"
x="118.78199"
y="93.040558">|</tspan></text>
<text
xml:space="preserve"
style="font-size:2.91175px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
x="122.03333"
x="119.16922"
y="93.040558"
id="text2419"><tspan
sodipodi:role="line"
id="tspan2417"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
x="122.03333"
x="119.16922"
y="93.040558">|</tspan></text>
<text
xml:space="preserve"
style="font-size:2.91175px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
x="132.24149"
x="129.37737"
y="93.040558"
id="text2423"><tspan
sodipodi:role="line"
id="tspan2421"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
x="132.24149"
x="129.37737"
y="93.040558">|</tspan></text>
<text
xml:space="preserve"
style="font-size:2.91175px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
x="132.62868"
x="129.76456"
y="93.040558"
id="text2427"><tspan
sodipodi:role="line"
id="tspan2425"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
x="132.62868"
x="129.76456"
y="93.040558">|</tspan></text>
<text
xml:space="preserve"
@ -1120,7 +1121,7 @@
id="tspan1258"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#000000;fill-opacity:1;stroke-width:0.06904"
x="104.21696"
y="81.268738">2</tspan></text>
y="81.268738">1</tspan></text>
<text
xml:space="preserve"
style="font-size:1.65698px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
@ -1131,7 +1132,7 @@
id="tspan1262"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="109.59264"
y="81.023582">2</tspan></text>
y="81.023582">1</tspan></text>
<text
xml:space="preserve"
style="font-size:1.65698px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
@ -1142,7 +1143,7 @@
id="tspan1266"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="125.83566"
y="81.023582">2</tspan></text>
y="81.023582">1</tspan></text>
<text
xml:space="preserve"
style="font-size:1.3753px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
@ -1153,18 +1154,18 @@
id="tspan1270"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
x="110.81011"
y="93.41362">2</tspan></text>
y="93.41362">1</tspan></text>
<text
xml:space="preserve"
style="font-size:1.3753px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
x="141.30383"
x="138.43971"
y="93.41362"
id="text1388"><tspan
sodipodi:role="line"
id="tspan1386"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
x="141.30383"
y="93.41362">2</tspan></text>
x="138.43971"
y="93.41362">1</tspan></text>
<text
xml:space="preserve"
style="font-size:0.850423px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke-width:0.0354338"
@ -1238,7 +1239,7 @@
id="tspan2382"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="142.79185"
y="69.512749">2</tspan></text>
y="69.512749">1</tspan></text>
<text
xml:space="preserve"
style="font-size:1.65698px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
@ -1249,7 +1250,7 @@
id="tspan2386"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="155.51334"
y="69.512749">2</tspan></text>
y="69.512749">1</tspan></text>
<text
xml:space="preserve"
style="font-size:0.850423px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke-width:0.0354338"
@ -1296,8 +1297,8 @@
<rect
style="fill:#fde584;fill-opacity:1;stroke:none;stroke-width:0.127453;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
id="rect2530"
width="30.182928"
height="4.0817685"
width="31.441154"
height="4.0817719"
x="143.86957"
y="79.817894"
ry="2.0408843" />
@ -1329,7 +1330,7 @@
id="tspan2600"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
x="147.63687"
y="82.810692">1</tspan></text>
y="82.810692">0</tspan></text>
<text
xml:space="preserve"
style="font-size:1.69304px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0705427"
@ -1351,7 +1352,7 @@
id="tspan5116"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
x="153.96996"
y="82.810692">2</tspan></text>
y="82.810692">1</tspan></text>
<text
xml:space="preserve"
style="font-size:2.91175px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.121321"
@ -1395,7 +1396,7 @@
id="tspan5140"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#0000ff;fill-opacity:1;stroke-width:0.0573041"
x="166.20279"
y="82.810692">NumSlices</tspan></text>
y="82.810692">NumSlices-1</tspan></text>
<text
xml:space="preserve"
style="font-size:1.69304px;line-height:1.25;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke-width:0.0705427"
@ -1477,7 +1478,7 @@
id="tspan5436"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#000000;fill-opacity:1;stroke-width:0.06904"
x="179.39532"
y="71.868858">2</tspan></text>
y="71.868858">1</tspan></text>
<rect
style="fill:#0028ff;fill-opacity:1;stroke:none;stroke-width:0.0862688;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect572"
@ -1506,7 +1507,7 @@
id="tspan578"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="59.015289"
y="69.415131">2</tspan></text>
y="69.415131">1</tspan></text>
<rect
style="fill:#2692ab;fill-opacity:1;stroke:none;stroke-width:0.105515;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect582"
@ -1535,7 +1536,7 @@
id="tspan588"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="66.513161"
y="69.415131">2</tspan></text>
y="69.415131">1</tspan></text>
<rect
style="fill:#2dc895;fill-opacity:1;stroke:none;stroke-width:0.0954515;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect698"
@ -1658,7 +1659,7 @@
id="tspan746"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="46.629761"
y="69.415131">1</tspan></text>
y="69.415131">0</tspan></text>
<rect
style="fill:#2692ab;fill-opacity:1;stroke:none;stroke-width:0.105515;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect750"
@ -1687,7 +1688,7 @@
id="tspan756"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.06904"
x="54.127636"
y="69.415131">1</tspan></text>
y="69.415131">0</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:0.272535;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2)"
d="m 40.374289,70.026319 v 4.856042"

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -25,9 +25,9 @@
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.9401788"
inkscape:cx="266.21258"
inkscape:cy="181.94199"
inkscape:zoom="5.4876543"
inkscape:cx="309.14848"
inkscape:cy="248.92238"
inkscape:window-width="1920"
inkscape:window-height="979"
inkscape:window-x="0"
@ -330,7 +330,7 @@
height="5.2916675"
x="61.548569"
y="72.206657"
inkscape:export-filename="badge_version_0.4.1.png"
inkscape:export-filename="badge_version_0.4.2.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96" />
<text
@ -361,6 +361,6 @@
id="tspan462"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.183262"
x="79.882088"
y="76.044922">0.4.1</tspan></text>
y="76.044922">0.4.2</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

View file

@ -29,7 +29,7 @@
PROJ_SRCS := $(addprefix utils/,crypto.c disk.c dm.c file.c string.c input.c)
PROJ_SRCS += $(addprefix header/,position_map.c volume_master_block.c device_master_block.c)
PROJ_SRCS += $(addprefix operations/,create_vol.c open_vol.c close_vol.c dmb.c)
PROJ_SRCS += $(addprefix operations/,volume_header.c devmapper.c dmb.c)
PROJ_SRCS += $(addprefix commands/,init.c open.c close.c test_pwd.c change_pwd.c)
PROJ_SRCS += $(addprefix cli/,dispatch.c init.c open.c close.c testpwd.c changepwd.c)
PROJ_SRCS += main.c

View file

@ -21,8 +21,8 @@
* If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _CLI_CLI_H_
#define _CLI_CLI_H_
#ifndef _CLI_H_
#define _CLI_H_
/*****************************************************
@ -60,6 +60,6 @@ int sflc_cli_testPwd(char *block_device);
int sflc_cli_changePwd(char *block_device);
#endif /* _CLI_CLI_H_ */
#endif /* _CLI_H_ */

View file

@ -21,8 +21,8 @@
* If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _COMMANDS_COMMANDS_H_
#define _COMMANDS_COMMANDS_H_
#ifndef _COMMANDS_H_
#define _COMMANDS_H_
/*****************************************************
@ -33,7 +33,7 @@
#include <stddef.h>
#include <stdbool.h>
#include "header/device_master_block.h"
#include "header.h"
/*****************************************************
@ -110,4 +110,4 @@ int sflc_cmd_testPwd(sflc_cmd_OpenArgs *args, sflc_DmbCell *dmb_cell);
int sflc_cmd_changePwd(sflc_cmd_ChangePwdArgs *args);
#endif /* _COMMANDS_COMMANDS_H_ */
#endif /* _COMMANDS_H_ */

View file

@ -21,12 +21,8 @@
* If not, see <https://www.gnu.org/licenses/>.
*/
/*
* Defines the Device Master Block (DMB) and related functionalities
*/
#ifndef _HEADER_DEVICE_MASTER_BLOCK_H_
#define _HEADER_DEVICE_MASTER_BLOCK_H_
#ifndef _HEADER_H_
#define _HEADER_H_
/*****************************************************
@ -36,7 +32,6 @@
#include <stdint.h>
#include <stddef.h>
#include "utils/disk.h"
#include "utils/crypto.h"
@ -53,14 +48,21 @@
#endif
// The VMB cleartext occupies the last 4064 bytes on-disk (4096 bytes minus IV and MAC)
#define SFLC_CLEAR_VMB_LEN (SFLC_SECTOR_SIZE - \
SFLC_AESGCM_PADDED_IVLEN - \
SFLC_AESGCM_TAGLEN)
/*****************************************************
* STRUCTS *
*****************************************************/
/**
* The on-disk master block of a volume contains lots of crypto stuff
* 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.
* This struct only contains such useful info, in the clear.
*/
typedef struct {
// Each volume's VMB key
@ -71,6 +73,7 @@ typedef struct {
} 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)
@ -85,18 +88,74 @@ typedef struct {
} 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 {
// The key that encrypts the volume's data section
char volume_key[SFLC_CRYPTO_KEYLEN];
// The key that encrypts the previous volume's master block
char prev_vmb_key[SFLC_CRYPTO_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.
* 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;
} sflc_EncPosMap;
/*****************************************************
* 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 the specified 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);
#endif /* _HEADER_DEVICE_MASTER_BLOCK_H_ */
/* "Encrypt" a VMB with a VMB key, so it's ready to be written on-disk */
int sflc_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block);
/* "Decrypt" a VMB coming from the disk, directly using its key */
int sflc_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) */
int sflc_epm_create(size_t nr_slices, char *volume_key, sflc_EncPosMap *epm);
#endif /* _HEADER_H_ */

View file

@ -1,76 +0,0 @@
/*
* 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/>.
*/
/*
* Helpers to encrypt an empty position map
*/
#ifndef _HEADER_POSITION_MAP_H_
#define _HEADER_POSITION_MAP_H_
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <stdint.h>
#include <stddef.h>
/*****************************************************
* STRUCTS *
*****************************************************/
/**
* This struct represents an encrypted empty position map.
* There are as many IV blocks as there are PosMapBlock arrays.
* 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 contiguous, 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;
} sflc_EncPosMap;
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* Create an encrypted empty position map for the given number of slices (allocates memory) */
int sflc_epm_create(size_t nr_slices, char *volume_key, sflc_EncPosMap *epm);
#endif /* _HEADER_POSITION_MAP_H_ */

View file

@ -1,87 +0,0 @@
/*
* 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/>.
*/
/*
* Defines the Volume Master Block (VMB) and related functionalities
*/
#ifndef _HEADER_VOLUME_MASTER_BLOCK_H_
#define _HEADER_VOLUME_MASTER_BLOCK_H_
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <stdint.h>
#include <stddef.h>
#include "utils/disk.h"
#include "utils/crypto.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
// The VMB cleartext occupies the last 4064 bytes on-disk (4096 bytes minus IV and MAC)
#define SFLC_CLEAR_VMB_LEN (SFLC_SECTOR_SIZE - \
SFLC_AESGCM_PADDED_IVLEN - \
SFLC_AESGCM_TAGLEN)
/*****************************************************
* STRUCTS *
*****************************************************/
/**
* The on-disk master block of a volume contains crypto stuff
* (IVs, MACs...) used to properly hide the useful
* info. This struct only contains the useful info.
*/
typedef struct {
// The key that encrypts the volume's data section
char volume_key[SFLC_CRYPTO_KEYLEN];
// The key that encrypts the previous volume's master block
char prev_vmb_key[SFLC_CRYPTO_KEYLEN];
// The total number of logical slices virtually available to this volume
uint32_t nr_slices;
} sflc_VolumeMasterBlock;
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* "Encrypt" a VMB with a VMB key, so it's ready to be written on-disk */
int sflc_vmb_seal(sflc_VolumeMasterBlock *vmb, char *vmb_key, char *disk_block);
/* "Decrypt" a VMB coming from the disk, directly using its key */
int sflc_vmb_unseal(char *disk_block, char *vmb_key, sflc_VolumeMasterBlock *vmb);
#endif /* _HEADER_VOLUME_MASTER_BLOCK_H_ */

View file

@ -21,12 +21,8 @@
* If not, see <https://www.gnu.org/licenses/>.
*/
/*
* Defines the Volume, and the basic operations that can be done on a single one
*/
#ifndef _OPERATIONS_VOLUME_H_
#define _OPERATIONS_VOLUME_H_
#ifndef _OPERATIONS_H_
#define _OPERATIONS_H_
/*****************************************************
@ -36,47 +32,11 @@
#include <stdint.h>
#include <stddef.h>
#include "utils/disk.h"
#include "header.h"
#include "utils/crypto.h"
#include "utils/math.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
/*****************************************************
* STRUCTS *
*****************************************************/
/**
* Struct representing a volume.
* The functions in this module take a partially-filled struct in input
* and fill some more fields in it as part of their output.
*/
typedef struct {
// Keys
char vmb_key[SFLC_CRYPTO_KEYLEN];
char volume_key[SFLC_CRYPTO_KEYLEN];
char prev_vmb_key[SFLC_CRYPTO_KEYLEN];
// Number of slices
size_t nr_slices;
// ID of the underlying block device
size_t dev_id;
// Index of this volume in the underlying block device
size_t vol_idx;
// Underlying block device
char *bdev_path;
// Volume name under /dev/mapper/
char label[SFLC_MAX_VOL_NAME_LEN + 1];
} sflc_Volume;
/*****************************************************
* INLINE FUNCTIONS *
*****************************************************/
@ -94,9 +54,9 @@ static inline size_t sflc_volHeaderSize(size_t nr_slices)
}
// Position of the VMB for the given volume
static inline uint64_t sflc_vmbPosition(sflc_Volume *vol)
static inline uint64_t sflc_vmbPosition(size_t vol_idx, size_t nr_slices)
{
return 1 + ((uint64_t) vol->vol_idx) * ((uint64_t) sflc_volHeaderSize(vol->nr_slices));
return 1 + ((uint64_t) vol_idx) * ((uint64_t) sflc_volHeaderSize(nr_slices));
}
@ -104,13 +64,21 @@ static inline uint64_t sflc_vmbPosition(sflc_Volume *vol)
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* Writes a volume header (VMB+PM) on-disk */
int sflc_ops_createVolume(sflc_Volume *vol);
/* Encrypts and writes the DMB to disk */
int sflc_ops_writeDmb(char *bdev_path, char **pwds, size_t *pwd_lens, sflc_Dmb *dmb);
/* Reads the DMB from disk and outputs the unlocked VMB key */
int sflc_ops_readDmb(char *bdev_path, char *pwd, size_t pwd_len, sflc_DmbCell *dmb_cell);
/* Reads the DMB from disk, changes the relevant DMB cell, and writes it back */
int sflc_ops_rewriteDmbCell(char *bdev_path, sflc_DmbCell *dmb_cell, char *new_pwd, size_t new_pwd_len);
/* Read a VMB from disk and issue a DM ioctl to create the appropriate virtual device */
int sflc_ops_openVolume(sflc_Volume *vol);
/* Encrypts and writes a volume header (VMB+PM) on-disk */
int sflc_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, size_t vol_idx);
/* Reads a VMB from disk and unlocks it */
int sflc_ops_readVmb(char *bdev_path, char *vmb_key, size_t nr_slices, size_t vol_idx, sflc_Vmb *vmb);
/* Build parameter list for ctor in dm_sflc, and send DM ioctl to create virtual block device */
int sflc_ops_openVolume(char *bdev_path, size_t dev_id, size_t vol_idx, sflc_Vmb *vmb);
/* Close the volume via the appropriate ioctl to DM */
int sflc_ops_closeVolume(char *label);
#endif /* _OPERATIONS_VOLUME_H_ */
#endif /* _OPERATIONS_H_ */

View file

@ -1,62 +0,0 @@
/*
* 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/>.
*/
/*
* Global operations on the device
*/
#ifndef _OPERATIONS_DEVICE_H_
#define _OPERATIONS_DEVICE_H_
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <stdint.h>
#include <stddef.h>
#include "header/device_master_block.h"
#include "utils/disk.h"
#include "utils/crypto.h"
/*****************************************************
* CONSTANTS *
*****************************************************/
/*****************************************************
* PUBLIC FUNCTIONS PROTOTYPES *
*****************************************************/
/* Samples VMB keys and writes the corresponding DMB to disk */
int sflc_ops_createAndWriteDmb(char *bdev_path, char **pwds, size_t *pwd_lens, sflc_Dmb *dmb);
/* Reads the DMB from disk and outputs the unlocked VMB key */
int sflc_ops_readDmb(char *bdev_path, char *pwd, size_t pwd_len, sflc_DmbCell *dmb_cell);
/* Reads the DMB from disk, changes the relevant DMB cell, and writes it back */
int sflc_ops_reencryptDmbCellAndWrite(char *bdev_path, sflc_DmbCell *dmb_cell, char *new_pwd, size_t new_pwd_len);
#endif /* _OPERATIONS_DEVICE_H_ */

View file

@ -51,7 +51,7 @@
/* Max total number of open devices at any given time */
#define SFLC_TOT_MAX_DEVICES 1024
/* A volume name is sflc-<devID>-<volIdx> */
/* A volume name is sflc_<devID>_<volIdx> */
#define SFLC_MAX_VOL_NAME_LEN 15
/* A slice index is represented over 32 bits */

View file

@ -29,8 +29,8 @@
#include <errno.h>
#include <stdlib.h>
#include "cli/cli.h"
#include "commands/commands.h"
#include "cli.h"
#include "commands.h"
#include "utils/sflc.h"
#include "utils/input.h"
#include "utils/log.h"

View file

@ -29,8 +29,8 @@
#include <errno.h>
#include <stdlib.h>
#include "cli/cli.h"
#include "commands/commands.h"
#include "cli.h"
#include "commands.h"
#include "utils/sflc.h"
#include "utils/input.h"
#include "utils/log.h"

View file

@ -31,7 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "cli/cli.h"
#include "cli.h"
#include "utils/sflc.h"
#include "utils/disk.h"
#include "utils/log.h"

View file

@ -29,8 +29,8 @@
#include <errno.h>
#include <stdlib.h>
#include "cli/cli.h"
#include "commands/commands.h"
#include "cli.h"
#include "commands.h"
#include "utils/sflc.h"
#include "utils/input.h"
#include "utils/log.h"
@ -88,11 +88,11 @@ int sflc_cli_init(char *block_device, int num_volumes, int skip_randfill)
"volume 0 (the least secret) to volume %lu (the most secret).\n\n", args.nr_vols - 1);
size_t i;
for (i = 0; i < args.nr_vols; i++) {
// Allocate pwd TODO: USE SECURE INPUT METHOD FOR PASSWORDS
// Allocate pwd
pwds[i] = malloc(SFLC_BIGBUFSIZE);
/* Read it */
printf("Choose password for volume %lu: ", i);
printf("Choose password for volume %lu (must not be empty): ", i);
err = sflc_safeReadLine(pwds[i], SFLC_BIGBUFSIZE);
if (err) {
sflc_log_error("Could not read password for volume %lu; error %d", i, err);
@ -101,6 +101,11 @@ int sflc_cli_init(char *block_device, int num_volumes, int skip_randfill)
/* You can trust the length of strings input this way */
pwd_lens[i] = strlen(pwds[i]);
/* Check non-empty */
if (pwd_lens[i] == 0) {
sflc_log_error("Password cannot be empty!");
return EINVAL;
}
}
/* Assign them */
args.pwds = pwds;

View file

@ -29,8 +29,8 @@
#include <errno.h>
#include <stdlib.h>
#include "cli/cli.h"
#include "commands/commands.h"
#include "cli.h"
#include "commands.h"
#include "utils/sflc.h"
#include "utils/input.h"
#include "utils/log.h"
@ -63,6 +63,11 @@ int sflc_cli_open(char *block_device)
}
/* You can trust the length of strings input this way */
pwd_len = strlen(pwd);
/* Check non-empty */
if (pwd_len == 0) {
sflc_log_error("Password cannot be empty!");
return EINVAL;
}
/* Assign them */
args.pwd = pwd;
args.pwd_len = pwd_len;

View file

@ -29,8 +29,8 @@
#include <errno.h>
#include <stdlib.h>
#include "cli/cli.h"
#include "commands/commands.h"
#include "cli.h"
#include "commands.h"
#include "utils/sflc.h"
#include "utils/input.h"
#include "utils/log.h"

View file

@ -29,9 +29,8 @@
#include <stdlib.h>
#include <stdint.h>
#include "commands/commands.h"
#include "operations/volume.h"
#include "operations/device.h"
#include "commands.h"
#include "operations.h"
#include "utils/sflc.h"
#include "utils/crypto.h"
#include "utils/file.h"
@ -55,5 +54,5 @@
int sflc_cmd_changePwd(sflc_cmd_ChangePwdArgs *args)
{
/* Delegate entirely to the function reading the DMB */
return sflc_ops_reencryptDmbCellAndWrite(args->bdev_path, args->dmb_cell, args->new_pwd, args->new_pwd_len);
return sflc_ops_rewriteDmbCell(args->bdev_path, args->dmb_cell, args->new_pwd, args->new_pwd_len);
}

View file

@ -29,8 +29,8 @@
#include <stdint.h>
#include <stdlib.h>
#include "commands/commands.h"
#include "operations/volume.h"
#include "commands.h"
#include "operations.h"
#include "utils/sflc.h"
#include "utils/crypto.h"
#include "utils/string.h"
@ -45,7 +45,7 @@
/* Reads the list of volumes from sysfs */
static int _readVolumesList(char *bdev_path, char **labels, size_t *nr_vols);
/* Close them all */
/* Close them all (in reverse order of opening) */
static int _closeVolumes(char **labels, size_t nr_vols);
@ -83,7 +83,7 @@ int sflc_cmd_closeVolumes(char *bdev_path)
goto out;
}
/* Close the volumes */
/* Close the volumes (in reverse order of opening) */
err = _closeVolumes(labels, nr_vols);
if (err) {
sflc_log_error("Could not close volumes; error %d", err);
@ -156,14 +156,14 @@ static int _readVolumesList(char *bdev_path, char **labels, size_t *nr_vols)
}
/* Close them all */
/* Close them all (in reverse order of opening) */
static int _closeVolumes(char **labels, size_t nr_vols)
{
int err;
/* Eazy peazy */
size_t i;
for (i = 0; i < nr_vols; i++) {
int i;
for (i = nr_vols-1; i >= 0; i--) {
err = sflc_ops_closeVolume(labels[i]);
if (err) {
sflc_log_error("Could not close volume %s; error %d", labels[i], err);

View file

@ -29,10 +29,10 @@
#include <stdint.h>
#include <stdlib.h>
#include "commands/commands.h"
#include "operations/device.h"
#include "operations/volume.h"
#include "commands.h"
#include "operations.h"
#include "utils/sflc.h"
#include "utils/disk.h"
#include "utils/crypto.h"
#include "utils/log.h"
@ -52,7 +52,7 @@
*****************************************************/
/* Fill the device with random data */
static int _fillWithRandom(char *bdev_path, uint64_t dev_size);
static int _fillDiskWithRandom(char *bdev_path, uint64_t dev_size);
/*****************************************************
@ -75,6 +75,7 @@ static int _fillWithRandom(char *bdev_path, uint64_t dev_size);
int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args)
{
sflc_Dmb dmb;
sflc_Vmb vmb;
int64_t dev_size;
size_t nr_slices;
int err;
@ -85,7 +86,7 @@ int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args)
return EINVAL;
}
/* Get device info */
/* Get device size */
dev_size = sflc_disk_getSize(args->bdev_path);
if (dev_size < 0) {
err = -dev_size;
@ -96,42 +97,47 @@ int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args)
nr_slices = sflc_disk_maxSlices(dev_size);
sflc_log_debug("Device %s has %ld blocks, corresponding to %lu logical slices", args->bdev_path, dev_size, nr_slices);
/* Fill with random, if needed */
/* Fill disk with random bytes, if requested */
if (!args->no_randfill) {
err = _fillWithRandom(args->bdev_path, (uint64_t) dev_size);
err = _fillDiskWithRandom(args->bdev_path, (uint64_t) dev_size);
if (err) {
sflc_log_error("Could not fill device %s with random bytes; error %d", args->bdev_path, err);
return err;
}
}
/* Create the DMB and write it to disk */
/* Fill the DMB */
dmb.nr_vols = args->nr_vols;
err = sflc_ops_createAndWriteDmb(args->bdev_path, args->pwds, args->pwd_lens, &dmb);
/* Sample the VMB keys */
size_t i;
for (i = 0; i < dmb.nr_vols; i++) {
err = sflc_rand_getStrongBytes(dmb.vmb_keys[i], SFLC_CRYPTO_KEYLEN);
if (err) {
sflc_log_error("Could not sample VMB key number %lu; error %d", i , err);
return err;
}
}
/* And write (encrypted) to disk */
err = sflc_ops_writeDmb(args->bdev_path, args->pwds, args->pwd_lens, &dmb);
if (err) {
sflc_log_error("Could not create DMB and write it to disk; error %d", err);
return err;
}
/* Common fields for all the volumes */
sflc_Volume vol;
vol.bdev_path = args->bdev_path;
vol.nr_slices = nr_slices;
/* Create each of the volumes */
size_t i;
/* Write the volume headers */
vmb.nr_slices = nr_slices;
for (i = 0; i < args->nr_vols; i++) {
/* This volume's vmb_key and prev_vmb_key */
memcpy(vol.vmb_key, dmb.vmb_keys[i], SFLC_CRYPTO_KEYLEN);
/* This volume's prev_vmb_key */
if (i > 0) {
memcpy(vol.prev_vmb_key, dmb.vmb_keys[i-1], SFLC_CRYPTO_KEYLEN);
memcpy(vmb.prev_vmb_key, dmb.vmb_keys[i-1], SFLC_CRYPTO_KEYLEN);
}
/* This volume's index */
vol.vol_idx = i;
/* Sample this volume's VEK */
sflc_rand_getStrongBytes(vmb.volume_key, SFLC_CRYPTO_KEYLEN);
/* Create volume */
err = sflc_ops_createVolume(&vol);
/* Write complete volume header (VMB + PM) */
err = sflc_ops_writeVolumeHeader(args->bdev_path, dmb.vmb_keys[i], &vmb, i);
if (err) {
sflc_log_error("Error creating volume %lu on device %s; error %d", i, args->bdev_path, err);
sflc_log_error("Error writing volume header %lu on device %s; error %d", i, args->bdev_path, err);
return err;
}
}
@ -146,7 +152,7 @@ int sflc_cmd_initVolumes(sflc_cmd_InitArgs *args)
*****************************************************/
/* Fill the device with random data */
static int _fillWithRandom(char *bdev_path, uint64_t dev_size)
static int _fillDiskWithRandom(char *bdev_path, uint64_t dev_size)
{
char *rand_chunk;
int err;

View file

@ -29,11 +29,11 @@
#include <stdlib.h>
#include <stdint.h>
#include "commands/commands.h"
#include "operations/volume.h"
#include "operations/device.h"
#include "commands.h"
#include "operations.h"
#include "utils/sflc.h"
#include "utils/crypto.h"
#include "utils/disk.h"
#include "utils/file.h"
#include "utils/log.h"
@ -42,12 +42,6 @@
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
/* Finds the volume opened by the given pwd */
static int _findVolumeByPwd(sflc_cmd_OpenArgs *args, size_t nr_slices, size_t *vol_idx, char *vmb_key);
/* Opens the indicated volume and the previous ones with the VMB keys */
static int _openVolumes(sflc_cmd_OpenArgs *args, size_t nr_slices, size_t vol_idx, char *vmb_key);
/* Read the next device ID in sysfs */
static int _getNextDevId(size_t *next_dev_id);
@ -57,13 +51,15 @@ static int _getNextDevId(size_t *next_dev_id);
*****************************************************/
/**
* Open M volumes, from the one whose pwd is provided back up to the first one.
* Scans the device to find the volume that can be opened with the provided
* pwd, opens it, then opens the previous ones with their VMB key.
* Open M volumes, from the first one down to the one whose pwd is provided.
* Scans the DMB cells to find which one is unlocked by the provided pwd; then,
* using the decrypted VMB key, unlocks the M-th VMB; then, iteratively using
* the prev_vmb_key field, unlocks all the previous VMBs; then, using the
* decrypted VMB keys, opens the volumes "in order" from 1 to M.
*
* @param args->bdev_path The underlying block device
* @param pwd The password
* @param pwd_len The password length
* @param args->pwd The password
* @param args->pwd_len The password length
*
* @return Error code (also if no volume could be opened), 0 on success
*/
@ -71,8 +67,9 @@ int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args)
{
int64_t dev_size;
size_t nr_slices;
size_t vol_idx;
char vmb_key[SFLC_CRYPTO_KEYLEN];
sflc_DmbCell dmb_cell;
sflc_Vmb vmbs[SFLC_DEV_MAX_VOLUMES];
size_t dev_id;
int err;
/* Get number of slices */
@ -85,21 +82,63 @@ int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args)
nr_slices = sflc_disk_maxSlices(dev_size);
/* Find volume opened by the pwd */
err = _findVolumeByPwd(args, nr_slices, &vol_idx, vmb_key);
err = sflc_ops_readDmb(args->bdev_path, args->pwd, args->pwd_len, &dmb_cell);
if (err) {
sflc_log_error("Could not find volume opened by given password; error %d", err);
sflc_log_error("Could not read DMB; error %d", err);
return err;
}
/* Was there one? */
if (vol_idx >= SFLC_DEV_MAX_VOLUMES) {
if (dmb_cell.vol_idx >= SFLC_DEV_MAX_VOLUMES) {
sflc_log_error("The provided password opens no volume on the device");
return EINVAL;
}
printf("Password is correct! Opening volumes...\n");
/* Open volumes */
return _openVolumes(args, nr_slices, vol_idx, vmb_key);
/* Unlock VMBs "backwards" */
int i; // Needs sign, because loop ends on i>=0
for (i = dmb_cell.vol_idx; i >= 0; i--) {
/* Which VMB key to use? */
char *vmb_key;
if (i == dmb_cell.vol_idx) {
// The one unlocked by pwd
vmb_key = dmb_cell.vmb_key;
} else {
// Or the prev_vmb_key from last iteration
vmb_key = vmbs[i+1].prev_vmb_key;
}
/* Read and unlock VMB */
err = sflc_ops_readVmb(args->bdev_path, vmb_key, nr_slices, (size_t) i, &vmbs[i]);
if (err) {
sflc_log_error("Could not read VMB %d on device %s; error %d",
i, args->bdev_path, err);
return err;
}
}
/* Get the ID that will be assigned to the block device */
err = _getNextDevId(&dev_id);
if (err) {
sflc_log_error("Could not get next device ID; error %d", err);
return err;
}
sflc_log_debug("Next device ID is %lu", dev_id);
/* Open volumes "in order" */
for (i = 0; i <= dmb_cell.vol_idx; i++) {
err = sflc_ops_openVolume(args->bdev_path, dev_id, (size_t) i, &vmbs[i]);
if (err) {
sflc_log_error("Could not open volume %d; error %d. "
"Previous volumes on the device might have already "
"been opened, it's recommended you close them",
i, err);
return err;
}
sflc_log_debug("Successfully opened volume %d with VMB key", i);
printf("Opened volume /dev/mapper/sflc_%lu_%d\n", dev_id, i);
}
return 0;
}
@ -107,85 +146,6 @@ int sflc_cmd_openVolumes(sflc_cmd_OpenArgs *args)
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
/* Finds the volume opened by the given pwd */
int _findVolumeByPwd(sflc_cmd_OpenArgs *args, size_t nr_slices, size_t *vol_idx, char *vmb_key)
{
sflc_DmbCell dmb;
int err;
/* Delegate entirely to the function reading the DMB */
err = sflc_ops_readDmb(args->bdev_path, args->pwd, args->pwd_len, &dmb);
if (err) {
sflc_log_error("Could not read DMB; error %d", err);
return err;
}
/* Check that a volume was found */
if (dmb.vol_idx >= SFLC_DEV_MAX_VOLUMES) {
sflc_log_error("Could not unlock any volumes: wrong password supplied");
return EINVAL;
}
/* Copy to output parameters */
*vol_idx = dmb.vol_idx;
memcpy(vmb_key, dmb.vmb_key, SFLC_CRYPTO_KEYLEN);
return 0;
}
/* Opens the indicated volume with the pwd and the previous ones with the VMB key */
int _openVolumes(sflc_cmd_OpenArgs *args, size_t nr_slices, size_t vol_idx, char *vmb_key)
{
sflc_Volume vol;
int err;
/* Input fields to open a volume */
vol.bdev_path = args->bdev_path;
vol.nr_slices = nr_slices;
/* Get the ID that will be assigned to the block device */
err = _getNextDevId(&vol.dev_id);
if (err) {
sflc_log_error("Could not get next device ID; error %d", err);
return err;
}
sflc_log_debug("Next device ID is %lu", vol.dev_id);
/* Open the last one with the provided vmb_key */
vol.vol_idx = vol_idx;
memcpy(vol.vmb_key, vmb_key, SFLC_CRYPTO_KEYLEN);
err = sflc_ops_openVolume(&vol);
if (err) {
sflc_log_error("Could not open volume %lu with pwd; error %d", vol_idx, err);
return err;
}
sflc_log_debug("Successfully opened most secret volume (%lu) with password", vol_idx);
printf("Opened volume /dev/mapper/sflc_%lu_%lu\n", vol.dev_id, vol_idx);
/* Loop backwards to open the previous ones */
int i;
for (i = vol_idx-1; i >= 0; i--) {
size_t idx = (size_t) i; // Looping directly with idx would overflow at the "last" iteration
/* This volume's VMB key was an output of the last openVolume() */
memcpy(vol.vmb_key, vol.prev_vmb_key, SFLC_CRYPTO_KEYLEN);
/* Open this volume with VMB key */
vol.vol_idx = idx;
err = sflc_ops_openVolume(&vol);
if (err) {
sflc_log_error("Could not open volume %lu with VMB key; error %d. "
"Some volumes on the device have already been opened, it's recommended you close them", idx, err);
return err;
}
sflc_log_debug("Successfully opened volume %lu with VMB key", idx);
printf("Opened volume /dev/mapper/sflc_%lu_%lu\n", vol.dev_id, idx);
}
return 0;
}
/* Read the next device ID in sysfs */
static int _getNextDevId(size_t *next_dev_id)
{

View file

@ -29,9 +29,8 @@
#include <stdlib.h>
#include <stdint.h>
#include "commands/commands.h"
#include "operations/volume.h"
#include "operations/device.h"
#include "commands.h"
#include "operations.h"
#include "utils/sflc.h"
#include "utils/crypto.h"
#include "utils/file.h"

View file

@ -29,7 +29,7 @@
#include <errno.h>
#include <string.h>
#include "header/device_master_block.h"
#include "header.h"
#include "utils/crypto.h"
#include "utils/log.h"
@ -195,7 +195,7 @@ int sflc_dmb_setCell(char *disk_block, sflc_DmbCell *dmb_cell, char *pwd, size_t
sflc_log_error("Could not re-encrypt VMB key number %lu; error %d", dmb_cell->vol_idx, err);
return err;
}
sflc_log_debug("Successfully re-encrypted VMB key number %lu", vol_idx);
sflc_log_debug("Successfully re-encrypted VMB key number %lu", dmb_cell->vol_idx);
return 0;
}

View file

@ -29,7 +29,7 @@
#include <stdlib.h>
#include <string.h>
#include "header/position_map.h"
#include "header.h"
#include "utils/sflc.h"
#include "utils/crypto.h"
#include "utils/math.h"

View file

@ -30,7 +30,7 @@
#include <string.h>
#include <arpa/inet.h> // Network byte order
#include "header/volume_master_block.h"
#include "header.h"
#include "utils/crypto.h"
#include "utils/string.h"
#include "utils/log.h"
@ -41,10 +41,10 @@
*****************************************************/
/* Serialise the VMB before encrypting it */
static void _serialiseVmb(sflc_VolumeMasterBlock *vmb, char *clear_vmb);
static void _serialiseVmb(sflc_Vmb *vmb, char *clear_vmb);
/* Deserialise the VMB after decrypting it */
static int _deserialiseVmb(char *clear_vmb, sflc_VolumeMasterBlock *vmb);
static int _deserialiseVmb(char *clear_vmb, sflc_Vmb *vmb);
/*****************************************************
@ -61,7 +61,7 @@ static int _deserialiseVmb(char *clear_vmb, sflc_VolumeMasterBlock *vmb);
*
* @return The error code, 0 on success
*/
int sflc_vmb_seal(sflc_VolumeMasterBlock *vmb, char *vmb_key, char *disk_block)
int sflc_vmb_seal(sflc_Vmb *vmb, char *vmb_key, char *disk_block)
{
// Pointers inside the block
char *iv = disk_block;
@ -123,7 +123,7 @@ bad_clear_alloc:
*
* @return An error code, 0 on success
*/
int sflc_vmb_unseal(char *disk_block, char *vmb_key, sflc_VolumeMasterBlock *vmb)
int sflc_vmb_unseal(char *disk_block, char *vmb_key, sflc_Vmb *vmb)
{
// Pointers inside the block
char *iv = disk_block;
@ -177,7 +177,7 @@ bad_clear_alloc:
*****************************************************/
/* Serialise the payload before encrypting it */
static void _serialiseVmb(sflc_VolumeMasterBlock *vmb, char *clear_vmb)
static void _serialiseVmb(sflc_Vmb *vmb, char *clear_vmb)
{
// Pointers inside the VMB
char *p_vol_key = clear_vmb;
@ -200,7 +200,7 @@ static void _serialiseVmb(sflc_VolumeMasterBlock *vmb, char *clear_vmb)
/* Deserialise the VMB after decrypting it */
static int _deserialiseVmb(char *clear_vmb, sflc_VolumeMasterBlock *vmb)
static int _deserialiseVmb(char *clear_vmb, sflc_Vmb *vmb)
{
// Pointers inside the VMB
char *p_vol_key = clear_vmb;

View file

@ -30,7 +30,7 @@
* INCLUDE SECTION *
*****************************************************/
#include "cli/cli.h"
#include "cli.h"
/*****************************************************

View file

@ -31,8 +31,8 @@
#include <stdlib.h>
#include <string.h>
#include "header/volume_master_block.h"
#include "operations/volume.h"
#include "header.h"
#include "operations.h"
#include "utils/sflc.h"
#include "utils/crypto.h"
#include "utils/file.h"
@ -45,6 +45,58 @@
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/**
* Build parameter list for ctor in dm_sflc, and send DM ioctl to create
* virtual block device.
*
* @param bdev_path The path to the underlying device
* @param dev_id The ID of the underlying block device
* @param vol_idx The index of the volume within the device
* @param vmb Volume metadata
*
* @return Error code, 0 on success
*/
int sflc_ops_openVolume(char *bdev_path, size_t dev_id, size_t vol_idx, sflc_Vmb *vmb)
{
char label[SFLC_BIGBUFSIZE];
char *hex_key;
char params[SFLC_BIGBUFSIZE];
uint64_t num_sectors;
int err;
/* Build volume label */
sprintf(label, "sflc_%lu_%lu", dev_id, vol_idx);
/* Get the hex version of the volume's data section key */
hex_key = sflc_toHex(vmb->volume_key, SFLC_CRYPTO_KEYLEN);
if (!hex_key) {
sflc_log_error("Could not encode volume key to hexadecimal");
err = ENOMEM;
goto err_hexkey;
}
/* Get the number of logical 512-byte sectors composing the volume */
num_sectors = ((uint64_t) vmb->nr_slices) * SFLC_BLOCKS_PER_LOG_SLICE * SFLC_SECTOR_SCALE;
/* Build param list */
sprintf(params, "%s %lu %lu %s", bdev_path, vol_idx, vmb->nr_slices, hex_key);
/* Issue ioctl */
err = sflc_dm_create(label, num_sectors, params);
if (err) {
sflc_log_error("Could not issue ioctl CREATE command to device mapper; error %d", err);
goto err_dmcreate;
}
err = 0;
err_dmcreate:
free(hex_key);
err_hexkey:
return err;
}
/**
* Close the volume by issuing the appropriate ioctl to the DM.
*

View file

@ -31,9 +31,10 @@
#include <stdlib.h>
#include <string.h>
#include "header/device_master_block.h"
#include "operations/device.h"
#include "header.h"
#include "operations.h"
#include "utils/sflc.h"
#include "utils/disk.h"
#include "utils/crypto.h"
#include "utils/log.h"
@ -43,18 +44,17 @@
*****************************************************/
/**
* Samples VMB keys and writes the corresponding DMB to disk.
* Encrypts and writes the DMB to disk.
*
* @param bdev_path The path to the underlying block device
* @param pwds The array of passwords
* @param pwd_lens Their lengths
* @param dmb->nr_vols
*
* @output dmb->vmb_keys
*
* @return Error code, 0 on success
*/
int sflc_ops_createAndWriteDmb(char *bdev_path, char **pwds, size_t *pwd_lens, sflc_Dmb *dmb)
int sflc_ops_writeDmb(char *bdev_path, char **pwds, size_t *pwd_lens, sflc_Dmb *dmb)
{
/* On-disk DMB */
char enc_dmb[SFLC_SECTOR_SIZE];
@ -67,17 +67,7 @@ int sflc_ops_createAndWriteDmb(char *bdev_path, char **pwds, size_t *pwd_lens, s
return EINVAL;
}
/* Sample the VMB keys */
size_t i;
for (i = 0; i < dmb->nr_vols; i++) {
err = sflc_rand_getStrongBytes(dmb->vmb_keys[i], SFLC_CRYPTO_KEYLEN);
if (err) {
sflc_log_error("Could not sample VMB key number %lu; error %d", i , err);
return err;
}
}
/* Seal it */
/* Seal DMB */
err = sflc_dmb_seal(dmb, pwds, pwd_lens, enc_dmb);
if (err) {
sflc_log_error("Coul dnot seal DMB; error %d", err);
@ -109,9 +99,7 @@ int sflc_ops_createAndWriteDmb(char *bdev_path, char **pwds, size_t *pwd_lens, s
*/
int sflc_ops_readDmb(char *bdev_path, char *pwd, size_t pwd_len, sflc_DmbCell *dmb)
{
/* On-disk DMB */
char enc_dmb[SFLC_SECTOR_SIZE];
/* Error code */
int err;
/* Read DMB from disk (at sector 0) */
@ -141,11 +129,9 @@ int sflc_ops_readDmb(char *bdev_path, char *pwd, size_t pwd_len, sflc_DmbCell *d
*
* @return Error code, 0 on success
*/
int sflc_ops_reencryptDmbCellAndWrite(char *bdev_path, sflc_DmbCell *dmb_cell, char *new_pwd, size_t new_pwd_len)
int sflc_ops_rewriteDmbCell(char *bdev_path, sflc_DmbCell *dmb_cell, char *new_pwd, size_t new_pwd_len)
{
/* On-disk DMB */
char enc_dmb[SFLC_SECTOR_SIZE];
/* Error code */
int err;
/* Sanity check */

View file

@ -1,155 +0,0 @@
/*
* 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/>.
*/
/*****************************************************
* INCLUDE SECTION *
*****************************************************/
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header/volume_master_block.h"
#include "operations/volume.h"
#include "utils/sflc.h"
#include "utils/crypto.h"
#include "utils/file.h"
#include "utils/string.h"
#include "utils/dm.h"
#include "utils/log.h"
/*****************************************************
* PRIVATE FUNCTIONS PROTOTYPES *
*****************************************************/
/* Open the volume through the appropriate ioctl */
static int _openVolume(sflc_Volume *vol);
/*****************************************************
* PUBLIC FUNCTIONS DEFINITIONS *
*****************************************************/
/**
* Read a VMB from disk and issue a DM ioctl to create the appropriate virtual device
*
* @param vol->vmb_key The key encrypting this volume's VMB
* @param vol->dev_id The ID of the underlying block device
* @param vol->vol_idx The index of the volume within the device
* @param vol->bdev_path The path to the underlying device
* @param vol->nr_slices The number of logical slices for this device / volumes
*
* @output vol->volume_key This volume's data section key
* @output vol->prev_vmb_key The previous volume's VMB key
* @output vol->label The volume's name under /dev/mapper/
*
* @return Error code, 0 on success
*/
int sflc_ops_openVolume(sflc_Volume *vol)
{
sflc_VolumeMasterBlock vmb;
char enc_vmb[SFLC_SECTOR_SIZE];
uint64_t sector;
int err;
/* Read encrypted VMB from disk */
sector = sflc_vmbPosition(vol);
err = sflc_disk_readSector(vol->bdev_path, sector, enc_vmb);
if (err) {
sflc_log_error("Could not read VMB from disk; error %d", err);
return err;
}
/* Unseal it */
err = sflc_vmb_unseal(enc_vmb, vol->vmb_key, &vmb);
if (err) {
sflc_log_error("Could not unseal VMB; error %d", err);
return err;
}
/* Compare the number of slices */
if (vol->nr_slices != vmb.nr_slices) {
sflc_log_error("Incompatible header size: the device size was different when the volumes"
"were created. Did you resize the device %s since last time?", vol->bdev_path);
return EINVAL;
}
/* Copy the keys over to the Volume struct */
memcpy(vol->volume_key, vmb.volume_key, SFLC_CRYPTO_KEYLEN);
memcpy(vol->prev_vmb_key, vmb.prev_vmb_key, SFLC_CRYPTO_KEYLEN);
/* Build volume label */
sprintf(vol->label, "sflc_%lu_%lu", vol->dev_id, vol->vol_idx);
/* Actually open the volume */
err = _openVolume(vol);
if (err) {
sflc_log_error("Could not open volume; error %d", err);
return err;
}
return 0;
}
/*****************************************************
* PRIVATE FUNCTIONS DEFINITIONS *
*****************************************************/
/* Open the volume through the appropriate ioctl */
static int _openVolume(sflc_Volume *vol)
{
char *hex_key;
char params[SFLC_BIGBUFSIZE];
uint64_t num_sectors;
int err;
/* Get the hex version of the volume's data section key */
hex_key = sflc_toHex(vol->volume_key, SFLC_CRYPTO_KEYLEN);
if (!hex_key) {
sflc_log_error("Could not encode volume key to hexadecimal");
err = ENOMEM;
goto err_hexkey;
}
/* Get the number of logical 512-byte sectors composing the volume */
num_sectors = ((uint64_t) vol->nr_slices) * SFLC_BLOCKS_PER_LOG_SLICE * SFLC_SECTOR_SCALE;
/* Build param list */
sprintf(params, "%s %lu %lu %s", vol->bdev_path, vol->vol_idx, vol->nr_slices, hex_key);
/* Issue ioctl */
err = sflc_dm_create(vol->label, num_sectors, params);
if (err) {
sflc_log_error("Could not issue ioctl CREATE command to device mapper; error %d", err);
goto err_dmcreate;
}
err = 0;
err_dmcreate:
free(hex_key);
err_hexkey:
return err;
}

View file

@ -30,10 +30,11 @@
#include <stdlib.h>
#include <string.h>
#include "header/position_map.h"
#include "header/volume_master_block.h"
#include "operations/volume.h"
#include "header.h"
#include "header.h"
#include "operations.h"
#include "utils/sflc.h"
#include "utils/disk.h"
#include "utils/crypto.h"
#include "utils/log.h"
@ -43,48 +44,32 @@
*****************************************************/
/**
* Writes a volume header (VMB+PM) on-disk. Also fills the struct's volume_key field.
* Some of the fields in the struct are input, some are output.
* Writes a volume header (VMB+PM) on-disk.
*
* @param vol->vmb_key The key to decrypt the VMB
* @param vol->prev_vmb_key The previous volume's VMB key
* @param vol->nr_slices The number of logical slices of the volume(s)
* @param vol->vol_idx The index of the volume within the device
* @param vol->bdev_path The underlying block device to write the volume header
*
* @output vol->volume_key This volume's data section key
*
* @unused vol->label
* @unused vol->dev_id
* @param bdev_path The underlying block device to write the volume header
* @param vmb_key The key to encrypt the VMB
* @param vmb The VMB to encrypt
* @param vol_idx The index of the volume within the device
*
* @return Error code, 0 on success
*/
int sflc_ops_createVolume(sflc_Volume *vol)
int sflc_ops_writeVolumeHeader(char *bdev_path, char *vmb_key, sflc_Vmb *vmb, size_t vol_idx)
{
sflc_VolumeMasterBlock vmb;
char enc_vmb[SFLC_SECTOR_SIZE];
sflc_EncPosMap epm;
uint64_t sector;
int err;
// Sample keys
sflc_rand_getWeakBytes(vol->volume_key, SFLC_CRYPTO_KEYLEN);
// Fill VMB
memcpy(vmb.volume_key, vol->volume_key, SFLC_CRYPTO_KEYLEN);
memcpy(vmb.prev_vmb_key, vol->prev_vmb_key, SFLC_CRYPTO_KEYLEN);
vmb.nr_slices = vol->nr_slices;
// Encrypt it
err = sflc_vmb_seal(&vmb, vol->vmb_key, enc_vmb);
// Encrypt VMB
err = sflc_vmb_seal(vmb, vmb_key, enc_vmb);
if (err) {
sflc_log_error("Could not seal VMB; error %d", err);
goto out;
}
// Write it to disk
sector = sflc_vmbPosition(vol);
err = sflc_disk_writeSector(vol->bdev_path, sector, enc_vmb);
sector = sflc_vmbPosition(vol_idx, vmb->nr_slices);
err = sflc_disk_writeSector(bdev_path, sector, enc_vmb);
if (err) {
sflc_log_error("Could not write VMB to disk; error %d", err);
goto out;
@ -92,13 +77,13 @@ int sflc_ops_createVolume(sflc_Volume *vol)
sector += 1;
// Create encrypted empty position map
err = sflc_epm_create(vol->nr_slices, vol->volume_key, &epm);
err = sflc_epm_create(vmb->nr_slices, vmb->volume_key, &epm);
if (err) {
sflc_log_error("Could not create encrypted empty position map; error %d", err);
goto out;
}
// Loop over PMB arrays to write it to disk
// Loop over PMB arrays to write them to disk
int i;
for (i = 0; i < epm.nr_arrays; i++) {
char *iv_block = epm.iv_blocks[i];
@ -106,7 +91,7 @@ int sflc_ops_createVolume(sflc_Volume *vol)
size_t nr_pmbs = ((i == epm.nr_arrays-1) ? epm.nr_last_pmbs : SFLC_BLOCKS_PER_LOG_SLICE);
// First write the IV block
err = sflc_disk_writeSector(vol->bdev_path, sector, iv_block);
err = sflc_disk_writeSector(bdev_path, sector, iv_block);
if (err) {
sflc_log_error("Could not write IV block to disk; error %d", err);
goto out;
@ -114,7 +99,7 @@ int sflc_ops_createVolume(sflc_Volume *vol)
sector += 1;
// Then the whole PMB array
err = sflc_disk_writeManySectors(vol->bdev_path, sector, pmb_array, nr_pmbs);
err = sflc_disk_writeManySectors(bdev_path, sector, pmb_array, nr_pmbs);
if (err) {
sflc_log_error("Could not write PMB array to disk; error %d", err);
goto out;
@ -134,3 +119,47 @@ int sflc_ops_createVolume(sflc_Volume *vol)
out:
return err;
}
/**
* Reads a VMB from disk and unlocks it
*
* @param bdev_path The underlying block device
* @param vmb_key The key to decrypt the VMB
* @param nr_slices The number of slices in the device
* @param vol_idx The index of the volume within the device
*
* @output vmb The decrypted VMB
*
* @return Error code, 0 on success
*/
int sflc_ops_readVmb(char *bdev_path, char *vmb_key, size_t nr_slices, size_t vol_idx, sflc_Vmb *vmb)
{
char enc_vmb[SFLC_SECTOR_SIZE];
uint64_t sector;
int err;
/* Read encrypted VMB from disk */
sector = sflc_vmbPosition(vol_idx, nr_slices);
err = sflc_disk_readSector(bdev_path, sector, enc_vmb);
if (err) {
sflc_log_error("Could not read VMB from disk; error %d", err);
return err;
}
/* Unseal it */
err = sflc_vmb_unseal(enc_vmb, vmb_key, vmb);
if (err) {
sflc_log_error("Could not unseal VMB; error %d", err);
return err;
}
/* Compare the number of slices */
if (nr_slices != vmb->nr_slices) {
sflc_log_error("Incompatible header size: the device size was different when the volumes"
"were created. Did you resize the device %s since last time?", bdev_path);
return EINVAL;
}
return 0;
}