|
Packit Service |
a9384c |
/*
|
|
Packit Service |
a9384c |
* cryptsetup volume key implementation
|
|
Packit Service |
a9384c |
*
|
|
Packit Service |
a9384c |
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
|
|
Packit Service |
a9384c |
* Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved.
|
|
Packit Service |
a9384c |
*
|
|
Packit Service |
a9384c |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
a9384c |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
a9384c |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
a9384c |
* of the License, or (at your option) any later version.
|
|
Packit Service |
a9384c |
*
|
|
Packit Service |
a9384c |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
a9384c |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
a9384c |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
a9384c |
* GNU General Public License for more details.
|
|
Packit Service |
a9384c |
*
|
|
Packit Service |
a9384c |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
a9384c |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
a9384c |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit Service |
a9384c |
*/
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
#include <string.h>
|
|
Packit Service |
a9384c |
#include <stdint.h>
|
|
Packit Service |
a9384c |
#include <stdlib.h>
|
|
Packit Service |
a9384c |
#include <errno.h>
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
#include "internal.h"
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
struct volume_key *crypt_alloc_volume_key(size_t keylength, const char *key)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
struct volume_key *vk;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
if (keylength > (SIZE_MAX - sizeof(*vk)))
|
|
Packit Service |
a9384c |
return NULL;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
vk = malloc(sizeof(*vk) + keylength);
|
|
Packit Service |
a9384c |
if (!vk)
|
|
Packit Service |
a9384c |
return NULL;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
vk->key_description = NULL;
|
|
Packit Service |
a9384c |
vk->keylength = keylength;
|
|
Packit Service |
a9384c |
vk->id = -1;
|
|
Packit Service |
a9384c |
vk->next = NULL;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
/* keylength 0 is valid => no key */
|
|
Packit Service |
a9384c |
if (vk->keylength) {
|
|
Packit Service |
a9384c |
if (key)
|
|
Packit Service |
a9384c |
memcpy(&vk->key, key, keylength);
|
|
Packit Service |
a9384c |
else
|
|
Packit Service |
a9384c |
crypt_safe_memzero(&vk->key, keylength);
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
return vk;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
int crypt_volume_key_set_description(struct volume_key *vk, const char *key_description)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
if (!vk)
|
|
Packit Service |
a9384c |
return -EINVAL;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
free(CONST_CAST(void*)vk->key_description);
|
|
Packit Service |
a9384c |
vk->key_description = NULL;
|
|
Packit Service |
a9384c |
if (key_description && !(vk->key_description = strdup(key_description)))
|
|
Packit Service |
a9384c |
return -ENOMEM;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
return 0;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
void crypt_volume_key_set_id(struct volume_key *vk, int id)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
if (vk && id >= 0)
|
|
Packit Service |
a9384c |
vk->id = id;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
int crypt_volume_key_get_id(const struct volume_key *vk)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
return vk ? vk->id : -1;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
struct volume_key *crypt_volume_key_by_id(struct volume_key *vks, int id)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
struct volume_key *vk = vks;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
if (id < 0)
|
|
Packit Service |
a9384c |
return NULL;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
while (vk && vk->id != id)
|
|
Packit Service |
a9384c |
vk = vk->next;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
return vk;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
void crypt_volume_key_add_next(struct volume_key **vks, struct volume_key *vk)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
struct volume_key *tmp;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
if (!vks)
|
|
Packit Service |
a9384c |
return;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
if (!*vks) {
|
|
Packit Service |
a9384c |
*vks = vk;
|
|
Packit Service |
a9384c |
return;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
tmp = *vks;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
while (tmp->next)
|
|
Packit Service |
a9384c |
tmp = tmp->next;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
tmp->next = vk;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
struct volume_key *crypt_volume_key_next(struct volume_key *vk)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
return vk ? vk->next : NULL;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
void crypt_free_volume_key(struct volume_key *vk)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
struct volume_key *vk_next;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
while (vk) {
|
|
Packit Service |
a9384c |
crypt_safe_memzero(vk->key, vk->keylength);
|
|
Packit Service |
a9384c |
vk->keylength = 0;
|
|
Packit Service |
a9384c |
free(CONST_CAST(void*)vk->key_description);
|
|
Packit Service |
a9384c |
vk_next = vk->next;
|
|
Packit Service |
a9384c |
free(vk);
|
|
Packit Service |
a9384c |
vk = vk_next;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, size_t keylength)
|
|
Packit Service |
a9384c |
{
|
|
Packit Service |
a9384c |
int r;
|
|
Packit Service |
a9384c |
struct volume_key *vk;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
vk = crypt_alloc_volume_key(keylength, NULL);
|
|
Packit Service |
a9384c |
if (!vk)
|
|
Packit Service |
a9384c |
return NULL;
|
|
Packit Service |
a9384c |
|
|
Packit Service |
a9384c |
r = crypt_random_get(cd, vk->key, keylength, CRYPT_RND_KEY);
|
|
Packit Service |
a9384c |
if(r < 0) {
|
|
Packit Service |
a9384c |
crypt_free_volume_key(vk);
|
|
Packit Service |
a9384c |
return NULL;
|
|
Packit Service |
a9384c |
}
|
|
Packit Service |
a9384c |
return vk;
|
|
Packit Service |
a9384c |
}
|