1/* 2 * QEMU Crypto anti forensic information splitter 3 * 4 * Copyright (c) 2015-2016 Red Hat, Inc. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21#ifndef QCRYPTO_AFSPLIT_H__ 22#define QCRYPTO_AFSPLIT_H__ 23 24#include "crypto/hash.h" 25 26/** 27 * This module implements the anti-forensic splitter that is specified 28 * as part of the LUKS format: 29 * 30 * http://clemens.endorphin.org/cryptography 31 * http://clemens.endorphin.org/TKS1-draft.pdf 32 * 33 * The core idea is to take a short piece of data (key material) 34 * and process it to expand it to a much larger piece of data. 35 * The expansion process is reversible, to obtain the original 36 * short data. The key property of the expansion is that if any 37 * byte in the larger data set is changed / missing, it should be 38 * impossible to recreate the original short data. 39 * 40 * <example> 41 * <title>Creating a large split key for storage</title> 42 * <programlisting> 43 * size_t nkey = 32; 44 * uint32_t stripes = 32768; // To produce a 1 MB split key 45 * uint8_t *masterkey = ....a 32-byte AES key... 46 * uint8_t *splitkey; 47 * 48 * splitkey = g_new0(uint8_t, nkey * stripes); 49 * 50 * if (qcrypto_afsplit_encode(QCRYPTO_HASH_ALG_SHA256, 51 * nkey, stripes, 52 * masterkey, splitkey, errp) < 0) { 53 * g_free(splitkey); 54 * g_free(masterkey); 55 * return -1; 56 * } 57 * 58 * ...store splitkey somewhere... 59 * 60 * g_free(splitkey); 61 * g_free(masterkey); 62 * </programlisting> 63 * </example> 64 * 65 * <example> 66 * <title>Retrieving a master key from storage</title> 67 * <programlisting> 68 * size_t nkey = 32; 69 * uint32_t stripes = 32768; // To produce a 1 MB split key 70 * uint8_t *masterkey; 71 * uint8_t *splitkey = .... read in 1 MB of data... 72 * 73 * masterkey = g_new0(uint8_t, nkey); 74 * 75 * if (qcrypto_afsplit_decode(QCRYPTO_HASH_ALG_SHA256, 76 * nkey, stripes, 77 * splitkey, masterkey, errp) < 0) { 78 * g_free(splitkey); 79 * g_free(masterkey); 80 * return -1; 81 * } 82 * 83 * ..decrypt data with masterkey... 84 * 85 * g_free(splitkey); 86 * g_free(masterkey); 87 * </programlisting> 88 * </example> 89 */ 90 91/** 92 * qcrypto_afsplit_encode: 93 * @hash: the hash algorithm to use for data expansion 94 * @blocklen: the size of @in in bytes 95 * @stripes: the number of times to expand @in in size 96 * @in: the master key to be expanded in size 97 * @out: preallocated buffer to hold the split key 98 * @errp: pointer to a NULL-initialized error object 99 * 100 * Split the data in @in, which is @blocklen bytes in 101 * size, to form a larger piece of data @out, which is 102 * @blocklen * @stripes bytes in size. 103 * 104 * Returns: 0 on success, -1 on error; 105 */ 106int qcrypto_afsplit_encode(QCryptoHashAlgorithm hash, 107 size_t blocklen, 108 uint32_t stripes, 109 const uint8_t *in, 110 uint8_t *out, 111 Error **errp); 112 113/** 114 * qcrypto_afsplit_decode: 115 * @hash: the hash algorithm to use for data compression 116 * @blocklen: the size of @out in bytes 117 * @stripes: the number of times to decrease @in in size 118 * @in: the split key to be recombined 119 * @out: preallocated buffer to hold the master key 120 * @errp: pointer to a NULL-initialized error object 121 * 122 * Join the data in @in, which is @blocklen * @stripes 123 * bytes in size, to form the original small piece of 124 * data @out, which is @blocklen bytes in size. 125 * 126 * Returns: 0 on success, -1 on error; 127 */ 128int qcrypto_afsplit_decode(QCryptoHashAlgorithm hash, 129 size_t blocklen, 130 uint32_t stripes, 131 const uint8_t *in, 132 uint8_t *out, 133 Error **errp); 134 135#endif /* QCRYPTO_AFSPLIT_H__ */ 136