fab20f20d4a0312725fad555f6aede1dcfbf7aea
[dragonfly.git] / lib / libtcplay / hdr.c
1 /*
2  * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
20  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 #include <sys/types.h>
30 #include <sys/endian.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "crc32.h"
37 #include "tcplay.h"
38
39 /* Endianess macros */
40 #define BE_TO_HOST(n, v) v = be ## n ## toh(v)
41 #define LE_TO_HOST(n, v) v = le ## n ## toh(v)
42 #define HOST_TO_BE(n, v) v = htobe ## n (v)
43 #define HOST_TO_LE(n, v) v = htole ## n (v)
44
45 struct tchdr_dec *
46 decrypt_hdr(struct tchdr_enc *ehdr, struct tc_cipher_chain *cipher_chain,
47     unsigned char *key)
48 {
49         struct tchdr_dec *dhdr;
50         unsigned char iv[128];
51         int error;
52
53         if ((dhdr = alloc_safe_mem(sizeof(struct tchdr_dec))) == NULL) {
54                 tc_log(1, "Error allocating safe tchdr_dec memory\n");
55                 return NULL;
56         }
57
58         memset(iv, 0, sizeof(iv));
59
60         error = tc_decrypt(cipher_chain, key, iv, ehdr->enc,
61             sizeof(struct tchdr_dec), (unsigned char *)dhdr);
62         if (error) {
63                 tc_log(1, "Header decryption failed\n");
64                 free_safe_mem(dhdr);
65                 return NULL;
66         }
67
68         BE_TO_HOST(16, dhdr->tc_ver);
69         LE_TO_HOST(16, dhdr->tc_min_ver);
70         BE_TO_HOST(32, dhdr->crc_keys);
71         BE_TO_HOST(64, dhdr->vol_ctime);
72         BE_TO_HOST(64, dhdr->hdr_ctime);
73         BE_TO_HOST(64, dhdr->sz_hidvol);
74         BE_TO_HOST(64, dhdr->sz_vol);
75         BE_TO_HOST(64, dhdr->off_mk_scope);
76         BE_TO_HOST(64, dhdr->sz_mk_scope);
77         BE_TO_HOST(32, dhdr->flags);
78         BE_TO_HOST(32, dhdr->sec_sz);
79         BE_TO_HOST(32, dhdr->crc_dhdr);
80
81         return dhdr;
82 }
83
84 int
85 verify_hdr(struct tchdr_dec *hdr)
86 {
87         uint32_t crc;
88
89         if (memcmp(hdr->tc_str, TC_SIG, sizeof(hdr->tc_str)) != 0) {
90 #ifdef DEBUG
91                 fprintf(stderr, "Signature mismatch\n");
92 #endif
93                 return 0;
94         }
95
96         crc = crc32((void *)&hdr->keys, 256);
97         if (crc != hdr->crc_keys) {
98 #ifdef DEBUG
99                 fprintf(stderr, "CRC32 mismatch (crc_keys)\n");
100 #endif
101                 return 0;
102         }
103
104         switch(hdr->tc_ver) {
105         case 1:
106         case 2:
107                 /* Unsupported header version */
108                 tc_log(1, "Header version %d unsupported\n", hdr->tc_ver);
109                 return 0;
110
111         case 3:
112         case 4:
113                 hdr->sec_sz = 512;
114                 break;
115         }
116
117         return 1;
118 }
119
120 struct tchdr_enc *
121 create_hdr(unsigned char *pass, int passlen, struct pbkdf_prf_algo *prf_algo,
122     struct tc_cipher_chain *cipher_chain, size_t sec_sz,
123     size_t total_blocks __unused,
124     off_t offset, size_t blocks, int hidden)
125 {
126         struct tchdr_enc *ehdr;
127         struct tchdr_dec *dhdr;
128         unsigned char *key;
129         unsigned char iv[128];
130         int error;
131
132         if ((dhdr = (struct tchdr_dec *)alloc_safe_mem(sizeof(*dhdr))) == NULL) {
133                 tc_log(1, "could not allocate safe dhdr memory\n");
134                 return NULL;
135         }
136
137         if ((ehdr = (struct tchdr_enc *)alloc_safe_mem(sizeof(*ehdr))) == NULL) {
138                 tc_log(1, "could not allocate safe ehdr memory\n");
139                 return NULL;
140         }
141
142         if ((key = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
143                 tc_log(1, "could not allocate safe key memory\n");
144                 return NULL;
145         }
146
147         if ((error = get_random(ehdr->salt, sizeof(ehdr->salt))) != 0) {
148                 tc_log(1, "could not get salt\n");
149                 return NULL;
150         }
151
152         error = pbkdf2(pass, passlen,
153             ehdr->salt, sizeof(ehdr->salt),
154             prf_algo->iteration_count,
155             prf_algo->name, MAX_KEYSZ, key);
156         if (error) {
157                 tc_log(1, "could not derive key\n");
158                 return NULL;
159         }
160
161         memset(dhdr, 0, sizeof(*dhdr));
162
163         if ((error = get_random(dhdr->keys, sizeof(dhdr->keys))) != 0) {
164                 tc_log(1, "could not get key random bits\n");
165                 return NULL;
166         }
167
168         memcpy(dhdr->tc_str, "TRUE", 4);
169         dhdr->tc_ver = 5;
170         dhdr->tc_min_ver = 7;
171         dhdr->crc_keys = crc32((void *)&dhdr->keys, 256);
172         dhdr->sz_vol = blocks * sec_sz;
173         if (hidden)
174                 dhdr->sz_hidvol = dhdr->sz_vol;
175         dhdr->off_mk_scope = offset * sec_sz;
176         dhdr->sz_mk_scope = blocks * sec_sz;
177         dhdr->sec_sz = sec_sz;
178         dhdr->flags = 0;
179
180         HOST_TO_BE(16, dhdr->tc_ver);
181         HOST_TO_LE(16, dhdr->tc_min_ver);
182         HOST_TO_BE(32, dhdr->crc_keys);
183         HOST_TO_BE(64, dhdr->sz_vol);
184         HOST_TO_BE(64, dhdr->sz_hidvol);
185         HOST_TO_BE(64, dhdr->off_mk_scope);
186         HOST_TO_BE(64, dhdr->sz_mk_scope);
187         HOST_TO_BE(32, dhdr->sec_sz);
188         HOST_TO_BE(32, dhdr->flags);
189
190         dhdr->crc_dhdr = crc32((void *)dhdr, 188);
191         HOST_TO_BE(32, dhdr->crc_dhdr);
192
193         memset(iv, 0, sizeof(iv));
194         error = tc_encrypt(cipher_chain, key, iv, (unsigned char *)dhdr,
195             sizeof(struct tchdr_dec), ehdr->enc);
196         if (error) {
197                 tc_log(1, "Header encryption failed\n");
198                 free_safe_mem(dhdr);
199                 return NULL;
200         }
201
202         free_safe_mem(dhdr);
203         return ehdr;
204 }