|
Packit |
da863b |
/* vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: */
|
|
Packit |
da863b |
/*
|
|
Packit |
da863b |
* Copyright (c) 2016 Red Hat, Inc.
|
|
Packit |
da863b |
* Author: Nathaniel McCallum <npmccallum@redhat.com>
|
|
Packit |
da863b |
*
|
|
Packit |
da863b |
* This program is free software: you can redistribute it and/or modify it
|
|
Packit |
da863b |
* under the terms of the GNU Lesser General Public License as published by
|
|
Packit |
da863b |
* the Free Software Foundation, either version 2.1 of the License, or
|
|
Packit |
da863b |
* (at your option) any later version.
|
|
Packit |
da863b |
*
|
|
Packit |
da863b |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
da863b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
da863b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
da863b |
* GNU Lesser General Public License for more details.
|
|
Packit |
da863b |
*
|
|
Packit |
da863b |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
da863b |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
da863b |
*/
|
|
Packit |
da863b |
|
|
Packit |
da863b |
#include "crc32c.h"
|
|
Packit |
da863b |
#include "luksmeta.h"
|
|
Packit |
da863b |
|
|
Packit |
da863b |
#include <sys/types.h>
|
|
Packit |
da863b |
#include <sys/stat.h>
|
|
Packit |
da863b |
#include <errno.h>
|
|
Packit |
da863b |
#include <fcntl.h>
|
|
Packit |
da863b |
#include <stdbool.h>
|
|
Packit |
da863b |
#include <stdlib.h>
|
|
Packit |
da863b |
#include <string.h>
|
|
Packit |
da863b |
#include <unistd.h>
|
|
Packit |
da863b |
|
|
Packit |
da863b |
#define ALIGN(s, up) (((s) + (up ? 4095 : 0)) & ~4095ULL)
|
|
Packit |
da863b |
#define LUKS_NSLOTS 8
|
|
Packit |
da863b |
#define LM_VERSION 1
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static const uint8_t LM_MAGIC[] = { 'L', 'U', 'K', 'S', 'M', 'E', 'T', 'A' };
|
|
Packit |
da863b |
|
|
Packit |
da863b |
typedef struct __attribute__((packed)) {
|
|
Packit |
da863b |
luksmeta_uuid_t uuid;
|
|
Packit |
da863b |
uint32_t offset; /* Bytes from the start of the hole */
|
|
Packit |
da863b |
uint32_t length; /* Bytes */
|
|
Packit |
da863b |
uint32_t crc32c;
|
|
Packit |
da863b |
uint32_t _reserved; /* Reserved */
|
|
Packit |
da863b |
} lm_slot_t;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
typedef struct __attribute__((packed)) {
|
|
Packit |
da863b |
uint8_t magic[sizeof(LM_MAGIC)];
|
|
Packit |
da863b |
uint32_t version;
|
|
Packit |
da863b |
uint32_t crc32c;
|
|
Packit |
da863b |
lm_slot_t slots[LUKS_NSLOTS];
|
|
Packit |
da863b |
} lm_t;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static bool
|
|
Packit |
da863b |
uuid_is_zero(const luksmeta_uuid_t uuid)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
for (size_t i = 0; i < sizeof(luksmeta_uuid_t); i++) {
|
|
Packit |
da863b |
if (uuid[i] != 0)
|
|
Packit |
da863b |
return false;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
return true;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static inline uint32_t
|
|
Packit |
da863b |
checksum(lm_t lm)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
lm.crc32c = 0;
|
|
Packit |
da863b |
return crc32c(0, &lm, sizeof(lm_t));
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static inline bool
|
|
Packit |
da863b |
overlap(const lm_t *lm, uint32_t start, size_t end)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
for (int i = 0; i < LUKS_NSLOTS; i++) {
|
|
Packit |
da863b |
const lm_slot_t *s = &lm->slots[i];
|
|
Packit |
da863b |
uint32_t e = s->offset + s->length;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (start <= s->offset && s->offset < end)
|
|
Packit |
da863b |
return true;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (start < e && e <= end)
|
|
Packit |
da863b |
return true;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
return false;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static inline uint32_t
|
|
Packit |
da863b |
find_gap(const lm_t *lm, uint32_t length, size_t size)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
size = ALIGN(size, true);
|
|
Packit |
da863b |
|
|
Packit |
da863b |
for (uint32_t off = ALIGN(1, true); off < length; off += ALIGN(1, true)) {
|
|
Packit |
da863b |
if (!overlap(lm, off, off + size))
|
|
Packit |
da863b |
return off;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
return 0;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static int
|
|
Packit |
da863b |
find_unused_slot(struct crypt_device *cd, const lm_t *lm)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
|
|
Packit |
da863b |
if (crypt_keyslot_status(cd, slot) == CRYPT_SLOT_INACTIVE &&
|
|
Packit |
da863b |
uuid_is_zero(lm->slots[slot].uuid))
|
|
Packit |
da863b |
return slot;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
return -1;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static inline ssize_t
|
|
Packit |
da863b |
readall(int fd, void *data, size_t size)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
uint8_t *tmp = data;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
for (ssize_t r, t = 0; t < (ssize_t) size; t += r) {
|
|
Packit |
da863b |
r = read(fd, &tmp[t], size - t);
|
|
Packit |
da863b |
if (r < 0 && errno != EAGAIN)
|
|
Packit |
da863b |
return -errno;
|
|
Packit |
da863b |
if (r == 0)
|
|
Packit |
da863b |
return -ENOENT;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
return size;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static inline ssize_t
|
|
Packit |
da863b |
writeall(int fd, const void *buf, size_t size)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
const uint8_t *tmp = buf;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
for (ssize_t r, t = 0; t < (ssize_t) size; t += r) {
|
|
Packit |
da863b |
r = write(fd, &tmp[t], size - t);
|
|
Packit |
da863b |
if (r < 0) {
|
|
Packit |
da863b |
if (errno != EAGAIN)
|
|
Packit |
da863b |
return -errno;
|
|
Packit |
da863b |
r = 0;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
return size;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
/**
|
|
Packit |
da863b |
* Opens the device with the specified flags.
|
|
Packit |
da863b |
*
|
|
Packit |
da863b |
* The length parameter is set to the amount of space in the gap between the
|
|
Packit |
da863b |
* end of the last slot and the start of the encrypted data.
|
|
Packit |
da863b |
*
|
|
Packit |
da863b |
* The function returns either the file descriptor positioned to the start of
|
|
Packit |
da863b |
* the hole or a negative errno.
|
|
Packit |
da863b |
*/
|
|
Packit |
da863b |
static int
|
|
Packit |
da863b |
open_hole(struct crypt_device *cd, int flags, uint32_t *length)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
const char *name = NULL;
|
|
Packit |
da863b |
const char *type = NULL;
|
|
Packit |
da863b |
uint64_t hole = 0;
|
|
Packit |
da863b |
uint64_t data = 0;
|
|
Packit |
da863b |
int fd = 0;
|
|
Packit |
da863b |
int r = 0;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
type = crypt_get_type(cd);
|
|
Packit |
da863b |
if (!type || strcmp(CRYPT_LUKS1, type) != 0)
|
|
Packit |
da863b |
return -ENOTSUP;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
data = crypt_get_data_offset(cd) * 512;
|
|
Packit |
da863b |
if (data < 4096)
|
|
Packit |
da863b |
return -ENOSPC;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
|
|
Packit |
da863b |
uint64_t off = 0;
|
|
Packit |
da863b |
uint64_t len = 0;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = crypt_keyslot_area(cd, slot, &off, &len;;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
return r;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (hole < off + len)
|
|
Packit |
da863b |
hole = ALIGN(off + len, true);
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (hole == 0)
|
|
Packit |
da863b |
return -ENOTSUP;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (hole >= data)
|
|
Packit |
da863b |
return -ENOSPC;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
name = crypt_get_device_name(cd);
|
|
Packit |
da863b |
if (!name)
|
|
Packit |
da863b |
return -ENOTSUP;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
fd = open(name, flags);
|
|
Packit |
da863b |
if (fd < 0)
|
|
Packit |
da863b |
return -errno;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (lseek(fd, hole, SEEK_SET) == -1) {
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return -errno;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
*length = ALIGN(data - hole, false);
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static int
|
|
Packit |
da863b |
read_header(struct crypt_device *cd, int flags, uint32_t *length, lm_t *lm)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
uint32_t maxlen;
|
|
Packit |
da863b |
int fd = -1;
|
|
Packit |
da863b |
int r = 0;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
fd = open_hole(cd, flags, length);
|
|
Packit |
da863b |
if (fd < 0)
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = *length >= sizeof(lm_t) ? 0 : -ENOENT;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = readall(fd, lm, sizeof(lm_t));
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = memcmp(LM_MAGIC, lm->magic, sizeof(LM_MAGIC)) == 0 ? 0 : -ENOENT;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = lm->version == htobe32(LM_VERSION) ? 0 : -ENOTSUP;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
lm->crc32c = be32toh(lm->crc32c);
|
|
Packit |
da863b |
r = checksum(*lm) == lm->crc32c ? 0 : -EINVAL;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
lm->version = be32toh(lm->version);
|
|
Packit |
da863b |
|
|
Packit |
da863b |
maxlen = *length - ALIGN(sizeof(lm_t), true);
|
|
Packit |
da863b |
for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
|
|
Packit |
da863b |
lm_slot_t *s = &lm->slots[slot];
|
|
Packit |
da863b |
|
|
Packit |
da863b |
s->offset = be32toh(s->offset);
|
|
Packit |
da863b |
s->length = be32toh(s->length);
|
|
Packit |
da863b |
s->crc32c = be32toh(s->crc32c);
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (!uuid_is_zero(s->uuid)) {
|
|
Packit |
da863b |
r = s->offset > sizeof(lm_t) ? 0 : -EINVAL;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = s->length <= maxlen ? 0 : -EINVAL;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
error:
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return r;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
static int
|
|
Packit |
da863b |
write_header(int fd, lm_t lm)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
|
|
Packit |
da863b |
lm.slots[slot].offset = htobe32(lm.slots[slot].offset);
|
|
Packit |
da863b |
lm.slots[slot].length = htobe32(lm.slots[slot].length);
|
|
Packit |
da863b |
lm.slots[slot].crc32c = htobe32(lm.slots[slot].crc32c);
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
memcpy(lm.magic, LM_MAGIC, sizeof(LM_MAGIC));
|
|
Packit |
da863b |
lm.version = htobe32(LM_VERSION);
|
|
Packit |
da863b |
lm.crc32c = htobe32(checksum(lm));
|
|
Packit |
da863b |
return writeall(fd, &lm, sizeof(lm));
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
int
|
|
Packit |
da863b |
luksmeta_test(struct crypt_device *cd)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
int fd = -1;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
fd = read_header(cd, O_RDONLY, &(uint32_t) {0}, &(lm_t) {});
|
|
Packit |
da863b |
if (fd >= 0) {
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return 0;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
int
|
|
Packit |
da863b |
luksmeta_nuke(struct crypt_device *cd)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
uint8_t zero[ALIGN(1, true)] = {};
|
|
Packit |
da863b |
uint32_t length = 0;
|
|
Packit |
da863b |
int fd = -1;
|
|
Packit |
da863b |
int r = 0;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
fd = open_hole(cd, O_RDWR | O_SYNC, &length);
|
|
Packit |
da863b |
if (fd < 0)
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
for (size_t i = 0; r >= 0 && i < length; i += sizeof(zero))
|
|
Packit |
da863b |
r = writeall(fd, zero, sizeof(zero));
|
|
Packit |
da863b |
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return r < 0 ? r : 0;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
int
|
|
Packit |
da863b |
luksmeta_init(struct crypt_device *cd)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
uint32_t length = 0;
|
|
Packit |
da863b |
int fd = -1;
|
|
Packit |
da863b |
int r = 0;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = luksmeta_test(cd);
|
|
Packit |
da863b |
if (r == 0)
|
|
Packit |
da863b |
return -EALREADY;
|
|
Packit |
da863b |
else if (r != -ENOENT && r != -EINVAL)
|
|
Packit |
da863b |
return r;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
fd = open_hole(cd, O_RDWR | O_SYNC, &length);
|
|
Packit |
da863b |
if (fd < 0)
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (length < ALIGN(sizeof(lm_t), true)) {
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return -ENOSPC;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = write_header(fd, (lm_t) {});
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return r > 0 ? 0 : r;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
int
|
|
Packit |
da863b |
luksmeta_load(struct crypt_device *cd, int slot,
|
|
Packit |
da863b |
luksmeta_uuid_t uuid, void *buf, size_t size)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
uint32_t length = 0;
|
|
Packit |
da863b |
lm_slot_t *s = NULL;
|
|
Packit |
da863b |
lm_t lm = {};
|
|
Packit |
da863b |
int fd = -1;
|
|
Packit |
da863b |
int r = 0;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (slot < 0 || slot >= LUKS_NSLOTS)
|
|
Packit |
da863b |
return -EBADSLT;
|
|
Packit |
da863b |
s = &lm.slots[slot];
|
|
Packit |
da863b |
|
|
Packit |
da863b |
fd = read_header(cd, O_RDONLY, &length, &lm);
|
|
Packit |
da863b |
if (fd < 0)
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = uuid_is_zero(s->uuid) ? -ENODATA : 0;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (buf) {
|
|
Packit |
da863b |
r = size >= s->length ? 0 : -E2BIG;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = lseek(fd, s->offset - sizeof(lm), SEEK_CUR) == -1 ? -errno : 0;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = readall(fd, buf, s->length);
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = crc32c(0, buf, s->length) == s->crc32c ? 0 : -EINVAL;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
memcpy(uuid, s->uuid, sizeof(luksmeta_uuid_t));
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return s->length;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
error:
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return r;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
int
|
|
Packit |
da863b |
luksmeta_save(struct crypt_device *cd, int slot,
|
|
Packit |
da863b |
const luksmeta_uuid_t uuid, const void *buf, size_t size)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
uint32_t length = 0;
|
|
Packit |
da863b |
lm_slot_t *s = NULL;
|
|
Packit |
da863b |
lm_t lm = {};
|
|
Packit |
da863b |
int fd = -1;
|
|
Packit |
da863b |
int r = 0;
|
|
Packit |
da863b |
off_t off;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (uuid_is_zero(uuid))
|
|
Packit |
da863b |
return -EKEYREJECTED;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
fd = read_header(cd, O_RDWR | O_SYNC, &length, &lm);
|
|
Packit |
da863b |
if (fd < 0)
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (slot == CRYPT_ANY_SLOT)
|
|
Packit |
da863b |
slot = find_unused_slot(cd, &lm);
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = slot >= 0 && slot < LUKS_NSLOTS ? 0 : -EBADSLT;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
s = &lm.slots[slot];
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = uuid_is_zero(s->uuid) ? 0 : -EALREADY;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
s->offset = find_gap(&lm, length, size);
|
|
Packit |
da863b |
r = s->offset >= ALIGN(sizeof(lm), true) ? 0 : -ENOSPC;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
memcpy(s->uuid, uuid, sizeof(luksmeta_uuid_t));
|
|
Packit |
da863b |
s->length = size;
|
|
Packit |
da863b |
s->crc32c = crc32c(0, buf, size);
|
|
Packit |
da863b |
|
|
Packit |
da863b |
off = s->offset - sizeof(lm);
|
|
Packit |
da863b |
r = lseek(fd, off, SEEK_CUR) == -1 ? -errno : 0;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = writeall(fd, buf, size);
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
off = s->offset + s->length;
|
|
Packit |
da863b |
r = lseek(fd, -off, SEEK_CUR) == -1 ? -errno : 0;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = write_header(fd, lm);
|
|
Packit |
da863b |
|
|
Packit |
da863b |
error:
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return r < 0 ? r : slot;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
int
|
|
Packit |
da863b |
luksmeta_wipe(struct crypt_device *cd, int slot, const luksmeta_uuid_t uuid)
|
|
Packit |
da863b |
{
|
|
Packit |
da863b |
uint8_t *zero = NULL;
|
|
Packit |
da863b |
uint32_t length = 0;
|
|
Packit |
da863b |
lm_slot_t *s = NULL;
|
|
Packit |
da863b |
lm_t lm = {};
|
|
Packit |
da863b |
int fd = -1;
|
|
Packit |
da863b |
int r = 0;
|
|
Packit |
da863b |
off_t off;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (slot < 0 || slot >= LUKS_NSLOTS)
|
|
Packit |
da863b |
return -EBADSLT;
|
|
Packit |
da863b |
s = &lm.slots[slot];
|
|
Packit |
da863b |
|
|
Packit |
da863b |
fd = read_header(cd, O_RDWR | O_SYNC, &length, &lm);
|
|
Packit |
da863b |
if (fd < 0)
|
|
Packit |
da863b |
return fd;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = uuid_is_zero(s->uuid) ? -EALREADY : 0;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
if (uuid && memcmp(uuid, s->uuid, sizeof(luksmeta_uuid_t)) != 0) {
|
|
Packit |
da863b |
r = -EKEYREJECTED;
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
}
|
|
Packit |
da863b |
|
|
Packit |
da863b |
off = s->offset - sizeof(lm_t);
|
|
Packit |
da863b |
r = lseek(fd, off, SEEK_CUR) == -1 ? -errno : 0;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = (zero = calloc(1, s->length)) ? 0 : -errno;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
r = writeall(fd, zero, s->length);
|
|
Packit |
da863b |
free(zero);
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
off = s->offset + s->length;
|
|
Packit |
da863b |
r = lseek(fd, -off, SEEK_CUR) == -1 ? -errno : 0;
|
|
Packit |
da863b |
if (r < 0)
|
|
Packit |
da863b |
goto error;
|
|
Packit |
da863b |
|
|
Packit |
da863b |
memset(s, 0, sizeof(lm_slot_t));
|
|
Packit |
da863b |
r = write_header(fd, lm);
|
|
Packit |
da863b |
|
|
Packit |
da863b |
error:
|
|
Packit |
da863b |
close(fd);
|
|
Packit |
da863b |
return r < 0 ? r : 0;
|
|
Packit |
da863b |
}
|