diff --git a/configure.ac b/configure.ac index 3c86b79f..5c4f81f4 100644 --- a/configure.ac +++ b/configure.ac @@ -276,6 +276,7 @@ AC_DEFUN([CONFIGURE_KERNEL], [ AC_DEFUN([CONFIGURE_NETTLE], [ AC_CHECK_HEADERS(nettle/sha.h,, [AC_MSG_ERROR([You need Nettle cryptographic library.])]) + AC_CHECK_HEADERS(nettle/version.h) saved_LIBS=$LIBS AC_CHECK_LIB(nettle, nettle_pbkdf2_hmac_sha256,, diff --git a/lib/crypto_backend/crypto_nettle.c b/lib/crypto_backend/crypto_nettle.c index dfaab1ff..0768d6b6 100644 --- a/lib/crypto_backend/crypto_nettle.c +++ b/lib/crypto_backend/crypto_nettle.c @@ -23,11 +23,19 @@ #include #include #include +#include #include #include #include "crypto_backend.h" -static char *version = "Nettle"; +#if HAVE_NETTLE_VERSION_H +#include +#define VSTR(s) STR(s) +#define STR(s) #s +static const char *version = "Nettle "VSTR(NETTLE_VERSION_MAJOR)"."VSTR(NETTLE_VERSION_MINOR); +#else +static const char *version = "Nettle"; +#endif typedef void (*init_func) (void *); typedef void (*update_func) (void *, size_t, const uint8_t *); @@ -45,6 +53,24 @@ struct hash_alg { set_key_func hmac_set_key; }; +/* Missing HMAC wrappers in Nettle */ +#define HMAC_FCE(xxx) \ +struct xhmac_##xxx##_ctx HMAC_CTX(struct xxx##_ctx); \ +static void xhmac_##xxx##_set_key(struct xhmac_##xxx##_ctx *ctx, \ +size_t key_length, const uint8_t *key) \ +{HMAC_SET_KEY(ctx, &nettle_##xxx, key_length, key);} \ +static void xhmac_##xxx##_update(struct xhmac_##xxx##_ctx *ctx, \ +size_t length, const uint8_t *data) \ +{xxx##_update(&ctx->state, length, data);} \ +static void xhmac_##xxx##_digest(struct xhmac_##xxx##_ctx *ctx, \ +size_t length, uint8_t *digest) \ +{HMAC_DIGEST(ctx, &nettle_##xxx, length, digest);} + +HMAC_FCE(sha3_224); +HMAC_FCE(sha3_256); +HMAC_FCE(sha3_384); +HMAC_FCE(sha3_512); + static struct hash_alg hash_algs[] = { { "sha1", SHA1_DIGEST_SIZE, (init_func) sha1_init, @@ -94,6 +120,41 @@ static struct hash_alg hash_algs[] = { (digest_func) hmac_ripemd160_digest, (set_key_func) hmac_ripemd160_set_key, }, +/* Nettle prior to version 3.2 has incompatible SHA3 implementation */ +#if NETTLE_SHA3_FIPS202 + { "sha3-224", SHA3_224_DIGEST_SIZE, + (init_func) sha3_224_init, + (update_func) sha3_224_update, + (digest_func) sha3_224_digest, + (update_func) xhmac_sha3_224_update, + (digest_func) xhmac_sha3_224_digest, + (set_key_func) xhmac_sha3_224_set_key, + }, + { "sha3-256", SHA3_256_DIGEST_SIZE, + (init_func) sha3_256_init, + (update_func) sha3_256_update, + (digest_func) sha3_256_digest, + (update_func) xhmac_sha3_256_update, + (digest_func) xhmac_sha3_256_digest, + (set_key_func) xhmac_sha3_256_set_key, + }, + { "sha3-384", SHA3_384_DIGEST_SIZE, + (init_func) sha3_384_init, + (update_func) sha3_384_update, + (digest_func) sha3_384_digest, + (update_func) xhmac_sha3_384_update, + (digest_func) xhmac_sha3_384_digest, + (set_key_func) xhmac_sha3_384_set_key, + }, + { "sha3-512", SHA3_512_DIGEST_SIZE, + (init_func) sha3_512_init, + (update_func) sha3_512_update, + (digest_func) sha3_512_digest, + (update_func) xhmac_sha3_512_update, + (digest_func) xhmac_sha3_512_digest, + (set_key_func) xhmac_sha3_512_set_key, + }, +#endif { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, } }; @@ -106,6 +167,10 @@ struct crypt_hash { struct sha384_ctx sha384; struct sha512_ctx sha512; struct ripemd160_ctx ripemd160; + struct sha3_224_ctx sha3_224; + struct sha3_256_ctx sha3_256; + struct sha3_384_ctx sha3_384; + struct sha3_512_ctx sha3_512; } nettle_ctx; }; @@ -118,6 +183,10 @@ struct crypt_hmac { struct hmac_sha384_ctx sha384; struct hmac_sha512_ctx sha512; struct hmac_ripemd160_ctx ripemd160; + struct xhmac_sha3_224_ctx sha3_224; + struct xhmac_sha3_256_ctx sha3_256; + struct xhmac_sha3_384_ctx sha3_384; + struct xhmac_sha3_512_ctx sha3_512; } nettle_ctx; size_t key_length; uint8_t *key; @@ -301,8 +370,8 @@ int crypt_pbkdf(const char *kdf, const char *hash, if (r < 0) return r; - nettle_pbkdf2(&h->nettle_ctx, h->hash->nettle_hmac_update, - h->hash->nettle_hmac_digest, h->hash->length, iterations, + nettle_pbkdf2(&h->nettle_ctx, h->hash->hmac_update, + h->hash->hmac_digest, h->hash->length, iterations, salt_length, (const uint8_t *)salt, key_length, (uint8_t *)key); crypt_hmac_destroy(h); diff --git a/tests/crypto-vectors.c b/tests/crypto-vectors.c index 770042bb..9da00695 100644 --- a/tests/crypto-vectors.c +++ b/tests/crypto-vectors.c @@ -411,6 +411,10 @@ static int pbkdf_test_vectors(void) for (i = 0; i < (sizeof(kdf_test_vectors) / sizeof(*kdf_test_vectors)); i++) { vec = &kdf_test_vectors[i]; printf("PBKDF vector %02d %s ", i, vec->type); + if (vec->hash && crypt_hash_size(vec->hash) < 0) { + printf("[%s N/A]\n", vec->hash); + continue; + } if (crypt_pbkdf(vec->type, vec->hash, vec->password, vec->password_length, vec->salt, vec->salt_length,