1*37788f25SDaniel P. Berrange /* 2*37788f25SDaniel P. Berrange * QEMU Crypto PBKDF support (Password-Based Key Derivation Function) 3*37788f25SDaniel P. Berrange * 4*37788f25SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 5*37788f25SDaniel P. Berrange * 6*37788f25SDaniel P. Berrange * This library is free software; you can redistribute it and/or 7*37788f25SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 8*37788f25SDaniel P. Berrange * License as published by the Free Software Foundation; either 9*37788f25SDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 10*37788f25SDaniel P. Berrange * 11*37788f25SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 12*37788f25SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*37788f25SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*37788f25SDaniel P. Berrange * Lesser General Public License for more details. 15*37788f25SDaniel P. Berrange * 16*37788f25SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 17*37788f25SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18*37788f25SDaniel P. Berrange * 19*37788f25SDaniel P. Berrange */ 20*37788f25SDaniel P. Berrange 21*37788f25SDaniel P. Berrange #include "qemu/osdep.h" 22*37788f25SDaniel P. Berrange #include "crypto/pbkdf.h" 23*37788f25SDaniel P. Berrange #include "gcrypt.h" 24*37788f25SDaniel P. Berrange 25*37788f25SDaniel P. Berrange bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash) 26*37788f25SDaniel P. Berrange { 27*37788f25SDaniel P. Berrange switch (hash) { 28*37788f25SDaniel P. Berrange case QCRYPTO_HASH_ALG_MD5: 29*37788f25SDaniel P. Berrange case QCRYPTO_HASH_ALG_SHA1: 30*37788f25SDaniel P. Berrange case QCRYPTO_HASH_ALG_SHA256: 31*37788f25SDaniel P. Berrange return true; 32*37788f25SDaniel P. Berrange default: 33*37788f25SDaniel P. Berrange return false; 34*37788f25SDaniel P. Berrange } 35*37788f25SDaniel P. Berrange } 36*37788f25SDaniel P. Berrange 37*37788f25SDaniel P. Berrange int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, 38*37788f25SDaniel P. Berrange const uint8_t *key, size_t nkey, 39*37788f25SDaniel P. Berrange const uint8_t *salt, size_t nsalt, 40*37788f25SDaniel P. Berrange unsigned int iterations, 41*37788f25SDaniel P. Berrange uint8_t *out, size_t nout, 42*37788f25SDaniel P. Berrange Error **errp) 43*37788f25SDaniel P. Berrange { 44*37788f25SDaniel P. Berrange static const int hash_map[QCRYPTO_HASH_ALG__MAX] = { 45*37788f25SDaniel P. Berrange [QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5, 46*37788f25SDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1, 47*37788f25SDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256, 48*37788f25SDaniel P. Berrange }; 49*37788f25SDaniel P. Berrange int ret; 50*37788f25SDaniel P. Berrange 51*37788f25SDaniel P. Berrange if (hash >= G_N_ELEMENTS(hash_map) || 52*37788f25SDaniel P. Berrange hash_map[hash] == GCRY_MD_NONE) { 53*37788f25SDaniel P. Berrange error_setg(errp, "Unexpected hash algorithm %d", hash); 54*37788f25SDaniel P. Berrange return -1; 55*37788f25SDaniel P. Berrange } 56*37788f25SDaniel P. Berrange 57*37788f25SDaniel P. Berrange ret = gcry_kdf_derive(key, nkey, GCRY_KDF_PBKDF2, 58*37788f25SDaniel P. Berrange hash_map[hash], 59*37788f25SDaniel P. Berrange salt, nsalt, iterations, 60*37788f25SDaniel P. Berrange nout, out); 61*37788f25SDaniel P. Berrange if (ret != 0) { 62*37788f25SDaniel P. Berrange error_setg(errp, "Cannot derive password: %s", 63*37788f25SDaniel P. Berrange gcry_strerror(ret)); 64*37788f25SDaniel P. Berrange return -1; 65*37788f25SDaniel P. Berrange } 66*37788f25SDaniel P. Berrange 67*37788f25SDaniel P. Berrange return 0; 68*37788f25SDaniel P. Berrange } 69