1da668aa1SThomas Huth /*
2da668aa1SThomas Huth * QEMU Crypto anti-forensic splitter
3da668aa1SThomas Huth *
4da668aa1SThomas Huth * Copyright (c) 2015-2016 Red Hat, Inc.
5da668aa1SThomas Huth *
6da668aa1SThomas Huth * This library is free software; you can redistribute it and/or
7da668aa1SThomas Huth * modify it under the terms of the GNU Lesser General Public
8da668aa1SThomas Huth * License as published by the Free Software Foundation; either
9da668aa1SThomas Huth * version 2.1 of the License, or (at your option) any later version.
10da668aa1SThomas Huth *
11da668aa1SThomas Huth * This library is distributed in the hope that it will be useful,
12da668aa1SThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
13da668aa1SThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14da668aa1SThomas Huth * Lesser General Public License for more details.
15da668aa1SThomas Huth *
16da668aa1SThomas Huth * You should have received a copy of the GNU Lesser General Public
17da668aa1SThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18da668aa1SThomas Huth *
19da668aa1SThomas Huth */
20da668aa1SThomas Huth
21da668aa1SThomas Huth #include "qemu/osdep.h"
22da668aa1SThomas Huth #include "qapi/error.h"
23da668aa1SThomas Huth #include "crypto/init.h"
24da668aa1SThomas Huth #include "crypto/afsplit.h"
25da668aa1SThomas Huth
26da668aa1SThomas Huth typedef struct QCryptoAFSplitTestData QCryptoAFSplitTestData;
27da668aa1SThomas Huth struct QCryptoAFSplitTestData {
28da668aa1SThomas Huth const char *path;
29*ef834aa2SMarkus Armbruster QCryptoHashAlgo hash;
30da668aa1SThomas Huth uint32_t stripes;
31da668aa1SThomas Huth size_t blocklen;
32da668aa1SThomas Huth const uint8_t *key;
33da668aa1SThomas Huth const uint8_t *splitkey;
34da668aa1SThomas Huth };
35da668aa1SThomas Huth
36da668aa1SThomas Huth static QCryptoAFSplitTestData test_data[] = {
37da668aa1SThomas Huth {
38da668aa1SThomas Huth .path = "/crypto/afsplit/sha256/5",
39*ef834aa2SMarkus Armbruster .hash = QCRYPTO_HASH_ALGO_SHA256,
40da668aa1SThomas Huth .stripes = 5,
41da668aa1SThomas Huth .blocklen = 32,
42da668aa1SThomas Huth .key = (const uint8_t *)
43da668aa1SThomas Huth "\x00\x01\x02\x03\x04\x05\x06\x07"
44da668aa1SThomas Huth "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
45da668aa1SThomas Huth "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
46da668aa1SThomas Huth "\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
47da668aa1SThomas Huth .splitkey = (const uint8_t *)
48da668aa1SThomas Huth "\xfd\xd2\x73\xb1\x7d\x99\x93\x34"
49da668aa1SThomas Huth "\x70\xde\xfa\x07\xc5\xac\x58\xd2"
50da668aa1SThomas Huth "\x30\x67\x2f\x1a\x35\x43\x60\x7d"
51da668aa1SThomas Huth "\x77\x02\xdb\x62\x3c\xcb\x2c\x33"
52da668aa1SThomas Huth "\x48\x08\xb6\xf1\x7c\xa3\x20\xa0"
53da668aa1SThomas Huth "\xad\x2d\x4c\xf3\xcd\x18\x6f\x53"
54da668aa1SThomas Huth "\xf9\xe8\xe7\x59\x27\x3c\xa9\x54"
55da668aa1SThomas Huth "\x61\x87\xb3\xaf\xf6\xf7\x7e\x64"
56da668aa1SThomas Huth "\x86\xaa\x89\x7f\x1f\x9f\xdb\x86"
57da668aa1SThomas Huth "\xf4\xa2\x16\xff\xa3\x4f\x8c\xa1"
58da668aa1SThomas Huth "\x59\xc4\x23\x34\x28\xc4\x77\x71"
59da668aa1SThomas Huth "\x83\xd4\xcd\x8e\x89\x1b\xc7\xc5"
60da668aa1SThomas Huth "\xae\x4d\xa9\xcd\xc9\x72\x85\x70"
61da668aa1SThomas Huth "\x13\x68\x52\x83\xfc\xb8\x11\x72"
62da668aa1SThomas Huth "\xba\x3d\xc6\x4a\x28\xfa\xe2\x86"
63da668aa1SThomas Huth "\x7b\x27\xab\x58\xe1\xa4\xca\xf6"
64da668aa1SThomas Huth "\x9e\xbc\xfe\x0c\x92\x79\xb3\xec"
65da668aa1SThomas Huth "\x1c\x5f\x79\x3b\x0d\x1e\xaa\x1a"
66da668aa1SThomas Huth "\x77\x0f\x70\x19\x4b\xc8\x80\xee"
67da668aa1SThomas Huth "\x27\x7c\x6e\x4a\x91\x96\x5c\xf4"
68da668aa1SThomas Huth },
69da668aa1SThomas Huth {
70da668aa1SThomas Huth .path = "/crypto/afsplit/sha256/5000",
71*ef834aa2SMarkus Armbruster .hash = QCRYPTO_HASH_ALGO_SHA256,
72da668aa1SThomas Huth .stripes = 5000,
73da668aa1SThomas Huth .blocklen = 16,
74da668aa1SThomas Huth .key = (const uint8_t *)
75da668aa1SThomas Huth "\x00\x01\x02\x03\x04\x05\x06\x07"
76da668aa1SThomas Huth "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
77da668aa1SThomas Huth },
78da668aa1SThomas Huth {
79da668aa1SThomas Huth .path = "/crypto/afsplit/sha1/1000",
80*ef834aa2SMarkus Armbruster .hash = QCRYPTO_HASH_ALGO_SHA1,
81da668aa1SThomas Huth .stripes = 1000,
82da668aa1SThomas Huth .blocklen = 32,
83da668aa1SThomas Huth .key = (const uint8_t *)
84da668aa1SThomas Huth "\x00\x01\x02\x03\x04\x05\x06\x07"
85da668aa1SThomas Huth "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
86da668aa1SThomas Huth "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
87da668aa1SThomas Huth "\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
88da668aa1SThomas Huth },
89da668aa1SThomas Huth {
90da668aa1SThomas Huth .path = "/crypto/afsplit/sha256/big",
91*ef834aa2SMarkus Armbruster .hash = QCRYPTO_HASH_ALGO_SHA256,
92da668aa1SThomas Huth .stripes = 1000,
93da668aa1SThomas Huth .blocklen = 64,
94da668aa1SThomas Huth .key = (const uint8_t *)
95da668aa1SThomas Huth "\x00\x01\x02\x03\x04\x05\x06\x07"
96da668aa1SThomas Huth "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
97da668aa1SThomas Huth "\x00\x01\x02\x03\x04\x05\x06\x07"
98da668aa1SThomas Huth "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
99da668aa1SThomas Huth "\x00\x01\x02\x03\x04\x05\x06\x07"
100da668aa1SThomas Huth "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
101da668aa1SThomas Huth "\x00\x01\x02\x03\x04\x05\x06\x07"
102da668aa1SThomas Huth "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
103da668aa1SThomas Huth },
104da668aa1SThomas Huth };
105da668aa1SThomas Huth
106da668aa1SThomas Huth
hex(int i)107da668aa1SThomas Huth static inline char hex(int i)
108da668aa1SThomas Huth {
109da668aa1SThomas Huth if (i < 10) {
110da668aa1SThomas Huth return '0' + i;
111da668aa1SThomas Huth }
112da668aa1SThomas Huth return 'a' + (i - 10);
113da668aa1SThomas Huth }
114da668aa1SThomas Huth
hex_string(const uint8_t * bytes,size_t len)115da668aa1SThomas Huth static char *hex_string(const uint8_t *bytes,
116da668aa1SThomas Huth size_t len)
117da668aa1SThomas Huth {
118da668aa1SThomas Huth char *hexstr = g_new0(char, len * 2 + 1);
119da668aa1SThomas Huth size_t i;
120da668aa1SThomas Huth
121da668aa1SThomas Huth for (i = 0; i < len; i++) {
122da668aa1SThomas Huth hexstr[i * 2] = hex((bytes[i] >> 4) & 0xf);
123da668aa1SThomas Huth hexstr[i * 2 + 1] = hex(bytes[i] & 0xf);
124da668aa1SThomas Huth }
125da668aa1SThomas Huth hexstr[len * 2] = '\0';
126da668aa1SThomas Huth
127da668aa1SThomas Huth return hexstr;
128da668aa1SThomas Huth }
129da668aa1SThomas Huth
test_afsplit(const void * opaque)130da668aa1SThomas Huth static void test_afsplit(const void *opaque)
131da668aa1SThomas Huth {
132da668aa1SThomas Huth const QCryptoAFSplitTestData *data = opaque;
133da668aa1SThomas Huth size_t splitlen = data->blocklen * data->stripes;
134da668aa1SThomas Huth uint8_t *splitkey = g_new0(uint8_t, splitlen);
135da668aa1SThomas Huth uint8_t *key = g_new0(uint8_t, data->blocklen);
136da668aa1SThomas Huth gchar *expect, *actual;
137da668aa1SThomas Huth
138da668aa1SThomas Huth /* First time we round-trip the key */
139da668aa1SThomas Huth qcrypto_afsplit_encode(data->hash,
140da668aa1SThomas Huth data->blocklen, data->stripes,
141da668aa1SThomas Huth data->key, splitkey,
142da668aa1SThomas Huth &error_abort);
143da668aa1SThomas Huth
144da668aa1SThomas Huth qcrypto_afsplit_decode(data->hash,
145da668aa1SThomas Huth data->blocklen, data->stripes,
146da668aa1SThomas Huth splitkey, key,
147da668aa1SThomas Huth &error_abort);
148da668aa1SThomas Huth
149da668aa1SThomas Huth expect = hex_string(data->key, data->blocklen);
150da668aa1SThomas Huth actual = hex_string(key, data->blocklen);
151da668aa1SThomas Huth
152da668aa1SThomas Huth g_assert_cmpstr(actual, ==, expect);
153da668aa1SThomas Huth
154da668aa1SThomas Huth g_free(actual);
155da668aa1SThomas Huth g_free(expect);
156da668aa1SThomas Huth
157da668aa1SThomas Huth /* Second time we merely try decoding a previous split */
158da668aa1SThomas Huth if (data->splitkey) {
159da668aa1SThomas Huth memset(key, 0, data->blocklen);
160da668aa1SThomas Huth
161da668aa1SThomas Huth qcrypto_afsplit_decode(data->hash,
162da668aa1SThomas Huth data->blocklen, data->stripes,
163da668aa1SThomas Huth data->splitkey, key,
164da668aa1SThomas Huth &error_abort);
165da668aa1SThomas Huth
166da668aa1SThomas Huth expect = hex_string(data->key, data->blocklen);
167da668aa1SThomas Huth actual = hex_string(key, data->blocklen);
168da668aa1SThomas Huth
169da668aa1SThomas Huth g_assert_cmpstr(actual, ==, expect);
170da668aa1SThomas Huth
171da668aa1SThomas Huth g_free(actual);
172da668aa1SThomas Huth g_free(expect);
173da668aa1SThomas Huth }
174da668aa1SThomas Huth
175da668aa1SThomas Huth g_free(key);
176da668aa1SThomas Huth g_free(splitkey);
177da668aa1SThomas Huth }
178da668aa1SThomas Huth
main(int argc,char ** argv)179da668aa1SThomas Huth int main(int argc, char **argv)
180da668aa1SThomas Huth {
181da668aa1SThomas Huth size_t i;
182da668aa1SThomas Huth
183da668aa1SThomas Huth g_test_init(&argc, &argv, NULL);
184da668aa1SThomas Huth
185da668aa1SThomas Huth g_assert(qcrypto_init(NULL) == 0);
186da668aa1SThomas Huth
187da668aa1SThomas Huth for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
188da668aa1SThomas Huth if (!qcrypto_hash_supports(test_data[i].hash)) {
189da668aa1SThomas Huth continue;
190da668aa1SThomas Huth }
191da668aa1SThomas Huth g_test_add_data_func(test_data[i].path, &test_data[i], test_afsplit);
192da668aa1SThomas Huth }
193da668aa1SThomas Huth return g_test_run();
194da668aa1SThomas Huth }
195