qemu/crypto/xts.c
<<
>>
Prefs
   1/*
   2 * QEMU Crypto XTS cipher mode
   3 *
   4 * Copyright (c) 2015-2016 Red Hat, Inc.
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 *
  19 * This code is originally derived from public domain / WTFPL code in
  20 * LibTomCrypt crytographic library http://libtom.org. The XTS code
  21 * was donated by Elliptic Semiconductor Inc (www.ellipticsemi.com)
  22 * to the LibTom Projects
  23 *
  24 */
  25
  26#include "qemu/osdep.h"
  27#include "crypto/xts.h"
  28
  29static void xts_mult_x(uint8_t *I)
  30{
  31    int x;
  32    uint8_t t, tt;
  33
  34    for (x = t = 0; x < 16; x++) {
  35        tt = I[x] >> 7;
  36        I[x] = ((I[x] << 1) | t) & 0xFF;
  37        t = tt;
  38    }
  39    if (tt) {
  40        I[0] ^= 0x87;
  41    }
  42}
  43
  44
  45/**
  46 * xts_tweak_uncrypt:
  47 * @param ctxt: the cipher context
  48 * @param func: the cipher function
  49 * @src: buffer providing the cipher text of XTS_BLOCK_SIZE bytes
  50 * @dst: buffer to output the plain text of XTS_BLOCK_SIZE bytes
  51 * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes
  52 *
  53 * Decrypt data with a tweak
  54 */
  55static void xts_tweak_decrypt(const void *ctx,
  56                              xts_cipher_func *func,
  57                              const uint8_t *src,
  58                              uint8_t *dst,
  59                              uint8_t *iv)
  60{
  61    unsigned long x;
  62
  63    /* tweak encrypt block i */
  64    for (x = 0; x < XTS_BLOCK_SIZE; x++) {
  65        dst[x] = src[x] ^ iv[x];
  66    }
  67
  68    func(ctx, XTS_BLOCK_SIZE, dst, dst);
  69
  70    for (x = 0; x < XTS_BLOCK_SIZE; x++) {
  71        dst[x] = dst[x] ^ iv[x];
  72    }
  73
  74    /* LFSR the tweak */
  75    xts_mult_x(iv);
  76}
  77
  78
  79void xts_decrypt(const void *datactx,
  80                 const void *tweakctx,
  81                 xts_cipher_func *encfunc,
  82                 xts_cipher_func *decfunc,
  83                 uint8_t *iv,
  84                 size_t length,
  85                 uint8_t *dst,
  86                 const uint8_t *src)
  87{
  88    uint8_t PP[XTS_BLOCK_SIZE], CC[XTS_BLOCK_SIZE], T[XTS_BLOCK_SIZE];
  89    unsigned long i, m, mo, lim;
  90
  91    /* get number of blocks */
  92    m = length >> 4;
  93    mo = length & 15;
  94
  95    /* must have at least one full block */
  96    g_assert(m != 0);
  97
  98    if (mo == 0) {
  99        lim = m;
 100    } else {
 101        lim = m - 1;
 102    }
 103
 104    /* encrypt the iv */
 105    encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv);
 106
 107    for (i = 0; i < lim; i++) {
 108        xts_tweak_decrypt(datactx, decfunc, src, dst, T);
 109
 110        src += XTS_BLOCK_SIZE;
 111        dst += XTS_BLOCK_SIZE;
 112    }
 113
 114    /* if length is not a multiple of XTS_BLOCK_SIZE then */
 115    if (mo > 0) {
 116        memcpy(CC, T, XTS_BLOCK_SIZE);
 117        xts_mult_x(CC);
 118
 119        /* PP = tweak decrypt block m-1 */
 120        xts_tweak_decrypt(datactx, decfunc, src, PP, CC);
 121
 122        /* Pm = first length % XTS_BLOCK_SIZE bytes of PP */
 123        for (i = 0; i < mo; i++) {
 124            CC[i] = src[XTS_BLOCK_SIZE + i];
 125            dst[XTS_BLOCK_SIZE + i] = PP[i];
 126        }
 127        for (; i < XTS_BLOCK_SIZE; i++) {
 128            CC[i] = PP[i];
 129        }
 130
 131        /* Pm-1 = Tweak uncrypt CC */
 132        xts_tweak_decrypt(datactx, decfunc, CC, dst, T);
 133    }
 134
 135    /* Decrypt the iv back */
 136    decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T);
 137}
 138
 139
 140/**
 141 * xts_tweak_crypt:
 142 * @param ctxt: the cipher context
 143 * @param func: the cipher function
 144 * @src: buffer providing the plain text of XTS_BLOCK_SIZE bytes
 145 * @dst: buffer to output the cipher text of XTS_BLOCK_SIZE bytes
 146 * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes
 147 *
 148 * Encrypt data with a tweak
 149 */
 150static void xts_tweak_encrypt(const void *ctx,
 151                              xts_cipher_func *func,
 152                              const uint8_t *src,
 153                              uint8_t *dst,
 154                              uint8_t *iv)
 155{
 156    unsigned long x;
 157
 158    /* tweak encrypt block i */
 159    for (x = 0; x < XTS_BLOCK_SIZE; x++) {
 160        dst[x] = src[x] ^ iv[x];
 161    }
 162
 163    func(ctx, XTS_BLOCK_SIZE, dst, dst);
 164
 165    for (x = 0; x < XTS_BLOCK_SIZE; x++) {
 166        dst[x] = dst[x] ^ iv[x];
 167    }
 168
 169    /* LFSR the tweak */
 170    xts_mult_x(iv);
 171}
 172
 173
 174void xts_encrypt(const void *datactx,
 175                 const void *tweakctx,
 176                 xts_cipher_func *encfunc,
 177                 xts_cipher_func *decfunc,
 178                 uint8_t *iv,
 179                 size_t length,
 180                 uint8_t *dst,
 181                 const uint8_t *src)
 182{
 183    uint8_t PP[XTS_BLOCK_SIZE], CC[XTS_BLOCK_SIZE], T[XTS_BLOCK_SIZE];
 184    unsigned long i, m, mo, lim;
 185
 186    /* get number of blocks */
 187    m = length >> 4;
 188    mo = length & 15;
 189
 190    /* must have at least one full block */
 191    g_assert(m != 0);
 192
 193    if (mo == 0) {
 194        lim = m;
 195    } else {
 196        lim = m - 1;
 197    }
 198
 199    /* encrypt the iv */
 200    encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv);
 201
 202    for (i = 0; i < lim; i++) {
 203        xts_tweak_encrypt(datactx, encfunc, src, dst, T);
 204
 205        dst += XTS_BLOCK_SIZE;
 206        src += XTS_BLOCK_SIZE;
 207    }
 208
 209    /* if length is not a multiple of XTS_BLOCK_SIZE then */
 210    if (mo > 0) {
 211        /* CC = tweak encrypt block m-1 */
 212        xts_tweak_encrypt(datactx, encfunc, src, CC, T);
 213
 214        /* Cm = first length % XTS_BLOCK_SIZE bytes of CC */
 215        for (i = 0; i < mo; i++) {
 216            PP[i] = src[XTS_BLOCK_SIZE + i];
 217            dst[XTS_BLOCK_SIZE + i] = CC[i];
 218        }
 219
 220        for (; i < XTS_BLOCK_SIZE; i++) {
 221            PP[i] = CC[i];
 222        }
 223
 224        /* Cm-1 = Tweak encrypt PP */
 225        xts_tweak_encrypt(datactx, encfunc, PP, dst, T);
 226    }
 227
 228    /* Decrypt the iv back */
 229    decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T);
 230}
 231