xref: /qemu/tests/unit/test-crypto-afsplit.c (revision 422c16e7ecf8a2cd460e9b02cfb1955a235d36d7)
15a95e0fcSDaniel P. Berrange /*
25a95e0fcSDaniel P. Berrange  * QEMU Crypto anti-forensic splitter
35a95e0fcSDaniel P. Berrange  *
45a95e0fcSDaniel P. Berrange  * Copyright (c) 2015-2016 Red Hat, Inc.
55a95e0fcSDaniel P. Berrange  *
65a95e0fcSDaniel P. Berrange  * This library is free software; you can redistribute it and/or
75a95e0fcSDaniel P. Berrange  * modify it under the terms of the GNU Lesser General Public
85a95e0fcSDaniel P. Berrange  * License as published by the Free Software Foundation; either
9*422c16e7SChetan Pant  * version 2.1 of the License, or (at your option) any later version.
105a95e0fcSDaniel P. Berrange  *
115a95e0fcSDaniel P. Berrange  * This library is distributed in the hope that it will be useful,
125a95e0fcSDaniel P. Berrange  * but WITHOUT ANY WARRANTY; without even the implied warranty of
135a95e0fcSDaniel P. Berrange  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145a95e0fcSDaniel P. Berrange  * Lesser General Public License for more details.
155a95e0fcSDaniel P. Berrange  *
165a95e0fcSDaniel P. Berrange  * You should have received a copy of the GNU Lesser General Public
175a95e0fcSDaniel P. Berrange  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
185a95e0fcSDaniel P. Berrange  *
195a95e0fcSDaniel P. Berrange  */
205a95e0fcSDaniel P. Berrange 
215a95e0fcSDaniel P. Berrange #include "qemu/osdep.h"
22da34e65cSMarkus Armbruster #include "qapi/error.h"
235a95e0fcSDaniel P. Berrange #include "crypto/init.h"
245a95e0fcSDaniel P. Berrange #include "crypto/afsplit.h"
255a95e0fcSDaniel P. Berrange 
265a95e0fcSDaniel P. Berrange typedef struct QCryptoAFSplitTestData QCryptoAFSplitTestData;
275a95e0fcSDaniel P. Berrange struct QCryptoAFSplitTestData {
285a95e0fcSDaniel P. Berrange     const char *path;
295a95e0fcSDaniel P. Berrange     QCryptoHashAlgorithm hash;
305a95e0fcSDaniel P. Berrange     uint32_t stripes;
315a95e0fcSDaniel P. Berrange     size_t blocklen;
325a95e0fcSDaniel P. Berrange     const uint8_t *key;
335a95e0fcSDaniel P. Berrange     const uint8_t *splitkey;
345a95e0fcSDaniel P. Berrange };
355a95e0fcSDaniel P. Berrange 
365a95e0fcSDaniel P. Berrange static QCryptoAFSplitTestData test_data[] = {
375a95e0fcSDaniel P. Berrange     {
385a95e0fcSDaniel P. Berrange         .path = "/crypto/afsplit/sha256/5",
395a95e0fcSDaniel P. Berrange         .hash = QCRYPTO_HASH_ALG_SHA256,
405a95e0fcSDaniel P. Berrange         .stripes = 5,
415a95e0fcSDaniel P. Berrange         .blocklen = 32,
425a95e0fcSDaniel P. Berrange         .key = (const uint8_t *)
435a95e0fcSDaniel P. Berrange             "\x00\x01\x02\x03\x04\x05\x06\x07"
445a95e0fcSDaniel P. Berrange             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
455a95e0fcSDaniel P. Berrange             "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
465a95e0fcSDaniel P. Berrange             "\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
475a95e0fcSDaniel P. Berrange         .splitkey = (const uint8_t *)
485a95e0fcSDaniel P. Berrange             "\xfd\xd2\x73\xb1\x7d\x99\x93\x34"
495a95e0fcSDaniel P. Berrange             "\x70\xde\xfa\x07\xc5\xac\x58\xd2"
505a95e0fcSDaniel P. Berrange             "\x30\x67\x2f\x1a\x35\x43\x60\x7d"
515a95e0fcSDaniel P. Berrange             "\x77\x02\xdb\x62\x3c\xcb\x2c\x33"
525a95e0fcSDaniel P. Berrange             "\x48\x08\xb6\xf1\x7c\xa3\x20\xa0"
535a95e0fcSDaniel P. Berrange             "\xad\x2d\x4c\xf3\xcd\x18\x6f\x53"
545a95e0fcSDaniel P. Berrange             "\xf9\xe8\xe7\x59\x27\x3c\xa9\x54"
555a95e0fcSDaniel P. Berrange             "\x61\x87\xb3\xaf\xf6\xf7\x7e\x64"
565a95e0fcSDaniel P. Berrange             "\x86\xaa\x89\x7f\x1f\x9f\xdb\x86"
575a95e0fcSDaniel P. Berrange             "\xf4\xa2\x16\xff\xa3\x4f\x8c\xa1"
585a95e0fcSDaniel P. Berrange             "\x59\xc4\x23\x34\x28\xc4\x77\x71"
595a95e0fcSDaniel P. Berrange             "\x83\xd4\xcd\x8e\x89\x1b\xc7\xc5"
605a95e0fcSDaniel P. Berrange             "\xae\x4d\xa9\xcd\xc9\x72\x85\x70"
615a95e0fcSDaniel P. Berrange             "\x13\x68\x52\x83\xfc\xb8\x11\x72"
625a95e0fcSDaniel P. Berrange             "\xba\x3d\xc6\x4a\x28\xfa\xe2\x86"
635a95e0fcSDaniel P. Berrange             "\x7b\x27\xab\x58\xe1\xa4\xca\xf6"
645a95e0fcSDaniel P. Berrange             "\x9e\xbc\xfe\x0c\x92\x79\xb3\xec"
655a95e0fcSDaniel P. Berrange             "\x1c\x5f\x79\x3b\x0d\x1e\xaa\x1a"
665a95e0fcSDaniel P. Berrange             "\x77\x0f\x70\x19\x4b\xc8\x80\xee"
675a95e0fcSDaniel P. Berrange             "\x27\x7c\x6e\x4a\x91\x96\x5c\xf4"
685a95e0fcSDaniel P. Berrange     },
695a95e0fcSDaniel P. Berrange     {
705a95e0fcSDaniel P. Berrange         .path = "/crypto/afsplit/sha256/5000",
715a95e0fcSDaniel P. Berrange         .hash = QCRYPTO_HASH_ALG_SHA256,
725a95e0fcSDaniel P. Berrange         .stripes = 5000,
735a95e0fcSDaniel P. Berrange         .blocklen = 16,
745a95e0fcSDaniel P. Berrange         .key = (const uint8_t *)
755a95e0fcSDaniel P. Berrange             "\x00\x01\x02\x03\x04\x05\x06\x07"
765a95e0fcSDaniel P. Berrange             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
775a95e0fcSDaniel P. Berrange     },
785a95e0fcSDaniel P. Berrange     {
795a95e0fcSDaniel P. Berrange         .path = "/crypto/afsplit/sha1/1000",
805a95e0fcSDaniel P. Berrange         .hash = QCRYPTO_HASH_ALG_SHA1,
815a95e0fcSDaniel P. Berrange         .stripes = 1000,
825a95e0fcSDaniel P. Berrange         .blocklen = 32,
835a95e0fcSDaniel P. Berrange         .key = (const uint8_t *)
845a95e0fcSDaniel P. Berrange             "\x00\x01\x02\x03\x04\x05\x06\x07"
855a95e0fcSDaniel P. Berrange             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
865a95e0fcSDaniel P. Berrange             "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
875a95e0fcSDaniel P. Berrange             "\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
885a95e0fcSDaniel P. Berrange     },
895a95e0fcSDaniel P. Berrange     {
905a95e0fcSDaniel P. Berrange         .path = "/crypto/afsplit/sha256/big",
915a95e0fcSDaniel P. Berrange         .hash = QCRYPTO_HASH_ALG_SHA256,
925a95e0fcSDaniel P. Berrange         .stripes = 1000,
935a95e0fcSDaniel P. Berrange         .blocklen = 64,
945a95e0fcSDaniel P. Berrange         .key = (const uint8_t *)
955a95e0fcSDaniel P. Berrange             "\x00\x01\x02\x03\x04\x05\x06\x07"
965a95e0fcSDaniel P. Berrange             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
975a95e0fcSDaniel P. Berrange             "\x00\x01\x02\x03\x04\x05\x06\x07"
985a95e0fcSDaniel P. Berrange             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
995a95e0fcSDaniel P. Berrange             "\x00\x01\x02\x03\x04\x05\x06\x07"
1005a95e0fcSDaniel P. Berrange             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
1015a95e0fcSDaniel P. Berrange             "\x00\x01\x02\x03\x04\x05\x06\x07"
1025a95e0fcSDaniel P. Berrange             "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
1035a95e0fcSDaniel P. Berrange     },
1045a95e0fcSDaniel P. Berrange };
1055a95e0fcSDaniel P. Berrange 
1065a95e0fcSDaniel P. Berrange 
1075a95e0fcSDaniel P. Berrange static inline char hex(int i)
1085a95e0fcSDaniel P. Berrange {
1095a95e0fcSDaniel P. Berrange     if (i < 10) {
1105a95e0fcSDaniel P. Berrange         return '0' + i;
1115a95e0fcSDaniel P. Berrange     }
1125a95e0fcSDaniel P. Berrange     return 'a' + (i - 10);
1135a95e0fcSDaniel P. Berrange }
1145a95e0fcSDaniel P. Berrange 
1155a95e0fcSDaniel P. Berrange static char *hex_string(const uint8_t *bytes,
1165a95e0fcSDaniel P. Berrange                         size_t len)
1175a95e0fcSDaniel P. Berrange {
1185a95e0fcSDaniel P. Berrange     char *hexstr = g_new0(char, len * 2 + 1);
1195a95e0fcSDaniel P. Berrange     size_t i;
1205a95e0fcSDaniel P. Berrange 
1215a95e0fcSDaniel P. Berrange     for (i = 0; i < len; i++) {
1225a95e0fcSDaniel P. Berrange         hexstr[i * 2] = hex((bytes[i] >> 4) & 0xf);
1235a95e0fcSDaniel P. Berrange         hexstr[i * 2 + 1] = hex(bytes[i] & 0xf);
1245a95e0fcSDaniel P. Berrange     }
1255a95e0fcSDaniel P. Berrange     hexstr[len * 2] = '\0';
1265a95e0fcSDaniel P. Berrange 
1275a95e0fcSDaniel P. Berrange     return hexstr;
1285a95e0fcSDaniel P. Berrange }
1295a95e0fcSDaniel P. Berrange 
1305a95e0fcSDaniel P. Berrange static void test_afsplit(const void *opaque)
1315a95e0fcSDaniel P. Berrange {
1325a95e0fcSDaniel P. Berrange     const QCryptoAFSplitTestData *data = opaque;
1335a95e0fcSDaniel P. Berrange     size_t splitlen = data->blocklen * data->stripes;
1345a95e0fcSDaniel P. Berrange     uint8_t *splitkey = g_new0(uint8_t, splitlen);
1355a95e0fcSDaniel P. Berrange     uint8_t *key = g_new0(uint8_t, data->blocklen);
1365a95e0fcSDaniel P. Berrange     gchar *expect, *actual;
1375a95e0fcSDaniel P. Berrange 
1385a95e0fcSDaniel P. Berrange     /* First time we round-trip the key */
1395a95e0fcSDaniel P. Berrange     qcrypto_afsplit_encode(data->hash,
1405a95e0fcSDaniel P. Berrange                            data->blocklen, data->stripes,
1415a95e0fcSDaniel P. Berrange                            data->key, splitkey,
1425a95e0fcSDaniel P. Berrange                            &error_abort);
1435a95e0fcSDaniel P. Berrange 
1445a95e0fcSDaniel P. Berrange     qcrypto_afsplit_decode(data->hash,
1455a95e0fcSDaniel P. Berrange                            data->blocklen, data->stripes,
1465a95e0fcSDaniel P. Berrange                            splitkey, key,
1475a95e0fcSDaniel P. Berrange                            &error_abort);
1485a95e0fcSDaniel P. Berrange 
1495a95e0fcSDaniel P. Berrange     expect = hex_string(data->key, data->blocklen);
1505a95e0fcSDaniel P. Berrange     actual = hex_string(key, data->blocklen);
1515a95e0fcSDaniel P. Berrange 
1525a95e0fcSDaniel P. Berrange     g_assert_cmpstr(actual, ==, expect);
1535a95e0fcSDaniel P. Berrange 
1545a95e0fcSDaniel P. Berrange     g_free(actual);
1555a95e0fcSDaniel P. Berrange     g_free(expect);
1565a95e0fcSDaniel P. Berrange 
1575a95e0fcSDaniel P. Berrange     /* Second time we merely try decoding a previous split */
1585a95e0fcSDaniel P. Berrange     if (data->splitkey) {
1595a95e0fcSDaniel P. Berrange         memset(key, 0, data->blocklen);
1605a95e0fcSDaniel P. Berrange 
1615a95e0fcSDaniel P. Berrange         qcrypto_afsplit_decode(data->hash,
1625a95e0fcSDaniel P. Berrange                                data->blocklen, data->stripes,
1635a95e0fcSDaniel P. Berrange                                data->splitkey, key,
1645a95e0fcSDaniel P. Berrange                                &error_abort);
1655a95e0fcSDaniel P. Berrange 
1665a95e0fcSDaniel P. Berrange         expect = hex_string(data->key, data->blocklen);
1675a95e0fcSDaniel P. Berrange         actual = hex_string(key, data->blocklen);
1685a95e0fcSDaniel P. Berrange 
1695a95e0fcSDaniel P. Berrange         g_assert_cmpstr(actual, ==, expect);
1705a95e0fcSDaniel P. Berrange 
1715a95e0fcSDaniel P. Berrange         g_free(actual);
1725a95e0fcSDaniel P. Berrange         g_free(expect);
1735a95e0fcSDaniel P. Berrange     }
1745a95e0fcSDaniel P. Berrange 
1755a95e0fcSDaniel P. Berrange     g_free(key);
1765a95e0fcSDaniel P. Berrange     g_free(splitkey);
1775a95e0fcSDaniel P. Berrange }
1785a95e0fcSDaniel P. Berrange 
1795a95e0fcSDaniel P. Berrange int main(int argc, char **argv)
1805a95e0fcSDaniel P. Berrange {
1815a95e0fcSDaniel P. Berrange     size_t i;
1825a95e0fcSDaniel P. Berrange 
1835a95e0fcSDaniel P. Berrange     g_test_init(&argc, &argv, NULL);
1845a95e0fcSDaniel P. Berrange 
1855a95e0fcSDaniel P. Berrange     g_assert(qcrypto_init(NULL) == 0);
1865a95e0fcSDaniel P. Berrange 
1875a95e0fcSDaniel P. Berrange     for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
1885a95e0fcSDaniel P. Berrange         if (!qcrypto_hash_supports(test_data[i].hash)) {
1895a95e0fcSDaniel P. Berrange             continue;
1905a95e0fcSDaniel P. Berrange         }
1915a95e0fcSDaniel P. Berrange         g_test_add_data_func(test_data[i].path, &test_data[i], test_afsplit);
1925a95e0fcSDaniel P. Berrange     }
1935a95e0fcSDaniel P. Berrange     return g_test_run();
1945a95e0fcSDaniel P. Berrange }
195