9a80529e38980346e0b97b95f336a6747491f09a
[platform/upstream/cryptsetup.git] / lib / volumekey.c
1 /*
2  * cryptsetup volume key implementation
3  *
4  * Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
5  * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "internal.h"
26
27 struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key)
28 {
29         struct volume_key *vk = malloc(sizeof(*vk) + keylength);
30
31         if (!vk)
32                 return NULL;
33
34         vk->keylength = keylength;
35         if (key)
36                 memcpy(&vk->key, key, keylength);
37         else
38                 memset(&vk->key, 0, keylength);
39
40         return vk;
41 }
42
43 void crypt_free_volume_key(struct volume_key *vk)
44 {
45         if (vk) {
46                 memset(vk->key, 0, vk->keylength);
47                 vk->keylength = 0;
48                 free(vk);
49         }
50 }
51
52 struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, unsigned keylength)
53 {
54         int r;
55         struct volume_key *vk;
56
57         vk = crypt_alloc_volume_key(keylength, NULL);
58         if (!vk)
59                 return NULL;
60
61         r = crypt_random_get(cd, vk->key, keylength, CRYPT_RND_KEY);
62         if(r < 0) {
63                 crypt_free_volume_key(vk);
64                 return NULL;
65         }
66         return vk;
67 }