1*cb730894SDaniel P. Berrange /* 2*cb730894SDaniel P. Berrange * QEMU Crypto block IV generator - essiv 3*cb730894SDaniel P. Berrange * 4*cb730894SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 5*cb730894SDaniel P. Berrange * 6*cb730894SDaniel P. Berrange * This library is free software; you can redistribute it and/or 7*cb730894SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 8*cb730894SDaniel P. Berrange * License as published by the Free Software Foundation; either 9*cb730894SDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 10*cb730894SDaniel P. Berrange * 11*cb730894SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 12*cb730894SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*cb730894SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*cb730894SDaniel P. Berrange * Lesser General Public License for more details. 15*cb730894SDaniel P. Berrange * 16*cb730894SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 17*cb730894SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18*cb730894SDaniel P. Berrange * 19*cb730894SDaniel P. Berrange */ 20*cb730894SDaniel P. Berrange 21*cb730894SDaniel P. Berrange #include "qemu/osdep.h" 22*cb730894SDaniel P. Berrange #include "crypto/ivgen-essiv.h" 23*cb730894SDaniel P. Berrange 24*cb730894SDaniel P. Berrange typedef struct QCryptoIVGenESSIV QCryptoIVGenESSIV; 25*cb730894SDaniel P. Berrange struct QCryptoIVGenESSIV { 26*cb730894SDaniel P. Berrange QCryptoCipher *cipher; 27*cb730894SDaniel P. Berrange }; 28*cb730894SDaniel P. Berrange 29*cb730894SDaniel P. Berrange static int qcrypto_ivgen_essiv_init(QCryptoIVGen *ivgen, 30*cb730894SDaniel P. Berrange const uint8_t *key, size_t nkey, 31*cb730894SDaniel P. Berrange Error **errp) 32*cb730894SDaniel P. Berrange { 33*cb730894SDaniel P. Berrange uint8_t *salt; 34*cb730894SDaniel P. Berrange size_t nhash; 35*cb730894SDaniel P. Berrange size_t nsalt; 36*cb730894SDaniel P. Berrange QCryptoIVGenESSIV *essiv = g_new0(QCryptoIVGenESSIV, 1); 37*cb730894SDaniel P. Berrange 38*cb730894SDaniel P. Berrange /* Not necessarily the same as nkey */ 39*cb730894SDaniel P. Berrange nsalt = qcrypto_cipher_get_key_len(ivgen->cipher); 40*cb730894SDaniel P. Berrange 41*cb730894SDaniel P. Berrange nhash = qcrypto_hash_digest_len(ivgen->hash); 42*cb730894SDaniel P. Berrange /* Salt must be larger of hash size or key size */ 43*cb730894SDaniel P. Berrange salt = g_new0(uint8_t, MAX(nhash, nsalt)); 44*cb730894SDaniel P. Berrange 45*cb730894SDaniel P. Berrange if (qcrypto_hash_bytes(ivgen->hash, (const gchar *)key, nkey, 46*cb730894SDaniel P. Berrange &salt, &nhash, 47*cb730894SDaniel P. Berrange errp) < 0) { 48*cb730894SDaniel P. Berrange g_free(essiv); 49*cb730894SDaniel P. Berrange return -1; 50*cb730894SDaniel P. Berrange } 51*cb730894SDaniel P. Berrange 52*cb730894SDaniel P. Berrange /* Now potentially truncate salt to match cipher key len */ 53*cb730894SDaniel P. Berrange essiv->cipher = qcrypto_cipher_new(ivgen->cipher, 54*cb730894SDaniel P. Berrange QCRYPTO_CIPHER_MODE_ECB, 55*cb730894SDaniel P. Berrange salt, MIN(nhash, nsalt), 56*cb730894SDaniel P. Berrange errp); 57*cb730894SDaniel P. Berrange if (!essiv->cipher) { 58*cb730894SDaniel P. Berrange g_free(essiv); 59*cb730894SDaniel P. Berrange g_free(salt); 60*cb730894SDaniel P. Berrange return -1; 61*cb730894SDaniel P. Berrange } 62*cb730894SDaniel P. Berrange 63*cb730894SDaniel P. Berrange g_free(salt); 64*cb730894SDaniel P. Berrange ivgen->private = essiv; 65*cb730894SDaniel P. Berrange 66*cb730894SDaniel P. Berrange return 0; 67*cb730894SDaniel P. Berrange } 68*cb730894SDaniel P. Berrange 69*cb730894SDaniel P. Berrange static int qcrypto_ivgen_essiv_calculate(QCryptoIVGen *ivgen, 70*cb730894SDaniel P. Berrange uint64_t sector, 71*cb730894SDaniel P. Berrange uint8_t *iv, size_t niv, 72*cb730894SDaniel P. Berrange Error **errp) 73*cb730894SDaniel P. Berrange { 74*cb730894SDaniel P. Berrange QCryptoIVGenESSIV *essiv = ivgen->private; 75*cb730894SDaniel P. Berrange size_t ndata = qcrypto_cipher_get_block_len(ivgen->cipher); 76*cb730894SDaniel P. Berrange uint8_t *data = g_new(uint8_t, ndata); 77*cb730894SDaniel P. Berrange 78*cb730894SDaniel P. Berrange sector = cpu_to_le64(sector); 79*cb730894SDaniel P. Berrange memcpy(data, (uint8_t *)§or, ndata); 80*cb730894SDaniel P. Berrange if (sizeof(sector) < ndata) { 81*cb730894SDaniel P. Berrange memset(data + sizeof(sector), 0, ndata - sizeof(sector)); 82*cb730894SDaniel P. Berrange } 83*cb730894SDaniel P. Berrange 84*cb730894SDaniel P. Berrange if (qcrypto_cipher_encrypt(essiv->cipher, 85*cb730894SDaniel P. Berrange data, 86*cb730894SDaniel P. Berrange data, 87*cb730894SDaniel P. Berrange ndata, 88*cb730894SDaniel P. Berrange errp) < 0) { 89*cb730894SDaniel P. Berrange g_free(data); 90*cb730894SDaniel P. Berrange return -1; 91*cb730894SDaniel P. Berrange } 92*cb730894SDaniel P. Berrange 93*cb730894SDaniel P. Berrange if (ndata > niv) { 94*cb730894SDaniel P. Berrange ndata = niv; 95*cb730894SDaniel P. Berrange } 96*cb730894SDaniel P. Berrange memcpy(iv, data, ndata); 97*cb730894SDaniel P. Berrange if (ndata < niv) { 98*cb730894SDaniel P. Berrange memset(iv + ndata, 0, niv - ndata); 99*cb730894SDaniel P. Berrange } 100*cb730894SDaniel P. Berrange g_free(data); 101*cb730894SDaniel P. Berrange return 0; 102*cb730894SDaniel P. Berrange } 103*cb730894SDaniel P. Berrange 104*cb730894SDaniel P. Berrange static void qcrypto_ivgen_essiv_cleanup(QCryptoIVGen *ivgen) 105*cb730894SDaniel P. Berrange { 106*cb730894SDaniel P. Berrange QCryptoIVGenESSIV *essiv = ivgen->private; 107*cb730894SDaniel P. Berrange 108*cb730894SDaniel P. Berrange qcrypto_cipher_free(essiv->cipher); 109*cb730894SDaniel P. Berrange g_free(essiv); 110*cb730894SDaniel P. Berrange } 111*cb730894SDaniel P. Berrange 112*cb730894SDaniel P. Berrange 113*cb730894SDaniel P. Berrange struct QCryptoIVGenDriver qcrypto_ivgen_essiv = { 114*cb730894SDaniel P. Berrange .init = qcrypto_ivgen_essiv_init, 115*cb730894SDaniel P. Berrange .calculate = qcrypto_ivgen_essiv_calculate, 116*cb730894SDaniel P. Berrange .cleanup = qcrypto_ivgen_essiv_cleanup, 117*cb730894SDaniel P. Berrange }; 118*cb730894SDaniel P. Berrange 119