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