]>
Commit | Line | Data |
---|---|---|
37788f25 DB |
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 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 | #include "qemu/osdep.h" | |
a9c94277 | 22 | #include <nettle/pbkdf2.h> |
533008f4 | 23 | #include <nettle/hmac.h> |
da34e65c | 24 | #include "qapi/error.h" |
37788f25 | 25 | #include "crypto/pbkdf.h" |
37788f25 DB |
26 | |
27 | ||
28 | bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash) | |
29 | { | |
30 | switch (hash) { | |
31 | case QCRYPTO_HASH_ALG_SHA1: | |
533008f4 | 32 | case QCRYPTO_HASH_ALG_SHA224: |
37788f25 | 33 | case QCRYPTO_HASH_ALG_SHA256: |
533008f4 DB |
34 | case QCRYPTO_HASH_ALG_SHA384: |
35 | case QCRYPTO_HASH_ALG_SHA512: | |
36 | case QCRYPTO_HASH_ALG_RIPEMD160: | |
37788f25 DB |
37 | return true; |
38 | default: | |
39 | return false; | |
40 | } | |
41 | } | |
42 | ||
43 | int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, | |
44 | const uint8_t *key, size_t nkey, | |
45 | const uint8_t *salt, size_t nsalt, | |
59b060be | 46 | uint64_t iterations, |
37788f25 DB |
47 | uint8_t *out, size_t nout, |
48 | Error **errp) | |
49 | { | |
533008f4 DB |
50 | union { |
51 | struct hmac_md5_ctx md5; | |
52 | struct hmac_sha1_ctx sha1; | |
53 | struct hmac_sha224_ctx sha224; | |
54 | struct hmac_sha256_ctx sha256; | |
55 | struct hmac_sha384_ctx sha384; | |
56 | struct hmac_sha512_ctx sha512; | |
57 | struct hmac_ripemd160_ctx ripemd160; | |
58 | } ctx; | |
59 | ||
59b060be DB |
60 | if (iterations > UINT_MAX) { |
61 | error_setg_errno(errp, ERANGE, | |
62 | "PBKDF iterations %llu must be less than %u", | |
63 | (long long unsigned)iterations, UINT_MAX); | |
64 | return -1; | |
65 | } | |
533008f4 | 66 | |
37788f25 | 67 | switch (hash) { |
533008f4 DB |
68 | case QCRYPTO_HASH_ALG_MD5: |
69 | hmac_md5_set_key(&ctx.md5, nkey, key); | |
70 | PBKDF2(&ctx.md5, hmac_md5_update, hmac_md5_digest, | |
71 | MD5_DIGEST_SIZE, iterations, nsalt, salt, nout, out); | |
72 | break; | |
73 | ||
37788f25 | 74 | case QCRYPTO_HASH_ALG_SHA1: |
533008f4 DB |
75 | hmac_sha1_set_key(&ctx.sha1, nkey, key); |
76 | PBKDF2(&ctx.sha1, hmac_sha1_update, hmac_sha1_digest, | |
77 | SHA1_DIGEST_SIZE, iterations, nsalt, salt, nout, out); | |
78 | break; | |
79 | ||
80 | case QCRYPTO_HASH_ALG_SHA224: | |
81 | hmac_sha224_set_key(&ctx.sha224, nkey, key); | |
82 | PBKDF2(&ctx.sha224, hmac_sha224_update, hmac_sha224_digest, | |
83 | SHA224_DIGEST_SIZE, iterations, nsalt, salt, nout, out); | |
37788f25 DB |
84 | break; |
85 | ||
86 | case QCRYPTO_HASH_ALG_SHA256: | |
533008f4 DB |
87 | hmac_sha256_set_key(&ctx.sha256, nkey, key); |
88 | PBKDF2(&ctx.sha256, hmac_sha256_update, hmac_sha256_digest, | |
89 | SHA256_DIGEST_SIZE, iterations, nsalt, salt, nout, out); | |
90 | break; | |
91 | ||
92 | case QCRYPTO_HASH_ALG_SHA384: | |
93 | hmac_sha384_set_key(&ctx.sha384, nkey, key); | |
94 | PBKDF2(&ctx.sha384, hmac_sha384_update, hmac_sha384_digest, | |
95 | SHA384_DIGEST_SIZE, iterations, nsalt, salt, nout, out); | |
96 | break; | |
97 | ||
98 | case QCRYPTO_HASH_ALG_SHA512: | |
99 | hmac_sha512_set_key(&ctx.sha512, nkey, key); | |
100 | PBKDF2(&ctx.sha512, hmac_sha512_update, hmac_sha512_digest, | |
101 | SHA512_DIGEST_SIZE, iterations, nsalt, salt, nout, out); | |
102 | break; | |
103 | ||
104 | case QCRYPTO_HASH_ALG_RIPEMD160: | |
105 | hmac_ripemd160_set_key(&ctx.ripemd160, nkey, key); | |
106 | PBKDF2(&ctx.ripemd160, hmac_ripemd160_update, hmac_ripemd160_digest, | |
107 | RIPEMD160_DIGEST_SIZE, iterations, nsalt, salt, nout, out); | |
37788f25 DB |
108 | break; |
109 | ||
110 | default: | |
111 | error_setg_errno(errp, ENOSYS, | |
533008f4 DB |
112 | "PBKDF does not support hash algorithm %s", |
113 | QCryptoHashAlgorithm_lookup[hash]); | |
37788f25 DB |
114 | return -1; |
115 | } | |
116 | return 0; | |
117 | } |