cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

afsplit.c (4395B)


      1/*
      2 * QEMU Crypto anti forensic information splitter
      3 *
      4 * Copyright (c) 2015-2016 Red Hat, Inc.
      5 *
      6 * Derived from cryptsetup package lib/luks1/af.c
      7 *
      8 * Copyright (C) 2004, Clemens Fruhwirth <clemens@endorphin.org>
      9 * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
     10 *
     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.
     15 *
     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.
     20 *
     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/>.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "qemu/bswap.h"
     27#include "crypto/afsplit.h"
     28#include "crypto/random.h"
     29
     30
     31static void qcrypto_afsplit_xor(size_t blocklen,
     32                                const uint8_t *in1,
     33                                const uint8_t *in2,
     34                                uint8_t *out)
     35{
     36    size_t i;
     37    for (i = 0; i < blocklen; i++) {
     38        out[i] = in1[i] ^ in2[i];
     39    }
     40}
     41
     42
     43static int qcrypto_afsplit_hash(QCryptoHashAlgorithm hash,
     44                                size_t blocklen,
     45                                uint8_t *block,
     46                                Error **errp)
     47{
     48    size_t digestlen = qcrypto_hash_digest_len(hash);
     49
     50    size_t hashcount = blocklen / digestlen;
     51    size_t finallen = blocklen % digestlen;
     52    uint32_t i;
     53
     54    if (finallen) {
     55        hashcount++;
     56    } else {
     57        finallen = digestlen;
     58    }
     59
     60    for (i = 0; i < hashcount; i++) {
     61        g_autofree uint8_t *out = NULL;
     62        size_t outlen = 0;
     63        uint32_t iv = cpu_to_be32(i);
     64        struct iovec in[] = {
     65            { .iov_base = &iv,
     66              .iov_len = sizeof(iv) },
     67            { .iov_base = block + (i * digestlen),
     68              .iov_len = (i == (hashcount - 1)) ? finallen : digestlen },
     69        };
     70
     71        if (qcrypto_hash_bytesv(hash,
     72                                in,
     73                                G_N_ELEMENTS(in),
     74                                &out, &outlen,
     75                                errp) < 0) {
     76            return -1;
     77        }
     78
     79        assert(outlen == digestlen);
     80        memcpy(block + (i * digestlen), out,
     81               (i == (hashcount - 1)) ? finallen : digestlen);
     82    }
     83
     84    return 0;
     85}
     86
     87
     88int qcrypto_afsplit_encode(QCryptoHashAlgorithm hash,
     89                           size_t blocklen,
     90                           uint32_t stripes,
     91                           const uint8_t *in,
     92                           uint8_t *out,
     93                           Error **errp)
     94{
     95    g_autofree uint8_t *block = g_new0(uint8_t, blocklen);
     96    size_t i;
     97
     98    for (i = 0; i < (stripes - 1); i++) {
     99        if (qcrypto_random_bytes(out + (i * blocklen), blocklen, errp) < 0) {
    100            return -1;
    101        }
    102
    103        qcrypto_afsplit_xor(blocklen,
    104                            out + (i * blocklen),
    105                            block,
    106                            block);
    107        if (qcrypto_afsplit_hash(hash, blocklen, block,
    108                                 errp) < 0) {
    109            return -1;
    110        }
    111    }
    112    qcrypto_afsplit_xor(blocklen,
    113                        in,
    114                        block,
    115                        out + (i * blocklen));
    116    return 0;
    117}
    118
    119
    120int qcrypto_afsplit_decode(QCryptoHashAlgorithm hash,
    121                           size_t blocklen,
    122                           uint32_t stripes,
    123                           const uint8_t *in,
    124                           uint8_t *out,
    125                           Error **errp)
    126{
    127    g_autofree uint8_t *block = g_new0(uint8_t, blocklen);
    128    size_t i;
    129
    130    for (i = 0; i < (stripes - 1); i++) {
    131        qcrypto_afsplit_xor(blocklen,
    132                            in + (i * blocklen),
    133                            block,
    134                            block);
    135        if (qcrypto_afsplit_hash(hash, blocklen, block,
    136                                 errp) < 0) {
    137            return -1;
    138        }
    139    }
    140
    141    qcrypto_afsplit_xor(blocklen,
    142                        in + (i * blocklen),
    143                        block,
    144                        out);
    145    return 0;
    146}