15a95e0fcSDaniel P. Berrange /* 25a95e0fcSDaniel P. Berrange * QEMU Crypto anti forensic information splitter 35a95e0fcSDaniel P. Berrange * 45a95e0fcSDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 55a95e0fcSDaniel P. Berrange * 65a95e0fcSDaniel P. Berrange * Derived from cryptsetup package lib/luks1/af.c 75a95e0fcSDaniel P. Berrange * 85a95e0fcSDaniel P. Berrange * Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org> 95a95e0fcSDaniel P. Berrange * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved. 105a95e0fcSDaniel P. Berrange * 11e361a772SThomas Huth * This program is free software; you can redistribute it and/or 125a95e0fcSDaniel P. Berrange * modify it under the terms of the GNU General Public License 135a95e0fcSDaniel P. Berrange * as published by the Free Software Foundation; either version 2 145a95e0fcSDaniel P. Berrange * of the License, or (at your option) any later version. 155a95e0fcSDaniel P. Berrange * 16e361a772SThomas Huth * This program is distributed in the hope that it will be useful, 175a95e0fcSDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 185a95e0fcSDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19e361a772SThomas Huth * General Public License for more details. 205a95e0fcSDaniel P. Berrange * 21e361a772SThomas Huth * You should have received a copy of the GNU General Public License 22e361a772SThomas Huth * along with this program; if not, see <http://www.gnu.org/licenses/>. 235a95e0fcSDaniel P. Berrange */ 245a95e0fcSDaniel P. Berrange 255a95e0fcSDaniel P. Berrange #include "qemu/osdep.h" 2658369e22SPaolo Bonzini #include "qemu/bswap.h" 275a95e0fcSDaniel P. Berrange #include "crypto/afsplit.h" 285a95e0fcSDaniel P. Berrange #include "crypto/random.h" 295a95e0fcSDaniel P. Berrange 305a95e0fcSDaniel P. Berrange 315a95e0fcSDaniel P. Berrange static void qcrypto_afsplit_xor(size_t blocklen, 325a95e0fcSDaniel P. Berrange const uint8_t *in1, 335a95e0fcSDaniel P. Berrange const uint8_t *in2, 345a95e0fcSDaniel P. Berrange uint8_t *out) 355a95e0fcSDaniel P. Berrange { 365a95e0fcSDaniel P. Berrange size_t i; 375a95e0fcSDaniel P. Berrange for (i = 0; i < blocklen; i++) { 385a95e0fcSDaniel P. Berrange out[i] = in1[i] ^ in2[i]; 395a95e0fcSDaniel P. Berrange } 405a95e0fcSDaniel P. Berrange } 415a95e0fcSDaniel P. Berrange 425a95e0fcSDaniel P. Berrange 43*ef834aa2SMarkus Armbruster static int qcrypto_afsplit_hash(QCryptoHashAlgo hash, 445a95e0fcSDaniel P. Berrange size_t blocklen, 455a95e0fcSDaniel P. Berrange uint8_t *block, 465a95e0fcSDaniel P. Berrange Error **errp) 475a95e0fcSDaniel P. Berrange { 485a95e0fcSDaniel P. Berrange size_t digestlen = qcrypto_hash_digest_len(hash); 495a95e0fcSDaniel P. Berrange 505a95e0fcSDaniel P. Berrange size_t hashcount = blocklen / digestlen; 515a95e0fcSDaniel P. Berrange size_t finallen = blocklen % digestlen; 525a95e0fcSDaniel P. Berrange uint32_t i; 535a95e0fcSDaniel P. Berrange 545a95e0fcSDaniel P. Berrange if (finallen) { 555a95e0fcSDaniel P. Berrange hashcount++; 565a95e0fcSDaniel P. Berrange } else { 575a95e0fcSDaniel P. Berrange finallen = digestlen; 585a95e0fcSDaniel P. Berrange } 595a95e0fcSDaniel P. Berrange 605a95e0fcSDaniel P. Berrange for (i = 0; i < hashcount; i++) { 6157b9f113SDaniel P. Berrangé g_autofree uint8_t *out = NULL; 625a95e0fcSDaniel P. Berrange size_t outlen = 0; 635a95e0fcSDaniel P. Berrange uint32_t iv = cpu_to_be32(i); 645a95e0fcSDaniel P. Berrange struct iovec in[] = { 655a95e0fcSDaniel P. Berrange { .iov_base = &iv, 665a95e0fcSDaniel P. Berrange .iov_len = sizeof(iv) }, 675a95e0fcSDaniel P. Berrange { .iov_base = block + (i * digestlen), 685a95e0fcSDaniel P. Berrange .iov_len = (i == (hashcount - 1)) ? finallen : digestlen }, 695a95e0fcSDaniel P. Berrange }; 705a95e0fcSDaniel P. Berrange 715a95e0fcSDaniel P. Berrange if (qcrypto_hash_bytesv(hash, 725a95e0fcSDaniel P. Berrange in, 735a95e0fcSDaniel P. Berrange G_N_ELEMENTS(in), 745a95e0fcSDaniel P. Berrange &out, &outlen, 755a95e0fcSDaniel P. Berrange errp) < 0) { 765a95e0fcSDaniel P. Berrange return -1; 775a95e0fcSDaniel P. Berrange } 785a95e0fcSDaniel P. Berrange 795a95e0fcSDaniel P. Berrange assert(outlen == digestlen); 805a95e0fcSDaniel P. Berrange memcpy(block + (i * digestlen), out, 815a95e0fcSDaniel P. Berrange (i == (hashcount - 1)) ? finallen : digestlen); 825a95e0fcSDaniel P. Berrange } 835a95e0fcSDaniel P. Berrange 845a95e0fcSDaniel P. Berrange return 0; 855a95e0fcSDaniel P. Berrange } 865a95e0fcSDaniel P. Berrange 875a95e0fcSDaniel P. Berrange 88*ef834aa2SMarkus Armbruster int qcrypto_afsplit_encode(QCryptoHashAlgo hash, 895a95e0fcSDaniel P. Berrange size_t blocklen, 905a95e0fcSDaniel P. Berrange uint32_t stripes, 915a95e0fcSDaniel P. Berrange const uint8_t *in, 925a95e0fcSDaniel P. Berrange uint8_t *out, 935a95e0fcSDaniel P. Berrange Error **errp) 945a95e0fcSDaniel P. Berrange { 9557b9f113SDaniel P. Berrangé g_autofree uint8_t *block = g_new0(uint8_t, blocklen); 965a95e0fcSDaniel P. Berrange size_t i; 975a95e0fcSDaniel P. Berrange 985a95e0fcSDaniel P. Berrange for (i = 0; i < (stripes - 1); i++) { 995a95e0fcSDaniel P. Berrange if (qcrypto_random_bytes(out + (i * blocklen), blocklen, errp) < 0) { 10057b9f113SDaniel P. Berrangé return -1; 1015a95e0fcSDaniel P. Berrange } 1025a95e0fcSDaniel P. Berrange 1035a95e0fcSDaniel P. Berrange qcrypto_afsplit_xor(blocklen, 1045a95e0fcSDaniel P. Berrange out + (i * blocklen), 1055a95e0fcSDaniel P. Berrange block, 1065a95e0fcSDaniel P. Berrange block); 1075a95e0fcSDaniel P. Berrange if (qcrypto_afsplit_hash(hash, blocklen, block, 1085a95e0fcSDaniel P. Berrange errp) < 0) { 10957b9f113SDaniel P. Berrangé return -1; 1105a95e0fcSDaniel P. Berrange } 1115a95e0fcSDaniel P. Berrange } 1125a95e0fcSDaniel P. Berrange qcrypto_afsplit_xor(blocklen, 1135a95e0fcSDaniel P. Berrange in, 1145a95e0fcSDaniel P. Berrange block, 1155a95e0fcSDaniel P. Berrange out + (i * blocklen)); 11657b9f113SDaniel P. Berrangé return 0; 1175a95e0fcSDaniel P. Berrange } 1185a95e0fcSDaniel P. Berrange 1195a95e0fcSDaniel P. Berrange 120*ef834aa2SMarkus Armbruster int qcrypto_afsplit_decode(QCryptoHashAlgo hash, 1215a95e0fcSDaniel P. Berrange size_t blocklen, 1225a95e0fcSDaniel P. Berrange uint32_t stripes, 1235a95e0fcSDaniel P. Berrange const uint8_t *in, 1245a95e0fcSDaniel P. Berrange uint8_t *out, 1255a95e0fcSDaniel P. Berrange Error **errp) 1265a95e0fcSDaniel P. Berrange { 12757b9f113SDaniel P. Berrangé g_autofree uint8_t *block = g_new0(uint8_t, blocklen); 1285a95e0fcSDaniel P. Berrange size_t i; 1295a95e0fcSDaniel P. Berrange 1305a95e0fcSDaniel P. Berrange for (i = 0; i < (stripes - 1); i++) { 1315a95e0fcSDaniel P. Berrange qcrypto_afsplit_xor(blocklen, 1325a95e0fcSDaniel P. Berrange in + (i * blocklen), 1335a95e0fcSDaniel P. Berrange block, 1345a95e0fcSDaniel P. Berrange block); 1355a95e0fcSDaniel P. Berrange if (qcrypto_afsplit_hash(hash, blocklen, block, 1365a95e0fcSDaniel P. Berrange errp) < 0) { 13757b9f113SDaniel P. Berrangé return -1; 1385a95e0fcSDaniel P. Berrange } 1395a95e0fcSDaniel P. Berrange } 1405a95e0fcSDaniel P. Berrange 1415a95e0fcSDaniel P. Berrange qcrypto_afsplit_xor(blocklen, 1425a95e0fcSDaniel P. Berrange in + (i * blocklen), 1435a95e0fcSDaniel P. Berrange block, 1445a95e0fcSDaniel P. Berrange out); 14557b9f113SDaniel P. Berrangé return 0; 1465a95e0fcSDaniel P. Berrange } 147