pbkdf-gcrypt.c 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * QEMU Crypto PBKDF support (Password-Based Key Derivation Function)
  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.1 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. */
  20. #include "qemu/osdep.h"
  21. #include <gcrypt.h>
  22. #include "qapi/error.h"
  23. #include "crypto/pbkdf.h"
  24. bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
  25. {
  26. switch (hash) {
  27. case QCRYPTO_HASH_ALG_MD5:
  28. case QCRYPTO_HASH_ALG_SHA1:
  29. case QCRYPTO_HASH_ALG_SHA224:
  30. case QCRYPTO_HASH_ALG_SHA256:
  31. case QCRYPTO_HASH_ALG_SHA384:
  32. case QCRYPTO_HASH_ALG_SHA512:
  33. case QCRYPTO_HASH_ALG_RIPEMD160:
  34. return true;
  35. default:
  36. return false;
  37. }
  38. }
  39. int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
  40. const uint8_t *key, size_t nkey,
  41. const uint8_t *salt, size_t nsalt,
  42. uint64_t iterations,
  43. uint8_t *out, size_t nout,
  44. Error **errp)
  45. {
  46. static const int hash_map[QCRYPTO_HASH_ALG__MAX] = {
  47. [QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5,
  48. [QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1,
  49. [QCRYPTO_HASH_ALG_SHA224] = GCRY_MD_SHA224,
  50. [QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256,
  51. [QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384,
  52. [QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512,
  53. [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160,
  54. };
  55. int ret;
  56. if (iterations > ULONG_MAX) {
  57. error_setg_errno(errp, ERANGE,
  58. "PBKDF iterations %llu must be less than %lu",
  59. (long long unsigned)iterations, ULONG_MAX);
  60. return -1;
  61. }
  62. if (hash >= G_N_ELEMENTS(hash_map) ||
  63. hash_map[hash] == GCRY_MD_NONE) {
  64. error_setg_errno(errp, ENOSYS,
  65. "PBKDF does not support hash algorithm %s",
  66. QCryptoHashAlgorithm_str(hash));
  67. return -1;
  68. }
  69. ret = gcry_kdf_derive(key, nkey, GCRY_KDF_PBKDF2,
  70. hash_map[hash],
  71. salt, nsalt, iterations,
  72. nout, out);
  73. if (ret != 0) {
  74. error_setg(errp, "Cannot derive password: %s",
  75. gcry_strerror(ret));
  76. return -1;
  77. }
  78. return 0;
  79. }