diff options
author | Daniel P. Berrange <berrange@redhat.com> | 2016-09-07 13:12:28 +0100 |
---|---|---|
committer | Daniel P. Berrange <berrange@redhat.com> | 2016-09-19 16:30:45 +0100 |
commit | 533008f4f382490f817a0c313f2d32f6173c08c7 (patch) | |
tree | 79e6b5a6b136d9901480f93275bf618248cca654 /crypto | |
parent | 2ab66cd577d6d0ec3c44b14cc823e76ea5a4397c (diff) |
crypto: support more hash algorithms for pbkdf
Currently pbkdf is only supported with SHA1 and SHA256. Expand
this to support all algorithms known to QEMU.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/pbkdf-gcrypt.c | 12 | ||||
-rw-r--r-- | crypto/pbkdf-nettle.c | 63 |
2 files changed, 65 insertions, 10 deletions
diff --git a/crypto/pbkdf-gcrypt.c b/crypto/pbkdf-gcrypt.c index 44cf31aff4..40289858bf 100644 --- a/crypto/pbkdf-gcrypt.c +++ b/crypto/pbkdf-gcrypt.c @@ -28,7 +28,11 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash) switch (hash) { case QCRYPTO_HASH_ALG_MD5: case QCRYPTO_HASH_ALG_SHA1: + case QCRYPTO_HASH_ALG_SHA224: case QCRYPTO_HASH_ALG_SHA256: + case QCRYPTO_HASH_ALG_SHA384: + case QCRYPTO_HASH_ALG_SHA512: + case QCRYPTO_HASH_ALG_RIPEMD160: return true; default: return false; @@ -45,7 +49,11 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, static const int hash_map[QCRYPTO_HASH_ALG__MAX] = { [QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5, [QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1, + [QCRYPTO_HASH_ALG_SHA224] = GCRY_MD_SHA224, [QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256, + [QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384, + [QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512, + [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160, }; int ret; @@ -58,7 +66,9 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, if (hash >= G_N_ELEMENTS(hash_map) || hash_map[hash] == GCRY_MD_NONE) { - error_setg(errp, "Unexpected hash algorithm %d", hash); + error_setg_errno(errp, ENOSYS, + "PBKDF does not support hash algorithm %s", + QCryptoHashAlgorithm_lookup[hash]); return -1; } diff --git a/crypto/pbkdf-nettle.c b/crypto/pbkdf-nettle.c index db81517adc..6fb2671656 100644 --- a/crypto/pbkdf-nettle.c +++ b/crypto/pbkdf-nettle.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include <nettle/pbkdf2.h> +#include <nettle/hmac.h> #include "qapi/error.h" #include "crypto/pbkdf.h" @@ -28,7 +29,11 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash) { switch (hash) { case QCRYPTO_HASH_ALG_SHA1: + case QCRYPTO_HASH_ALG_SHA224: case QCRYPTO_HASH_ALG_SHA256: + case QCRYPTO_HASH_ALG_SHA384: + case QCRYPTO_HASH_ALG_SHA512: + case QCRYPTO_HASH_ALG_RIPEMD160: return true; default: return false; @@ -42,30 +47,70 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash, uint8_t *out, size_t nout, Error **errp) { + union { + struct hmac_md5_ctx md5; + struct hmac_sha1_ctx sha1; + struct hmac_sha224_ctx sha224; + struct hmac_sha256_ctx sha256; + struct hmac_sha384_ctx sha384; + struct hmac_sha512_ctx sha512; + struct hmac_ripemd160_ctx ripemd160; + } ctx; + if (iterations > UINT_MAX) { error_setg_errno(errp, ERANGE, "PBKDF iterations %llu must be less than %u", (long long unsigned)iterations, UINT_MAX); return -1; } + switch (hash) { + case QCRYPTO_HASH_ALG_MD5: + hmac_md5_set_key(&ctx.md5, nkey, key); + PBKDF2(&ctx.md5, hmac_md5_update, hmac_md5_digest, + MD5_DIGEST_SIZE, iterations, nsalt, salt, nout, out); + break; + case QCRYPTO_HASH_ALG_SHA1: - pbkdf2_hmac_sha1(nkey, key, - iterations, - nsalt, salt, - nout, out); + hmac_sha1_set_key(&ctx.sha1, nkey, key); + PBKDF2(&ctx.sha1, hmac_sha1_update, hmac_sha1_digest, + SHA1_DIGEST_SIZE, iterations, nsalt, salt, nout, out); + break; + + case QCRYPTO_HASH_ALG_SHA224: + hmac_sha224_set_key(&ctx.sha224, nkey, key); + PBKDF2(&ctx.sha224, hmac_sha224_update, hmac_sha224_digest, + SHA224_DIGEST_SIZE, iterations, nsalt, salt, nout, out); break; case QCRYPTO_HASH_ALG_SHA256: - pbkdf2_hmac_sha256(nkey, key, - iterations, - nsalt, salt, - nout, out); + hmac_sha256_set_key(&ctx.sha256, nkey, key); + PBKDF2(&ctx.sha256, hmac_sha256_update, hmac_sha256_digest, + SHA256_DIGEST_SIZE, iterations, nsalt, salt, nout, out); + break; + + case QCRYPTO_HASH_ALG_SHA384: + hmac_sha384_set_key(&ctx.sha384, nkey, key); + PBKDF2(&ctx.sha384, hmac_sha384_update, hmac_sha384_digest, + SHA384_DIGEST_SIZE, iterations, nsalt, salt, nout, out); + break; + + case QCRYPTO_HASH_ALG_SHA512: + hmac_sha512_set_key(&ctx.sha512, nkey, key); + PBKDF2(&ctx.sha512, hmac_sha512_update, hmac_sha512_digest, + SHA512_DIGEST_SIZE, iterations, nsalt, salt, nout, out); + break; + + case QCRYPTO_HASH_ALG_RIPEMD160: + hmac_ripemd160_set_key(&ctx.ripemd160, nkey, key); + PBKDF2(&ctx.ripemd160, hmac_ripemd160_update, hmac_ripemd160_digest, + RIPEMD160_DIGEST_SIZE, iterations, nsalt, salt, nout, out); break; default: error_setg_errno(errp, ENOSYS, - "PBKDF does not support hash algorithm %d", hash); + "PBKDF does not support hash algorithm %s", + QCryptoHashAlgorithm_lookup[hash]); return -1; } return 0; |