2 * QEMU Crypto anti forensic information splitter
4 * Copyright (c) 2015-2016 Red Hat, Inc.
6 * Derived from cryptsetup package lib/luks1/af.c
8 * Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
9 * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 #include "qemu/osdep.h"
26 #include "qemu/bswap.h"
27 #include "crypto/afsplit.h"
28 #include "crypto/random.h"
31 static void qcrypto_afsplit_xor(size_t blocklen
,
37 for (i
= 0; i
< blocklen
; i
++) {
38 out
[i
] = in1
[i
] ^ in2
[i
];
43 static int qcrypto_afsplit_hash(QCryptoHashAlgorithm hash
,
48 size_t digestlen
= qcrypto_hash_digest_len(hash
);
50 size_t hashcount
= blocklen
/ digestlen
;
51 size_t finallen
= blocklen
% digestlen
;
60 for (i
= 0; i
< hashcount
; i
++) {
61 g_autofree
uint8_t *out
= NULL
;
63 uint32_t iv
= cpu_to_be32(i
);
66 .iov_len
= sizeof(iv
) },
67 { .iov_base
= block
+ (i
* digestlen
),
68 .iov_len
= (i
== (hashcount
- 1)) ? finallen
: digestlen
},
71 if (qcrypto_hash_bytesv(hash
,
79 assert(outlen
== digestlen
);
80 memcpy(block
+ (i
* digestlen
), out
,
81 (i
== (hashcount
- 1)) ? finallen
: digestlen
);
88 int qcrypto_afsplit_encode(QCryptoHashAlgorithm hash
,
95 g_autofree
uint8_t *block
= g_new0(uint8_t, blocklen
);
98 for (i
= 0; i
< (stripes
- 1); i
++) {
99 if (qcrypto_random_bytes(out
+ (i
* blocklen
), blocklen
, errp
) < 0) {
103 qcrypto_afsplit_xor(blocklen
,
104 out
+ (i
* blocklen
),
107 if (qcrypto_afsplit_hash(hash
, blocklen
, block
,
112 qcrypto_afsplit_xor(blocklen
,
115 out
+ (i
* blocklen
));
120 int qcrypto_afsplit_decode(QCryptoHashAlgorithm hash
,
127 g_autofree
uint8_t *block
= g_new0(uint8_t, blocklen
);
130 for (i
= 0; i
< (stripes
- 1); i
++) {
131 qcrypto_afsplit_xor(blocklen
,
135 if (qcrypto_afsplit_hash(hash
, blocklen
, block
,
141 qcrypto_afsplit_xor(blocklen
,