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 9b7cbb874SThomas Huth * version 2.1 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 212a6a4076SMarkus Armbruster #ifndef QCRYPTO_PBKDF_H 222a6a4076SMarkus Armbruster #define QCRYPTO_PBKDF_H 2337788f25SDaniel P. Berrange 2437788f25SDaniel P. Berrange #include "crypto/hash.h" 2537788f25SDaniel P. Berrange 2637788f25SDaniel P. Berrange /** 2737788f25SDaniel P. Berrange * This module provides an interface to the PBKDF2 algorithm 2837788f25SDaniel P. Berrange * 2937788f25SDaniel P. Berrange * https://en.wikipedia.org/wiki/PBKDF2 3037788f25SDaniel P. Berrange * 3137788f25SDaniel P. Berrange * <example> 3237788f25SDaniel P. Berrange * <title>Generating an AES encryption key from a user password</title> 3337788f25SDaniel P. Berrange * <programlisting> 3437788f25SDaniel P. Berrange * #include "crypto/cipher.h" 3537788f25SDaniel P. Berrange * #include "crypto/random.h" 3637788f25SDaniel P. Berrange * #include "crypto/pbkdf.h" 3737788f25SDaniel P. Berrange * 3837788f25SDaniel P. Berrange * .... 3937788f25SDaniel P. Berrange * 4037788f25SDaniel P. Berrange * char *password = "a-typical-awful-user-password"; 41*a092c513SMarkus Armbruster * size_t nkey = qcrypto_cipher_get_key_len(QCRYPTO_CIPHER_ALGO_AES_128); 4237788f25SDaniel P. Berrange * uint8_t *salt = g_new0(uint8_t, nkey); 4337788f25SDaniel P. Berrange * uint8_t *key = g_new0(uint8_t, nkey); 4437788f25SDaniel P. Berrange * int iterations; 4537788f25SDaniel P. Berrange * QCryptoCipher *cipher; 4637788f25SDaniel P. Berrange * 4737788f25SDaniel P. Berrange * if (qcrypto_random_bytes(salt, nkey, errp) < 0) { 4837788f25SDaniel P. Berrange * g_free(key); 4937788f25SDaniel P. Berrange * g_free(salt); 5037788f25SDaniel P. Berrange * return -1; 5137788f25SDaniel P. Berrange * } 5237788f25SDaniel P. Berrange * 53ef834aa2SMarkus Armbruster * iterations = qcrypto_pbkdf2_count_iters(QCRYPTO_HASH_ALGO_SHA256, 5437788f25SDaniel P. Berrange * (const uint8_t *)password, 5537788f25SDaniel P. Berrange * strlen(password), 5637788f25SDaniel P. Berrange * salt, nkey, errp); 5737788f25SDaniel P. Berrange * if (iterations < 0) { 5837788f25SDaniel P. Berrange * g_free(key); 5937788f25SDaniel P. Berrange * g_free(salt); 6037788f25SDaniel P. Berrange * return -1; 6137788f25SDaniel P. Berrange * } 6237788f25SDaniel P. Berrange * 63ef834aa2SMarkus Armbruster * if (qcrypto_pbkdf2(QCRYPTO_HASH_ALGO_SHA256, 6437788f25SDaniel P. Berrange * (const uint8_t *)password, strlen(password), 6537788f25SDaniel P. Berrange * salt, nkey, iterations, key, nkey, errp) < 0) { 6637788f25SDaniel P. Berrange * g_free(key); 6737788f25SDaniel P. Berrange * g_free(salt); 6837788f25SDaniel P. Berrange * return -1; 6937788f25SDaniel P. Berrange * } 7037788f25SDaniel P. Berrange * 7137788f25SDaniel P. Berrange * g_free(salt); 7237788f25SDaniel P. Berrange * 73*a092c513SMarkus Armbruster * cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALGO_AES_128, 7437788f25SDaniel P. Berrange * QCRYPTO_CIPHER_MODE_ECB, 7537788f25SDaniel P. Berrange * key, nkey, errp); 7637788f25SDaniel P. Berrange * g_free(key); 7737788f25SDaniel P. Berrange * 7837788f25SDaniel P. Berrange * ....encrypt some data... 7937788f25SDaniel P. Berrange * 8037788f25SDaniel P. Berrange * qcrypto_cipher_free(cipher); 8137788f25SDaniel P. Berrange * </programlisting> 8237788f25SDaniel P. Berrange * </example> 8337788f25SDaniel P. Berrange * 8437788f25SDaniel P. Berrange */ 8537788f25SDaniel P. Berrange 8637788f25SDaniel P. Berrange /** 8737788f25SDaniel P. Berrange * qcrypto_pbkdf2_supports: 8837788f25SDaniel P. Berrange * @hash: the hash algorithm 8937788f25SDaniel P. Berrange * 9037788f25SDaniel P. Berrange * Determine if the current build supports the PBKDF2 algorithm 9137788f25SDaniel P. Berrange * in combination with the hash @hash. 9237788f25SDaniel P. Berrange * 9337788f25SDaniel P. Berrange * Returns true if supported, false otherwise 9437788f25SDaniel P. Berrange */ 95ef834aa2SMarkus Armbruster bool qcrypto_pbkdf2_supports(QCryptoHashAlgo hash); 9637788f25SDaniel P. Berrange 9737788f25SDaniel P. Berrange 9837788f25SDaniel P. Berrange /** 9937788f25SDaniel P. Berrange * qcrypto_pbkdf2: 10037788f25SDaniel P. Berrange * @hash: the hash algorithm to use 10137788f25SDaniel P. Berrange * @key: the user password / key 10237788f25SDaniel P. Berrange * @nkey: the length of @key in bytes 10337788f25SDaniel P. Berrange * @salt: a random salt 10437788f25SDaniel P. Berrange * @nsalt: length of @salt in bytes 10537788f25SDaniel P. Berrange * @iterations: the number of iterations to compute 10637788f25SDaniel P. Berrange * @out: pointer to pre-allocated buffer to hold output 10737788f25SDaniel P. Berrange * @nout: length of @out in bytes 10837788f25SDaniel P. Berrange * @errp: pointer to a NULL-initialized error object 10937788f25SDaniel P. Berrange * 11037788f25SDaniel P. Berrange * Apply the PBKDF2 algorithm to derive an encryption 11137788f25SDaniel P. Berrange * key from a user password provided in @key. The 11237788f25SDaniel P. Berrange * @salt parameter is used to perturb the algorithm. 11337788f25SDaniel P. Berrange * The @iterations count determines how many times 11437788f25SDaniel P. Berrange * the hashing process is run, which influences how 11537788f25SDaniel P. Berrange * hard it is to crack the key. The number of @iterations 11637788f25SDaniel P. Berrange * should be large enough such that the algorithm takes 11737788f25SDaniel P. Berrange * 1 second or longer to derive a key. The derived key 11837788f25SDaniel P. Berrange * will be stored in the preallocated buffer @out. 11937788f25SDaniel P. Berrange * 12037788f25SDaniel P. Berrange * Returns: 0 on success, -1 on error 12137788f25SDaniel P. Berrange */ 122ef834aa2SMarkus Armbruster int qcrypto_pbkdf2(QCryptoHashAlgo hash, 12337788f25SDaniel P. Berrange const uint8_t *key, size_t nkey, 12437788f25SDaniel P. Berrange const uint8_t *salt, size_t nsalt, 12559b060beSDaniel P. Berrange uint64_t iterations, 12637788f25SDaniel P. Berrange uint8_t *out, size_t nout, 12737788f25SDaniel P. Berrange Error **errp); 12837788f25SDaniel P. Berrange 12937788f25SDaniel P. Berrange /** 13037788f25SDaniel P. Berrange * qcrypto_pbkdf2_count_iters: 13137788f25SDaniel P. Berrange * @hash: the hash algorithm to use 13237788f25SDaniel P. Berrange * @key: the user password / key 13337788f25SDaniel P. Berrange * @nkey: the length of @key in bytes 13437788f25SDaniel P. Berrange * @salt: a random salt 13537788f25SDaniel P. Berrange * @nsalt: length of @salt in bytes 136e74aabcfSDaniel P. Berrange * @nout: size of desired derived key 13737788f25SDaniel P. Berrange * @errp: pointer to a NULL-initialized error object 13837788f25SDaniel P. Berrange * 13937788f25SDaniel P. Berrange * Time the PBKDF2 algorithm to determine how many 14037788f25SDaniel P. Berrange * iterations are required to derive an encryption 14137788f25SDaniel P. Berrange * key from a user password provided in @key in 1 14237788f25SDaniel P. Berrange * second of compute time. The result of this can 14337788f25SDaniel P. Berrange * be used as a the @iterations parameter of a later 144e74aabcfSDaniel P. Berrange * call to qcrypto_pbkdf2(). The value of @nout should 145e74aabcfSDaniel P. Berrange * match that value that will later be provided with 146e74aabcfSDaniel P. Berrange * a call to qcrypto_pbkdf2(). 14737788f25SDaniel P. Berrange * 14837788f25SDaniel P. Berrange * Returns: number of iterations in 1 second, -1 on error 14937788f25SDaniel P. Berrange */ 150ef834aa2SMarkus Armbruster uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgo hash, 15137788f25SDaniel P. Berrange const uint8_t *key, size_t nkey, 15237788f25SDaniel P. Berrange const uint8_t *salt, size_t nsalt, 153e74aabcfSDaniel P. Berrange size_t nout, 15437788f25SDaniel P. Berrange Error **errp); 15537788f25SDaniel P. Berrange 1562a6a4076SMarkus Armbruster #endif /* QCRYPTO_PBKDF_H */ 157