1*5a95e0fcSDaniel P. Berrange /* 2*5a95e0fcSDaniel P. Berrange * QEMU Crypto anti forensic information splitter 3*5a95e0fcSDaniel P. Berrange * 4*5a95e0fcSDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 5*5a95e0fcSDaniel P. Berrange * 6*5a95e0fcSDaniel P. Berrange * Derived from cryptsetup package lib/luks1/af.c 7*5a95e0fcSDaniel P. Berrange * 8*5a95e0fcSDaniel P. Berrange * Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org> 9*5a95e0fcSDaniel P. Berrange * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. 10*5a95e0fcSDaniel P. Berrange * 11*5a95e0fcSDaniel P. Berrange * This library is free software; you can redistribute it and/or 12*5a95e0fcSDaniel P. Berrange * modify it under the terms of the GNU General Public License 13*5a95e0fcSDaniel P. Berrange * as published by the Free Software Foundation; either version 2 14*5a95e0fcSDaniel P. Berrange * of the License, or (at your option) any later version. 15*5a95e0fcSDaniel P. Berrange * 16*5a95e0fcSDaniel P. Berrange * This library is distributed in the hope that it will be useful, 17*5a95e0fcSDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 18*5a95e0fcSDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19*5a95e0fcSDaniel P. Berrange * Lesser General Public License for more details. 20*5a95e0fcSDaniel P. Berrange * 21*5a95e0fcSDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 22*5a95e0fcSDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 23*5a95e0fcSDaniel P. Berrange * 24*5a95e0fcSDaniel P. Berrange */ 25*5a95e0fcSDaniel P. Berrange 26*5a95e0fcSDaniel P. Berrange #include "qemu/osdep.h" 27*5a95e0fcSDaniel P. Berrange #include "crypto/afsplit.h" 28*5a95e0fcSDaniel P. Berrange #include "crypto/random.h" 29*5a95e0fcSDaniel P. Berrange 30*5a95e0fcSDaniel P. Berrange 31*5a95e0fcSDaniel P. Berrange static void qcrypto_afsplit_xor(size_t blocklen, 32*5a95e0fcSDaniel P. Berrange const uint8_t *in1, 33*5a95e0fcSDaniel P. Berrange const uint8_t *in2, 34*5a95e0fcSDaniel P. Berrange uint8_t *out) 35*5a95e0fcSDaniel P. Berrange { 36*5a95e0fcSDaniel P. Berrange size_t i; 37*5a95e0fcSDaniel P. Berrange for (i = 0; i < blocklen; i++) { 38*5a95e0fcSDaniel P. Berrange out[i] = in1[i] ^ in2[i]; 39*5a95e0fcSDaniel P. Berrange } 40*5a95e0fcSDaniel P. Berrange } 41*5a95e0fcSDaniel P. Berrange 42*5a95e0fcSDaniel P. Berrange 43*5a95e0fcSDaniel P. Berrange static int qcrypto_afsplit_hash(QCryptoHashAlgorithm hash, 44*5a95e0fcSDaniel P. Berrange size_t blocklen, 45*5a95e0fcSDaniel P. Berrange uint8_t *block, 46*5a95e0fcSDaniel P. Berrange Error **errp) 47*5a95e0fcSDaniel P. Berrange { 48*5a95e0fcSDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash); 49*5a95e0fcSDaniel P. Berrange 50*5a95e0fcSDaniel P. Berrange size_t hashcount = blocklen / digestlen; 51*5a95e0fcSDaniel P. Berrange size_t finallen = blocklen % digestlen; 52*5a95e0fcSDaniel P. Berrange uint32_t i; 53*5a95e0fcSDaniel P. Berrange 54*5a95e0fcSDaniel P. Berrange if (finallen) { 55*5a95e0fcSDaniel P. Berrange hashcount++; 56*5a95e0fcSDaniel P. Berrange } else { 57*5a95e0fcSDaniel P. Berrange finallen = digestlen; 58*5a95e0fcSDaniel P. Berrange } 59*5a95e0fcSDaniel P. Berrange 60*5a95e0fcSDaniel P. Berrange for (i = 0; i < hashcount; i++) { 61*5a95e0fcSDaniel P. Berrange uint8_t *out = NULL; 62*5a95e0fcSDaniel P. Berrange size_t outlen = 0; 63*5a95e0fcSDaniel P. Berrange uint32_t iv = cpu_to_be32(i); 64*5a95e0fcSDaniel P. Berrange struct iovec in[] = { 65*5a95e0fcSDaniel P. Berrange { .iov_base = &iv, 66*5a95e0fcSDaniel P. Berrange .iov_len = sizeof(iv) }, 67*5a95e0fcSDaniel P. Berrange { .iov_base = block + (i * digestlen), 68*5a95e0fcSDaniel P. Berrange .iov_len = (i == (hashcount - 1)) ? finallen : digestlen }, 69*5a95e0fcSDaniel P. Berrange }; 70*5a95e0fcSDaniel P. Berrange 71*5a95e0fcSDaniel P. Berrange if (qcrypto_hash_bytesv(hash, 72*5a95e0fcSDaniel P. Berrange in, 73*5a95e0fcSDaniel P. Berrange G_N_ELEMENTS(in), 74*5a95e0fcSDaniel P. Berrange &out, &outlen, 75*5a95e0fcSDaniel P. Berrange errp) < 0) { 76*5a95e0fcSDaniel P. Berrange return -1; 77*5a95e0fcSDaniel P. Berrange } 78*5a95e0fcSDaniel P. Berrange 79*5a95e0fcSDaniel P. Berrange assert(outlen == digestlen); 80*5a95e0fcSDaniel P. Berrange memcpy(block + (i * digestlen), out, 81*5a95e0fcSDaniel P. Berrange (i == (hashcount - 1)) ? finallen : digestlen); 82*5a95e0fcSDaniel P. Berrange g_free(out); 83*5a95e0fcSDaniel P. Berrange } 84*5a95e0fcSDaniel P. Berrange 85*5a95e0fcSDaniel P. Berrange return 0; 86*5a95e0fcSDaniel P. Berrange } 87*5a95e0fcSDaniel P. Berrange 88*5a95e0fcSDaniel P. Berrange 89*5a95e0fcSDaniel P. Berrange int qcrypto_afsplit_encode(QCryptoHashAlgorithm hash, 90*5a95e0fcSDaniel P. Berrange size_t blocklen, 91*5a95e0fcSDaniel P. Berrange uint32_t stripes, 92*5a95e0fcSDaniel P. Berrange const uint8_t *in, 93*5a95e0fcSDaniel P. Berrange uint8_t *out, 94*5a95e0fcSDaniel P. Berrange Error **errp) 95*5a95e0fcSDaniel P. Berrange { 96*5a95e0fcSDaniel P. Berrange uint8_t *block = g_new0(uint8_t, blocklen); 97*5a95e0fcSDaniel P. Berrange size_t i; 98*5a95e0fcSDaniel P. Berrange int ret = -1; 99*5a95e0fcSDaniel P. Berrange 100*5a95e0fcSDaniel P. Berrange for (i = 0; i < (stripes - 1); i++) { 101*5a95e0fcSDaniel P. Berrange if (qcrypto_random_bytes(out + (i * blocklen), blocklen, errp) < 0) { 102*5a95e0fcSDaniel P. Berrange goto cleanup; 103*5a95e0fcSDaniel P. Berrange } 104*5a95e0fcSDaniel P. Berrange 105*5a95e0fcSDaniel P. Berrange qcrypto_afsplit_xor(blocklen, 106*5a95e0fcSDaniel P. Berrange out + (i * blocklen), 107*5a95e0fcSDaniel P. Berrange block, 108*5a95e0fcSDaniel P. Berrange block); 109*5a95e0fcSDaniel P. Berrange if (qcrypto_afsplit_hash(hash, blocklen, block, 110*5a95e0fcSDaniel P. Berrange errp) < 0) { 111*5a95e0fcSDaniel P. Berrange goto cleanup; 112*5a95e0fcSDaniel P. Berrange } 113*5a95e0fcSDaniel P. Berrange } 114*5a95e0fcSDaniel P. Berrange qcrypto_afsplit_xor(blocklen, 115*5a95e0fcSDaniel P. Berrange in, 116*5a95e0fcSDaniel P. Berrange block, 117*5a95e0fcSDaniel P. Berrange out + (i * blocklen)); 118*5a95e0fcSDaniel P. Berrange ret = 0; 119*5a95e0fcSDaniel P. Berrange 120*5a95e0fcSDaniel P. Berrange cleanup: 121*5a95e0fcSDaniel P. Berrange g_free(block); 122*5a95e0fcSDaniel P. Berrange return ret; 123*5a95e0fcSDaniel P. Berrange } 124*5a95e0fcSDaniel P. Berrange 125*5a95e0fcSDaniel P. Berrange 126*5a95e0fcSDaniel P. Berrange int qcrypto_afsplit_decode(QCryptoHashAlgorithm hash, 127*5a95e0fcSDaniel P. Berrange size_t blocklen, 128*5a95e0fcSDaniel P. Berrange uint32_t stripes, 129*5a95e0fcSDaniel P. Berrange const uint8_t *in, 130*5a95e0fcSDaniel P. Berrange uint8_t *out, 131*5a95e0fcSDaniel P. Berrange Error **errp) 132*5a95e0fcSDaniel P. Berrange { 133*5a95e0fcSDaniel P. Berrange uint8_t *block = g_new0(uint8_t, blocklen); 134*5a95e0fcSDaniel P. Berrange size_t i; 135*5a95e0fcSDaniel P. Berrange int ret = -1; 136*5a95e0fcSDaniel P. Berrange 137*5a95e0fcSDaniel P. Berrange for (i = 0; i < (stripes - 1); i++) { 138*5a95e0fcSDaniel P. Berrange qcrypto_afsplit_xor(blocklen, 139*5a95e0fcSDaniel P. Berrange in + (i * blocklen), 140*5a95e0fcSDaniel P. Berrange block, 141*5a95e0fcSDaniel P. Berrange block); 142*5a95e0fcSDaniel P. Berrange if (qcrypto_afsplit_hash(hash, blocklen, block, 143*5a95e0fcSDaniel P. Berrange errp) < 0) { 144*5a95e0fcSDaniel P. Berrange goto cleanup; 145*5a95e0fcSDaniel P. Berrange } 146*5a95e0fcSDaniel P. Berrange } 147*5a95e0fcSDaniel P. Berrange 148*5a95e0fcSDaniel P. Berrange qcrypto_afsplit_xor(blocklen, 149*5a95e0fcSDaniel P. Berrange in + (i * blocklen), 150*5a95e0fcSDaniel P. Berrange block, 151*5a95e0fcSDaniel P. Berrange out); 152*5a95e0fcSDaniel P. Berrange 153*5a95e0fcSDaniel P. Berrange ret = 0; 154*5a95e0fcSDaniel P. Berrange 155*5a95e0fcSDaniel P. Berrange cleanup: 156*5a95e0fcSDaniel P. Berrange g_free(block); 157*5a95e0fcSDaniel P. Berrange return ret; 158*5a95e0fcSDaniel P. Berrange } 159