10d9ba1e1SAlex Hornung /*
20d9ba1e1SAlex Hornung * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
30d9ba1e1SAlex Hornung * All rights reserved.
40d9ba1e1SAlex Hornung *
50d9ba1e1SAlex Hornung * Redistribution and use in source and binary forms, with or without
60d9ba1e1SAlex Hornung * modification, are permitted provided that the following conditions
70d9ba1e1SAlex Hornung * are met:
80d9ba1e1SAlex Hornung *
90d9ba1e1SAlex Hornung * 1. Redistributions of source code must retain the above copyright
100d9ba1e1SAlex Hornung * notice, this list of conditions and the following disclaimer.
110d9ba1e1SAlex Hornung * 2. Redistributions in binary form must reproduce the above copyright
120d9ba1e1SAlex Hornung * notice, this list of conditions and the following disclaimer in
130d9ba1e1SAlex Hornung * the documentation and/or other materials provided with the
140d9ba1e1SAlex Hornung * distribution.
150d9ba1e1SAlex Hornung *
160d9ba1e1SAlex Hornung * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
170d9ba1e1SAlex Hornung * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
180d9ba1e1SAlex Hornung * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
190d9ba1e1SAlex Hornung * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
200d9ba1e1SAlex Hornung * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
210d9ba1e1SAlex Hornung * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
220d9ba1e1SAlex Hornung * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
230d9ba1e1SAlex Hornung * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
240d9ba1e1SAlex Hornung * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
250d9ba1e1SAlex Hornung * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
260d9ba1e1SAlex Hornung * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
270d9ba1e1SAlex Hornung * SUCH DAMAGE.
280d9ba1e1SAlex Hornung */
2981b79547SAlex Hornung
300d9ba1e1SAlex Hornung #include <sys/types.h>
3181b79547SAlex Hornung
3281b79547SAlex Hornung #if defined(__DragonFly__)
330d9ba1e1SAlex Hornung #include <sys/endian.h>
3481b79547SAlex Hornung #elif defined(__linux__)
3581b79547SAlex Hornung #include <endian.h>
3681b79547SAlex Hornung #endif
370d9ba1e1SAlex Hornung #include <errno.h>
380d9ba1e1SAlex Hornung #include <stdio.h>
390d9ba1e1SAlex Hornung #include <stdlib.h>
4081b79547SAlex Hornung #include <inttypes.h>
410d9ba1e1SAlex Hornung #include <string.h>
420d9ba1e1SAlex Hornung
430d9ba1e1SAlex Hornung #include "crc32.h"
440d9ba1e1SAlex Hornung #include "tcplay.h"
450d9ba1e1SAlex Hornung
460d9ba1e1SAlex Hornung /* Endianess macros */
470d9ba1e1SAlex Hornung #define BE_TO_HOST(n, v) v = be ## n ## toh(v)
480d9ba1e1SAlex Hornung #define LE_TO_HOST(n, v) v = le ## n ## toh(v)
490d9ba1e1SAlex Hornung #define HOST_TO_BE(n, v) v = htobe ## n (v)
500d9ba1e1SAlex Hornung #define HOST_TO_LE(n, v) v = htole ## n (v)
510d9ba1e1SAlex Hornung
52*7b1e1c8eSDaniel Fojt struct sig_hdr_cfg {
53*7b1e1c8eSDaniel Fojt const char *sig;
54*7b1e1c8eSDaniel Fojt uint16_t min_ver;
55*7b1e1c8eSDaniel Fojt };
56*7b1e1c8eSDaniel Fojt
57*7b1e1c8eSDaniel Fojt struct sig_hdr_cfg sig_hdr_cfgs[] = {
58*7b1e1c8eSDaniel Fojt { TC_SIG, 0x0007 },
59*7b1e1c8eSDaniel Fojt { VC_SIG, 0x0b01 },
60*7b1e1c8eSDaniel Fojt { NULL, 0x0000 }
61*7b1e1c8eSDaniel Fojt };
62*7b1e1c8eSDaniel Fojt
63*7b1e1c8eSDaniel Fojt static
64*7b1e1c8eSDaniel Fojt const
hdr_cfg_from_sig(const char * sig)65*7b1e1c8eSDaniel Fojt struct sig_hdr_cfg *hdr_cfg_from_sig(const char *sig)
66*7b1e1c8eSDaniel Fojt {
67*7b1e1c8eSDaniel Fojt const struct sig_hdr_cfg *cfg;
68*7b1e1c8eSDaniel Fojt
69*7b1e1c8eSDaniel Fojt for (cfg = &sig_hdr_cfgs[0]; cfg->sig != NULL; cfg++) {
70*7b1e1c8eSDaniel Fojt if (strcmp(cfg->sig, sig) == 0)
71*7b1e1c8eSDaniel Fojt return cfg;
72*7b1e1c8eSDaniel Fojt }
73*7b1e1c8eSDaniel Fojt
74*7b1e1c8eSDaniel Fojt return NULL;
75*7b1e1c8eSDaniel Fojt }
76*7b1e1c8eSDaniel Fojt
770d9ba1e1SAlex Hornung struct tchdr_dec *
decrypt_hdr(struct tchdr_enc * ehdr,struct tc_cipher_chain * cipher_chain,unsigned char * key)780d9ba1e1SAlex Hornung decrypt_hdr(struct tchdr_enc *ehdr, struct tc_cipher_chain *cipher_chain,
790d9ba1e1SAlex Hornung unsigned char *key)
800d9ba1e1SAlex Hornung {
810d9ba1e1SAlex Hornung struct tchdr_dec *dhdr;
820d9ba1e1SAlex Hornung unsigned char iv[128];
830d9ba1e1SAlex Hornung int error;
840d9ba1e1SAlex Hornung
850d9ba1e1SAlex Hornung if ((dhdr = alloc_safe_mem(sizeof(struct tchdr_dec))) == NULL) {
860d9ba1e1SAlex Hornung tc_log(1, "Error allocating safe tchdr_dec memory\n");
870d9ba1e1SAlex Hornung return NULL;
880d9ba1e1SAlex Hornung }
890d9ba1e1SAlex Hornung
900d9ba1e1SAlex Hornung memset(iv, 0, sizeof(iv));
910d9ba1e1SAlex Hornung
920d9ba1e1SAlex Hornung error = tc_decrypt(cipher_chain, key, iv, ehdr->enc,
930d9ba1e1SAlex Hornung sizeof(struct tchdr_dec), (unsigned char *)dhdr);
940d9ba1e1SAlex Hornung if (error) {
950d9ba1e1SAlex Hornung tc_log(1, "Header decryption failed\n");
960d9ba1e1SAlex Hornung free_safe_mem(dhdr);
970d9ba1e1SAlex Hornung return NULL;
980d9ba1e1SAlex Hornung }
990d9ba1e1SAlex Hornung
1000d9ba1e1SAlex Hornung BE_TO_HOST(16, dhdr->tc_ver);
1010d9ba1e1SAlex Hornung LE_TO_HOST(16, dhdr->tc_min_ver);
1020d9ba1e1SAlex Hornung BE_TO_HOST(32, dhdr->crc_keys);
1030d9ba1e1SAlex Hornung BE_TO_HOST(64, dhdr->vol_ctime);
1040d9ba1e1SAlex Hornung BE_TO_HOST(64, dhdr->hdr_ctime);
1050d9ba1e1SAlex Hornung BE_TO_HOST(64, dhdr->sz_hidvol);
1060d9ba1e1SAlex Hornung BE_TO_HOST(64, dhdr->sz_vol);
1070d9ba1e1SAlex Hornung BE_TO_HOST(64, dhdr->off_mk_scope);
1080d9ba1e1SAlex Hornung BE_TO_HOST(64, dhdr->sz_mk_scope);
1090d9ba1e1SAlex Hornung BE_TO_HOST(32, dhdr->flags);
1100d9ba1e1SAlex Hornung BE_TO_HOST(32, dhdr->sec_sz);
1110d9ba1e1SAlex Hornung BE_TO_HOST(32, dhdr->crc_dhdr);
1120d9ba1e1SAlex Hornung
1130d9ba1e1SAlex Hornung return dhdr;
1140d9ba1e1SAlex Hornung }
1150d9ba1e1SAlex Hornung
1160d9ba1e1SAlex Hornung int
verify_hdr(struct tchdr_dec * hdr,struct pbkdf_prf_algo * prf_algo)117*7b1e1c8eSDaniel Fojt verify_hdr(struct tchdr_dec *hdr, struct pbkdf_prf_algo *prf_algo)
1180d9ba1e1SAlex Hornung {
1190d9ba1e1SAlex Hornung uint32_t crc;
1200d9ba1e1SAlex Hornung
121*7b1e1c8eSDaniel Fojt if (memcmp(hdr->tc_str, prf_algo->sig, sizeof(hdr->tc_str)) != 0) {
1220d9ba1e1SAlex Hornung #ifdef DEBUG
1230d9ba1e1SAlex Hornung fprintf(stderr, "Signature mismatch\n");
1240d9ba1e1SAlex Hornung #endif
1250d9ba1e1SAlex Hornung return 0;
1260d9ba1e1SAlex Hornung }
1270d9ba1e1SAlex Hornung
128c833cfcfSAlex Hornung crc = crc32((void *)&hdr->keys, 256);
1290d9ba1e1SAlex Hornung if (crc != hdr->crc_keys) {
1300d9ba1e1SAlex Hornung #ifdef DEBUG
1310d9ba1e1SAlex Hornung fprintf(stderr, "CRC32 mismatch (crc_keys)\n");
1320d9ba1e1SAlex Hornung #endif
1330d9ba1e1SAlex Hornung return 0;
1340d9ba1e1SAlex Hornung }
1350d9ba1e1SAlex Hornung
1360d9ba1e1SAlex Hornung switch(hdr->tc_ver) {
1370d9ba1e1SAlex Hornung case 1:
1380d9ba1e1SAlex Hornung case 2:
1390d9ba1e1SAlex Hornung /* Unsupported header version */
1400d9ba1e1SAlex Hornung tc_log(1, "Header version %d unsupported\n", hdr->tc_ver);
1410d9ba1e1SAlex Hornung return 0;
1420d9ba1e1SAlex Hornung
1430d9ba1e1SAlex Hornung case 3:
1440d9ba1e1SAlex Hornung case 4:
1450d9ba1e1SAlex Hornung hdr->sec_sz = 512;
1460d9ba1e1SAlex Hornung break;
1470d9ba1e1SAlex Hornung }
1480d9ba1e1SAlex Hornung
1490d9ba1e1SAlex Hornung return 1;
1500d9ba1e1SAlex Hornung }
1510d9ba1e1SAlex Hornung
1520d9ba1e1SAlex Hornung struct tchdr_enc *
create_hdr(unsigned char * pass,int passlen,struct pbkdf_prf_algo * prf_algo,struct tc_cipher_chain * cipher_chain,size_t sec_sz,disksz_t total_blocks __unused,off_t offset,disksz_t blocks,int hidden,int weak,struct tchdr_enc ** backup_hdr)1530d9ba1e1SAlex Hornung create_hdr(unsigned char *pass, int passlen, struct pbkdf_prf_algo *prf_algo,
1540d9ba1e1SAlex Hornung struct tc_cipher_chain *cipher_chain, size_t sec_sz,
155c833cfcfSAlex Hornung disksz_t total_blocks __unused,
156c833cfcfSAlex Hornung off_t offset, disksz_t blocks, int hidden, int weak, struct tchdr_enc **backup_hdr)
1570d9ba1e1SAlex Hornung {
15881b79547SAlex Hornung struct tchdr_enc *ehdr, *ehdr_backup;
1590d9ba1e1SAlex Hornung struct tchdr_dec *dhdr;
16081b79547SAlex Hornung unsigned char *key, *key_backup;
1610d9ba1e1SAlex Hornung unsigned char iv[128];
162*7b1e1c8eSDaniel Fojt const struct sig_hdr_cfg *hdr_cfg;
1630d9ba1e1SAlex Hornung int error;
1640d9ba1e1SAlex Hornung
16581b79547SAlex Hornung key = key_backup = NULL;
16681b79547SAlex Hornung dhdr = NULL;
16781b79547SAlex Hornung ehdr = ehdr_backup = NULL;
16881b79547SAlex Hornung
16981b79547SAlex Hornung if (backup_hdr != NULL)
17081b79547SAlex Hornung *backup_hdr = NULL;
17181b79547SAlex Hornung
1720d9ba1e1SAlex Hornung if ((dhdr = (struct tchdr_dec *)alloc_safe_mem(sizeof(*dhdr))) == NULL) {
1730d9ba1e1SAlex Hornung tc_log(1, "could not allocate safe dhdr memory\n");
17481b79547SAlex Hornung goto error;
1750d9ba1e1SAlex Hornung }
1760d9ba1e1SAlex Hornung
1770d9ba1e1SAlex Hornung if ((ehdr = (struct tchdr_enc *)alloc_safe_mem(sizeof(*ehdr))) == NULL) {
1780d9ba1e1SAlex Hornung tc_log(1, "could not allocate safe ehdr memory\n");
17981b79547SAlex Hornung goto error;
18081b79547SAlex Hornung }
18181b79547SAlex Hornung
18281b79547SAlex Hornung if ((ehdr_backup = (struct tchdr_enc *)alloc_safe_mem
18381b79547SAlex Hornung (sizeof(*ehdr_backup))) == NULL) {
18481b79547SAlex Hornung tc_log(1, "could not allocate safe ehdr_backup memory\n");
18581b79547SAlex Hornung goto error;
1860d9ba1e1SAlex Hornung }
1870d9ba1e1SAlex Hornung
1880d9ba1e1SAlex Hornung if ((key = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
1890d9ba1e1SAlex Hornung tc_log(1, "could not allocate safe key memory\n");
19081b79547SAlex Hornung goto error;
19181b79547SAlex Hornung }
19281b79547SAlex Hornung
19381b79547SAlex Hornung if ((key_backup = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
19481b79547SAlex Hornung tc_log(1, "could not allocate safe backup key memory\n");
19581b79547SAlex Hornung goto error;
1960d9ba1e1SAlex Hornung }
1970d9ba1e1SAlex Hornung
198c833cfcfSAlex Hornung if ((error = get_random(ehdr->salt, sizeof(ehdr->salt), weak)) != 0) {
1990d9ba1e1SAlex Hornung tc_log(1, "could not get salt\n");
20081b79547SAlex Hornung goto error;
2010d9ba1e1SAlex Hornung }
2020d9ba1e1SAlex Hornung
203c833cfcfSAlex Hornung if ((error = get_random(ehdr_backup->salt, sizeof(ehdr_backup->salt), weak))
20481b79547SAlex Hornung != 0) {
20581b79547SAlex Hornung tc_log(1, "could not get salt for backup header\n");
20681b79547SAlex Hornung goto error;
20781b79547SAlex Hornung }
20881b79547SAlex Hornung
20981b79547SAlex Hornung error = pbkdf2(prf_algo, (char *)pass, passlen,
2100d9ba1e1SAlex Hornung ehdr->salt, sizeof(ehdr->salt),
21181b79547SAlex Hornung MAX_KEYSZ, key);
2120d9ba1e1SAlex Hornung if (error) {
2130d9ba1e1SAlex Hornung tc_log(1, "could not derive key\n");
21481b79547SAlex Hornung goto error;
21581b79547SAlex Hornung }
21681b79547SAlex Hornung
21781b79547SAlex Hornung error = pbkdf2(prf_algo, (char *)pass, passlen,
21881b79547SAlex Hornung ehdr_backup->salt, sizeof(ehdr_backup->salt),
21981b79547SAlex Hornung MAX_KEYSZ, key_backup);
22081b79547SAlex Hornung if (error) {
22181b79547SAlex Hornung tc_log(1, "could not derive backup key\n");
22281b79547SAlex Hornung goto error;
2230d9ba1e1SAlex Hornung }
2240d9ba1e1SAlex Hornung
2250d9ba1e1SAlex Hornung memset(dhdr, 0, sizeof(*dhdr));
2260d9ba1e1SAlex Hornung
227c833cfcfSAlex Hornung if ((error = get_random(dhdr->keys, sizeof(dhdr->keys), weak)) != 0) {
2280d9ba1e1SAlex Hornung tc_log(1, "could not get key random bits\n");
22981b79547SAlex Hornung goto error;
2300d9ba1e1SAlex Hornung }
2310d9ba1e1SAlex Hornung
232*7b1e1c8eSDaniel Fojt if ((hdr_cfg = hdr_cfg_from_sig(prf_algo->sig)) == NULL) {
233*7b1e1c8eSDaniel Fojt tc_log(1, "could not find internal header configuration\n");
234*7b1e1c8eSDaniel Fojt goto error;
235*7b1e1c8eSDaniel Fojt }
236*7b1e1c8eSDaniel Fojt
237*7b1e1c8eSDaniel Fojt memcpy(dhdr->tc_str, prf_algo->sig, 4);
2380d9ba1e1SAlex Hornung dhdr->tc_ver = 5;
239*7b1e1c8eSDaniel Fojt dhdr->tc_min_ver = hdr_cfg->min_ver;
2400d9ba1e1SAlex Hornung dhdr->crc_keys = crc32((void *)&dhdr->keys, 256);
2410d9ba1e1SAlex Hornung dhdr->sz_vol = blocks * sec_sz;
2420d9ba1e1SAlex Hornung if (hidden)
2430d9ba1e1SAlex Hornung dhdr->sz_hidvol = dhdr->sz_vol;
2440d9ba1e1SAlex Hornung dhdr->off_mk_scope = offset * sec_sz;
2450d9ba1e1SAlex Hornung dhdr->sz_mk_scope = blocks * sec_sz;
2460d9ba1e1SAlex Hornung dhdr->sec_sz = sec_sz;
2470d9ba1e1SAlex Hornung dhdr->flags = 0;
2480d9ba1e1SAlex Hornung
2490d9ba1e1SAlex Hornung HOST_TO_BE(16, dhdr->tc_ver);
2500d9ba1e1SAlex Hornung HOST_TO_LE(16, dhdr->tc_min_ver);
2510d9ba1e1SAlex Hornung HOST_TO_BE(32, dhdr->crc_keys);
2520d9ba1e1SAlex Hornung HOST_TO_BE(64, dhdr->sz_vol);
2530d9ba1e1SAlex Hornung HOST_TO_BE(64, dhdr->sz_hidvol);
2540d9ba1e1SAlex Hornung HOST_TO_BE(64, dhdr->off_mk_scope);
2550d9ba1e1SAlex Hornung HOST_TO_BE(64, dhdr->sz_mk_scope);
2560d9ba1e1SAlex Hornung HOST_TO_BE(32, dhdr->sec_sz);
2570d9ba1e1SAlex Hornung HOST_TO_BE(32, dhdr->flags);
2580d9ba1e1SAlex Hornung
2590d9ba1e1SAlex Hornung dhdr->crc_dhdr = crc32((void *)dhdr, 188);
2600d9ba1e1SAlex Hornung HOST_TO_BE(32, dhdr->crc_dhdr);
2610d9ba1e1SAlex Hornung
2620d9ba1e1SAlex Hornung memset(iv, 0, sizeof(iv));
2630d9ba1e1SAlex Hornung error = tc_encrypt(cipher_chain, key, iv, (unsigned char *)dhdr,
2640d9ba1e1SAlex Hornung sizeof(struct tchdr_dec), ehdr->enc);
2650d9ba1e1SAlex Hornung if (error) {
2660d9ba1e1SAlex Hornung tc_log(1, "Header encryption failed\n");
26781b79547SAlex Hornung goto error;
2680d9ba1e1SAlex Hornung }
2690d9ba1e1SAlex Hornung
27081b79547SAlex Hornung memset(iv, 0, sizeof(iv));
27181b79547SAlex Hornung error = tc_encrypt(cipher_chain, key_backup, iv,
27281b79547SAlex Hornung (unsigned char *)dhdr,
27381b79547SAlex Hornung sizeof(struct tchdr_dec), ehdr_backup->enc);
27481b79547SAlex Hornung if (error) {
27581b79547SAlex Hornung tc_log(1, "Backup header encryption failed\n");
27681b79547SAlex Hornung goto error;
27781b79547SAlex Hornung }
27881b79547SAlex Hornung
27981b79547SAlex Hornung free_safe_mem(key);
28081b79547SAlex Hornung free_safe_mem(key_backup);
2810d9ba1e1SAlex Hornung free_safe_mem(dhdr);
28281b79547SAlex Hornung
28381b79547SAlex Hornung if (backup_hdr != NULL)
28481b79547SAlex Hornung *backup_hdr = ehdr_backup;
28581b79547SAlex Hornung else
28681b79547SAlex Hornung free_safe_mem(ehdr_backup);
28781b79547SAlex Hornung
2880d9ba1e1SAlex Hornung return ehdr;
28981b79547SAlex Hornung /* NOT REACHED */
29081b79547SAlex Hornung
29181b79547SAlex Hornung error:
29281b79547SAlex Hornung if (key)
29381b79547SAlex Hornung free_safe_mem(key);
29481b79547SAlex Hornung if (key_backup)
29581b79547SAlex Hornung free_safe_mem(key_backup);
29681b79547SAlex Hornung if (dhdr)
29781b79547SAlex Hornung free_safe_mem(dhdr);
29881b79547SAlex Hornung if (ehdr)
29981b79547SAlex Hornung free_safe_mem(ehdr);
30081b79547SAlex Hornung if (ehdr_backup)
30181b79547SAlex Hornung free_safe_mem(ehdr_backup);
30281b79547SAlex Hornung
30381b79547SAlex Hornung return NULL;
3040d9ba1e1SAlex Hornung }
305c833cfcfSAlex Hornung
copy_reencrypt_hdr(unsigned char * pass,int passlen,struct pbkdf_prf_algo * prf_algo,int weak,struct tcplay_info * info,struct tchdr_enc ** backup_hdr)306c833cfcfSAlex Hornung struct tchdr_enc *copy_reencrypt_hdr(unsigned char *pass, int passlen,
307c833cfcfSAlex Hornung struct pbkdf_prf_algo *prf_algo, int weak, struct tcplay_info *info,
308c833cfcfSAlex Hornung struct tchdr_enc **backup_hdr)
309c833cfcfSAlex Hornung {
310c833cfcfSAlex Hornung struct tchdr_enc *ehdr, *ehdr_backup;
311c833cfcfSAlex Hornung unsigned char *key, *key_backup;
312c833cfcfSAlex Hornung unsigned char iv[128];
313*7b1e1c8eSDaniel Fojt const struct sig_hdr_cfg *hdr_cfg;
314c833cfcfSAlex Hornung int error;
315c833cfcfSAlex Hornung
316c833cfcfSAlex Hornung key = key_backup = NULL;
317c833cfcfSAlex Hornung ehdr = ehdr_backup = NULL;
318c833cfcfSAlex Hornung
319c833cfcfSAlex Hornung /* By default stick to current PRF algo */
320c833cfcfSAlex Hornung if (prf_algo == NULL)
321c833cfcfSAlex Hornung prf_algo = info->pbkdf_prf;
322c833cfcfSAlex Hornung
323c833cfcfSAlex Hornung if ((ehdr = (struct tchdr_enc *)alloc_safe_mem(sizeof(*ehdr))) == NULL) {
324c833cfcfSAlex Hornung tc_log(1, "could not allocate safe ehdr memory\n");
325c833cfcfSAlex Hornung goto error;
326c833cfcfSAlex Hornung }
327c833cfcfSAlex Hornung
328c833cfcfSAlex Hornung if ((ehdr_backup = (struct tchdr_enc *)alloc_safe_mem
329c833cfcfSAlex Hornung (sizeof(*ehdr_backup))) == NULL) {
330c833cfcfSAlex Hornung tc_log(1, "could not allocate safe ehdr_backup memory\n");
331c833cfcfSAlex Hornung goto error;
332c833cfcfSAlex Hornung }
333c833cfcfSAlex Hornung
334c833cfcfSAlex Hornung if ((key = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
335c833cfcfSAlex Hornung tc_log(1, "could not allocate safe key memory\n");
336c833cfcfSAlex Hornung goto error;
337c833cfcfSAlex Hornung }
338c833cfcfSAlex Hornung
339c833cfcfSAlex Hornung if ((key_backup = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
340c833cfcfSAlex Hornung tc_log(1, "could not allocate safe backup key memory\n");
341c833cfcfSAlex Hornung goto error;
342c833cfcfSAlex Hornung }
343c833cfcfSAlex Hornung
344c833cfcfSAlex Hornung if ((error = get_random(ehdr->salt, sizeof(ehdr->salt), weak)) != 0) {
345c833cfcfSAlex Hornung tc_log(1, "could not get salt\n");
346c833cfcfSAlex Hornung goto error;
347c833cfcfSAlex Hornung }
348c833cfcfSAlex Hornung
349c833cfcfSAlex Hornung if ((error = get_random(ehdr_backup->salt, sizeof(ehdr_backup->salt), weak))
350c833cfcfSAlex Hornung != 0) {
351c833cfcfSAlex Hornung tc_log(1, "could not get salt for backup header\n");
352c833cfcfSAlex Hornung goto error;
353c833cfcfSAlex Hornung }
354c833cfcfSAlex Hornung
355c833cfcfSAlex Hornung error = pbkdf2(prf_algo, (char *)pass, passlen,
356c833cfcfSAlex Hornung ehdr->salt, sizeof(ehdr->salt),
357c833cfcfSAlex Hornung MAX_KEYSZ, key);
358c833cfcfSAlex Hornung if (error) {
359c833cfcfSAlex Hornung tc_log(1, "could not derive key\n");
360c833cfcfSAlex Hornung goto error;
361c833cfcfSAlex Hornung }
362c833cfcfSAlex Hornung
363c833cfcfSAlex Hornung error = pbkdf2(prf_algo, (char *)pass, passlen,
364c833cfcfSAlex Hornung ehdr_backup->salt, sizeof(ehdr_backup->salt),
365c833cfcfSAlex Hornung MAX_KEYSZ, key_backup);
366c833cfcfSAlex Hornung if (error) {
367c833cfcfSAlex Hornung tc_log(1, "could not derive backup key\n");
368c833cfcfSAlex Hornung goto error;
369c833cfcfSAlex Hornung }
370c833cfcfSAlex Hornung
371*7b1e1c8eSDaniel Fojt if ((hdr_cfg = hdr_cfg_from_sig(prf_algo->sig)) == NULL) {
372*7b1e1c8eSDaniel Fojt tc_log(1, "could not find internal header configuration\n");
373*7b1e1c8eSDaniel Fojt goto error;
374*7b1e1c8eSDaniel Fojt }
375*7b1e1c8eSDaniel Fojt
376*7b1e1c8eSDaniel Fojt /* Update signature and min_ver depending on selected PBKDF2 PRF algo */
377*7b1e1c8eSDaniel Fojt memcpy(info->hdr->tc_str, prf_algo->sig, 4);
378*7b1e1c8eSDaniel Fojt info->hdr->tc_min_ver = hdr_cfg->min_ver;
379*7b1e1c8eSDaniel Fojt
380c833cfcfSAlex Hornung HOST_TO_BE(16, info->hdr->tc_ver);
381c833cfcfSAlex Hornung HOST_TO_LE(16, info->hdr->tc_min_ver);
382c833cfcfSAlex Hornung HOST_TO_BE(32, info->hdr->crc_keys);
383c833cfcfSAlex Hornung HOST_TO_BE(64, info->hdr->vol_ctime);
384c833cfcfSAlex Hornung HOST_TO_BE(64, info->hdr->hdr_ctime);
385c833cfcfSAlex Hornung HOST_TO_BE(64, info->hdr->sz_vol);
386c833cfcfSAlex Hornung HOST_TO_BE(64, info->hdr->sz_hidvol);
387c833cfcfSAlex Hornung HOST_TO_BE(64, info->hdr->off_mk_scope);
388c833cfcfSAlex Hornung HOST_TO_BE(64, info->hdr->sz_mk_scope);
389c833cfcfSAlex Hornung HOST_TO_BE(32, info->hdr->sec_sz);
390c833cfcfSAlex Hornung HOST_TO_BE(32, info->hdr->flags);
391c833cfcfSAlex Hornung HOST_TO_BE(32, info->hdr->crc_dhdr);
392c833cfcfSAlex Hornung
393c833cfcfSAlex Hornung memset(iv, 0, sizeof(iv));
394c833cfcfSAlex Hornung error = tc_encrypt(info->cipher_chain, key, iv,
395c833cfcfSAlex Hornung (unsigned char *)info->hdr, sizeof(struct tchdr_dec), ehdr->enc);
396c833cfcfSAlex Hornung if (error) {
397c833cfcfSAlex Hornung tc_log(1, "Header encryption failed\n");
398c833cfcfSAlex Hornung goto error;
399c833cfcfSAlex Hornung }
400c833cfcfSAlex Hornung
401c833cfcfSAlex Hornung memset(iv, 0, sizeof(iv));
402c833cfcfSAlex Hornung error = tc_encrypt(info->cipher_chain, key_backup, iv,
403c833cfcfSAlex Hornung (unsigned char *)info->hdr,
404c833cfcfSAlex Hornung sizeof(struct tchdr_dec), ehdr_backup->enc);
405c833cfcfSAlex Hornung if (error) {
406c833cfcfSAlex Hornung tc_log(1, "Backup header encryption failed\n");
407c833cfcfSAlex Hornung goto error;
408c833cfcfSAlex Hornung }
409c833cfcfSAlex Hornung
410c833cfcfSAlex Hornung free_safe_mem(key);
411c833cfcfSAlex Hornung free_safe_mem(key_backup);
412c833cfcfSAlex Hornung
413c833cfcfSAlex Hornung if (backup_hdr != NULL)
414c833cfcfSAlex Hornung *backup_hdr = ehdr_backup;
415c833cfcfSAlex Hornung else
416c833cfcfSAlex Hornung free_safe_mem(ehdr_backup);
417c833cfcfSAlex Hornung
418c833cfcfSAlex Hornung return ehdr;
419c833cfcfSAlex Hornung /* NOT REACHED */
420c833cfcfSAlex Hornung
421c833cfcfSAlex Hornung error:
422c833cfcfSAlex Hornung if (key)
423c833cfcfSAlex Hornung free_safe_mem(key);
424c833cfcfSAlex Hornung if (key_backup)
425c833cfcfSAlex Hornung free_safe_mem(key_backup);
426c833cfcfSAlex Hornung if (ehdr)
427c833cfcfSAlex Hornung free_safe_mem(ehdr);
428c833cfcfSAlex Hornung if (ehdr_backup)
429c833cfcfSAlex Hornung free_safe_mem(ehdr_backup);
430c833cfcfSAlex Hornung
431c833cfcfSAlex Hornung return NULL;
432c833cfcfSAlex Hornung }
433