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 #ifndef QCRYPTO_PBKDF_H__ 22*37788f25SDaniel P. Berrange #define QCRYPTO_PBKDF_H__ 23*37788f25SDaniel P. Berrange 24*37788f25SDaniel P. Berrange #include "crypto/hash.h" 25*37788f25SDaniel P. Berrange 26*37788f25SDaniel P. Berrange /** 27*37788f25SDaniel P. Berrange * This module provides an interface to the PBKDF2 algorithm 28*37788f25SDaniel P. Berrange * 29*37788f25SDaniel P. Berrange * https://en.wikipedia.org/wiki/PBKDF2 30*37788f25SDaniel P. Berrange * 31*37788f25SDaniel P. Berrange * <example> 32*37788f25SDaniel P. Berrange * <title>Generating an AES encryption key from a user password</title> 33*37788f25SDaniel P. Berrange * <programlisting> 34*37788f25SDaniel P. Berrange * #include "crypto/cipher.h" 35*37788f25SDaniel P. Berrange * #include "crypto/random.h" 36*37788f25SDaniel P. Berrange * #include "crypto/pbkdf.h" 37*37788f25SDaniel P. Berrange * 38*37788f25SDaniel P. Berrange * .... 39*37788f25SDaniel P. Berrange * 40*37788f25SDaniel P. Berrange * char *password = "a-typical-awful-user-password"; 41*37788f25SDaniel P. Berrange * size_t nkey = qcrypto_cipher_get_key_len(QCRYPTO_CIPHER_ALG_AES_128); 42*37788f25SDaniel P. Berrange * uint8_t *salt = g_new0(uint8_t, nkey); 43*37788f25SDaniel P. Berrange * uint8_t *key = g_new0(uint8_t, nkey); 44*37788f25SDaniel P. Berrange * int iterations; 45*37788f25SDaniel P. Berrange * QCryptoCipher *cipher; 46*37788f25SDaniel P. Berrange * 47*37788f25SDaniel P. Berrange * if (qcrypto_random_bytes(salt, nkey, errp) < 0) { 48*37788f25SDaniel P. Berrange * g_free(key); 49*37788f25SDaniel P. Berrange * g_free(salt); 50*37788f25SDaniel P. Berrange * return -1; 51*37788f25SDaniel P. Berrange * } 52*37788f25SDaniel P. Berrange * 53*37788f25SDaniel P. Berrange * iterations = qcrypto_pbkdf2_count_iters(QCRYPTO_HASH_ALG_SHA256, 54*37788f25SDaniel P. Berrange * (const uint8_t *)password, 55*37788f25SDaniel P. Berrange * strlen(password), 56*37788f25SDaniel P. Berrange * salt, nkey, errp); 57*37788f25SDaniel P. Berrange * if (iterations < 0) { 58*37788f25SDaniel P. Berrange * g_free(key); 59*37788f25SDaniel P. Berrange * g_free(salt); 60*37788f25SDaniel P. Berrange * return -1; 61*37788f25SDaniel P. Berrange * } 62*37788f25SDaniel P. Berrange * 63*37788f25SDaniel P. Berrange * if (qcrypto_pbkdf2(QCRYPTO_HASH_ALG_SHA256, 64*37788f25SDaniel P. Berrange * (const uint8_t *)password, strlen(password), 65*37788f25SDaniel P. Berrange * salt, nkey, iterations, key, nkey, errp) < 0) { 66*37788f25SDaniel P. Berrange * g_free(key); 67*37788f25SDaniel P. Berrange * g_free(salt); 68*37788f25SDaniel P. Berrange * return -1; 69*37788f25SDaniel P. Berrange * } 70*37788f25SDaniel P. Berrange * 71*37788f25SDaniel P. Berrange * g_free(salt); 72*37788f25SDaniel P. Berrange * 73*37788f25SDaniel P. Berrange * cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128, 74*37788f25SDaniel P. Berrange * QCRYPTO_CIPHER_MODE_ECB, 75*37788f25SDaniel P. Berrange * key, nkey, errp); 76*37788f25SDaniel P. Berrange * g_free(key); 77*37788f25SDaniel P. Berrange * 78*37788f25SDaniel P. Berrange * ....encrypt some data... 79*37788f25SDaniel P. Berrange * 80*37788f25SDaniel P. Berrange * qcrypto_cipher_free(cipher); 81*37788f25SDaniel P. Berrange * </programlisting> 82*37788f25SDaniel P. Berrange * </example> 83*37788f25SDaniel P. Berrange * 84*37788f25SDaniel P. Berrange */ 85*37788f25SDaniel P. Berrange 86*37788f25SDaniel P. Berrange /** 87*37788f25SDaniel P. Berrange * qcrypto_pbkdf2_supports: 88*37788f25SDaniel P. Berrange * @hash: the hash algorithm 89*37788f25SDaniel P. Berrange * 90*37788f25SDaniel P. Berrange * Determine if the current build supports the PBKDF2 algorithm 91*37788f25SDaniel P. Berrange * in combination with the hash @hash. 92*37788f25SDaniel P. Berrange * 93*37788f25SDaniel P. Berrange * Returns true if supported, false otherwise 94*37788f25SDaniel P. Berrange */ 95*37788f25SDaniel P. Berrange bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash); 96*37788f25SDaniel P. Berrange 97*37788f25SDaniel P. Berrange 98*37788f25SDaniel P. Berrange /** 99*37788f25SDaniel P. Berrange * qcrypto_pbkdf2: 100*37788f25SDaniel P. Berrange * @hash: the hash algorithm to use 101*37788f25SDaniel P. Berrange * @key: the user password / key 102*37788f25SDaniel P. Berrange * @nkey: the length of @key in bytes 103*37788f25SDaniel P. Berrange * @salt: a random salt 104*37788f25SDaniel P. Berrange * @nsalt: length of @salt in bytes 105*37788f25SDaniel P. Berrange * @iterations: the number of iterations to compute 106*37788f25SDaniel P. Berrange * @out: pointer to pre-allocated buffer to hold output 107*37788f25SDaniel P. Berrange * @nout: length of @out in bytes 108*37788f25SDaniel P. Berrange * @errp: pointer to a NULL-initialized error object 109*37788f25SDaniel P. Berrange * 110*37788f25SDaniel P. Berrange * Apply the PBKDF2 algorithm to derive an encryption 111*37788f25SDaniel P. Berrange * key from a user password provided in @key. The 112*37788f25SDaniel P. Berrange * @salt parameter is used to perturb the algorithm. 113*37788f25SDaniel P. Berrange * The @iterations count determines how many times 114*37788f25SDaniel P. Berrange * the hashing process is run, which influences how 115*37788f25SDaniel P. Berrange * hard it is to crack the key. The number of @iterations 116*37788f25SDaniel P. Berrange * should be large enough such that the algorithm takes 117*37788f25SDaniel P. Berrange * 1 second or longer to derive a key. The derived key 118*37788f25SDaniel P. Berrange * will be stored in the preallocated buffer @out. 119*37788f25SDaniel P. Berrange * 120*37788f25SDaniel P. Berrange * Returns: 0 on success, -1 on error 121*37788f25SDaniel P. Berrange */ 122*37788f25SDaniel P. Berrange int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, 123*37788f25SDaniel P. Berrange const uint8_t *key, size_t nkey, 124*37788f25SDaniel P. Berrange const uint8_t *salt, size_t nsalt, 125*37788f25SDaniel P. Berrange unsigned int iterations, 126*37788f25SDaniel P. Berrange uint8_t *out, size_t nout, 127*37788f25SDaniel P. Berrange Error **errp); 128*37788f25SDaniel P. Berrange 129*37788f25SDaniel P. Berrange /** 130*37788f25SDaniel P. Berrange * qcrypto_pbkdf2_count_iters: 131*37788f25SDaniel P. Berrange * @hash: the hash algorithm to use 132*37788f25SDaniel P. Berrange * @key: the user password / key 133*37788f25SDaniel P. Berrange * @nkey: the length of @key in bytes 134*37788f25SDaniel P. Berrange * @salt: a random salt 135*37788f25SDaniel P. Berrange * @nsalt: length of @salt in bytes 136*37788f25SDaniel P. Berrange * @errp: pointer to a NULL-initialized error object 137*37788f25SDaniel P. Berrange * 138*37788f25SDaniel P. Berrange * Time the PBKDF2 algorithm to determine how many 139*37788f25SDaniel P. Berrange * iterations are required to derive an encryption 140*37788f25SDaniel P. Berrange * key from a user password provided in @key in 1 141*37788f25SDaniel P. Berrange * second of compute time. The result of this can 142*37788f25SDaniel P. Berrange * be used as a the @iterations parameter of a later 143*37788f25SDaniel P. Berrange * call to qcrypto_pbkdf2(). 144*37788f25SDaniel P. Berrange * 145*37788f25SDaniel P. Berrange * Returns: number of iterations in 1 second, -1 on error 146*37788f25SDaniel P. Berrange */ 147*37788f25SDaniel P. Berrange int qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash, 148*37788f25SDaniel P. Berrange const uint8_t *key, size_t nkey, 149*37788f25SDaniel P. Berrange const uint8_t *salt, size_t nsalt, 150*37788f25SDaniel P. Berrange Error **errp); 151*37788f25SDaniel P. Berrange 152*37788f25SDaniel P. Berrange #endif /* QCRYPTO_PBKDF_H__ */ 153