137788f25SDaniel P. Berrange /* 237788f25SDaniel P. Berrange * QEMU Crypto PBKDF support (Password-Based Key Derivation Function) 337788f25SDaniel P. Berrange * 437788f25SDaniel P. Berrange * Copyright (c) 2015-2016 Red Hat, Inc. 537788f25SDaniel P. Berrange * 637788f25SDaniel P. Berrange * This library is free software; you can redistribute it and/or 737788f25SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 837788f25SDaniel P. Berrange * License as published by the Free Software Foundation; either 937788f25SDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 1037788f25SDaniel P. Berrange * 1137788f25SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 1237788f25SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 1337788f25SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1437788f25SDaniel P. Berrange * Lesser General Public License for more details. 1537788f25SDaniel P. Berrange * 1637788f25SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 1737788f25SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1837788f25SDaniel P. Berrange * 1937788f25SDaniel P. Berrange */ 2037788f25SDaniel P. Berrange 2137788f25SDaniel P. Berrange #include "qemu/osdep.h" 22*da34e65cSMarkus Armbruster #include "qapi/error.h" 2337788f25SDaniel P. Berrange #include "crypto/pbkdf.h" 2437788f25SDaniel P. Berrange #include "gcrypt.h" 2537788f25SDaniel P. Berrange 2637788f25SDaniel P. Berrange bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash) 2737788f25SDaniel P. Berrange { 2837788f25SDaniel P. Berrange switch (hash) { 2937788f25SDaniel P. Berrange case QCRYPTO_HASH_ALG_MD5: 3037788f25SDaniel P. Berrange case QCRYPTO_HASH_ALG_SHA1: 3137788f25SDaniel P. Berrange case QCRYPTO_HASH_ALG_SHA256: 3237788f25SDaniel P. Berrange return true; 3337788f25SDaniel P. Berrange default: 3437788f25SDaniel P. Berrange return false; 3537788f25SDaniel P. Berrange } 3637788f25SDaniel P. Berrange } 3737788f25SDaniel P. Berrange 3837788f25SDaniel P. Berrange int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, 3937788f25SDaniel P. Berrange const uint8_t *key, size_t nkey, 4037788f25SDaniel P. Berrange const uint8_t *salt, size_t nsalt, 4137788f25SDaniel P. Berrange unsigned int iterations, 4237788f25SDaniel P. Berrange uint8_t *out, size_t nout, 4337788f25SDaniel P. Berrange Error **errp) 4437788f25SDaniel P. Berrange { 4537788f25SDaniel P. Berrange static const int hash_map[QCRYPTO_HASH_ALG__MAX] = { 4637788f25SDaniel P. Berrange [QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5, 4737788f25SDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1, 4837788f25SDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256, 4937788f25SDaniel P. Berrange }; 5037788f25SDaniel P. Berrange int ret; 5137788f25SDaniel P. Berrange 5237788f25SDaniel P. Berrange if (hash >= G_N_ELEMENTS(hash_map) || 5337788f25SDaniel P. Berrange hash_map[hash] == GCRY_MD_NONE) { 5437788f25SDaniel P. Berrange error_setg(errp, "Unexpected hash algorithm %d", hash); 5537788f25SDaniel P. Berrange return -1; 5637788f25SDaniel P. Berrange } 5737788f25SDaniel P. Berrange 5837788f25SDaniel P. Berrange ret = gcry_kdf_derive(key, nkey, GCRY_KDF_PBKDF2, 5937788f25SDaniel P. Berrange hash_map[hash], 6037788f25SDaniel P. Berrange salt, nsalt, iterations, 6137788f25SDaniel P. Berrange nout, out); 6237788f25SDaniel P. Berrange if (ret != 0) { 6337788f25SDaniel P. Berrange error_setg(errp, "Cannot derive password: %s", 6437788f25SDaniel P. Berrange gcry_strerror(ret)); 6537788f25SDaniel P. Berrange return -1; 6637788f25SDaniel P. Berrange } 6737788f25SDaniel P. Berrange 6837788f25SDaniel P. Berrange return 0; 6937788f25SDaniel P. Berrange } 70