/*
 * SPDX-License-Identifier: ISC
 * SPDX-URL: https://spdx.org/licenses/ISC.html
 *
 * Copyright (C) 2018 Aaron M. D. Jones <me@aaronmdjones.net>
 *
 * Digest interface testsuite.
 */

#include <atheme.h>
#include "internal.h"

/*
 * MD5 test vectors taken from RFC 1321 Appendix A.5:
 *   <https://tools.ietf.org/html/rfc1321.html#appendix-A.5>
 *
 * SHA1 test vectors taken from RFC 3174 Section 7.3:
 *   <https://tools.ietf.org/html/rfc3174#section-7.3>
 *
 * SHA2-256 test vectors taken from:
 *   <https://www.di-mgt.com.au/sha_testvectors.html>
 *
 * SHA2-512 test vectors taken from:
 *   <https://www.di-mgt.com.au/sha_testvectors.html>
 *
 * HMAC-MD5 test vectors taken from RFC 2202 Section 2:
 *   <https://tools.ietf.org/html/rfc2202.html#section-2>
 *
 * HMAC-SHA1 test vectors taken from RFC 2202 Section 3:
 *   <https://tools.ietf.org/html/rfc2202.html#section-3>
 *
 * HMAC-SHA2-256 test vectors taken from RFC 4231 Section 4.1:
 *   <https://tools.ietf.org/html/rfc4231#section-4.1>
 *
 * HMAC-SHA2-512 test vectors taken from RFC 4231 Section 4.1:
 *   <https://tools.ietf.org/html/rfc4231#section-4.1>
 *
 * HKDF vectors for MD5, SHA1, SHA2-256 & SHA2-512 were generated by
 * the Cryptography Hazmat interface in Python:
 *   <https://cryptography.io/en/latest/development/custom-vectors/hkdf/>
 *
 * The HKDF vectors cover the following 8 cases:
 * - ikmLen = hLen, saltLen = hLen, infoLen = hLen, okmLen = hLen
 *      ikm = 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 ...
 *     salt = 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 ...
 *     info = 0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 ...
 * - ikmLen = hLen, saltLen = (hLen * 4), infoLen = 0, okmLen = hLen
 *      ikm = 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F ...
 *     salt = 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 ...
 * - ikmLen = hLen, saltLen = 0, infoLen = (hLen * 4), okmLen = hLen
 *      ikm = 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 ...
 *     info = 0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 ...
 * - ikmLen = hLen, saltLen = 0, infoLen = 0, okmLen = hLen
 *      ikm = 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F ...
 * - ikmLen = (hLen * 2), saltLen = (hLen * 6), infoLen = (hLen * 6), okmLen = (hLen * 5)
 *      ikm = 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 ...
 *     salt = 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 ...
 *     info = 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 0xA6 0xA7 ...
 * - ikmLen = (hLen * 2), saltLen = (hLen * 8), infoLen = 0, okmLen = (hLen * 6)
 *      ikm = 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F ...
 *     salt = 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 ...
 * - ikmLen = (hLen * 2), saltLen = 0, infoLen = (hLen * 8), okmLen = (hLen * 7)
 *      ikm = 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 ...
 *     info = 0xB0 0xB1 0xB2 0xB3 0xB4 0xB5 0xB6 0xB7 ...
 * - ikmLen = (hLen * 2), saltLen = 0, infoLen = 0, okmLen = (hLen * 8)
 *      ikm = 0x38 0x39 0x3A 0x3B 0x3C 0x3D 0x3E 0x3F ...
 *
 * PBKDF2 vectors for MD5, SHA1, SHA2-256 & SHA2-512 were generated
 * by the PKCS5_PBKDF2_HMAC() function in OpenSSL:
 *   <https://www.openssl.org/>
 *   <https://github.com/openssl/openssl/blob/8d049ed24b06ada5/crypto/evp/p5_crpt2.c#L25-L34>
 */

static bool
digest_testsuite_run_md5(void)
{
	unsigned char result[DIGEST_MDLEN_MD5];

	size_t mdlen = sizeof result;

	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char vector[] = {
			0xD4U, 0x1DU, 0x8CU, 0xD9U, 0x8FU, 0x00U, 0xB2U, 0x04U,
			0xE9U, 0x80U, 0x09U, 0x98U, 0xECU, 0xF8U, 0x42U, 0x7EU,
		};

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_MD5, NULL, 0, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const char data[1] = "a";

		static const unsigned char vector[] = {
			0x0CU, 0xC1U, 0x75U, 0xB9U, 0xC0U, 0xF1U, 0xB6U, 0xA8U,
			0x31U, 0xC3U, 0x99U, 0xE2U, 0x69U, 0x77U, 0x26U, 0x61U,
		};

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_MD5, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const char data[3] = "abc";

		static const unsigned char vector[] = {
			0x90U, 0x01U, 0x50U, 0x98U, 0x3CU, 0xD2U, 0x4FU, 0xB0U,
			0xD6U, 0x96U, 0x3FU, 0x7DU, 0x28U, 0xE1U, 0x7FU, 0x72U,
		};

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_MD5, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const char data[14] = "message digest";

		static const unsigned char vector[] = {
			0xF9U, 0x6BU, 0x69U, 0x7DU, 0x7CU, 0xB7U, 0x93U, 0x8DU,
			0x52U, 0x5AU, 0x2FU, 0x31U, 0xAAU, 0xF1U, 0x61U, 0xD0U,
		};

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_MD5, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const char data[26] = "abcdefghijklmnopqrstuvwxyz";

		static const unsigned char vector[] = {
			0xC3U, 0xFCU, 0xD3U, 0xD7U, 0x61U, 0x92U, 0xE4U, 0x00U,
			0x7DU, 0xFBU, 0x49U, 0x6CU, 0xCAU, 0x67U, 0xE1U, 0x3BU,
		};

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_MD5, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const char data[62] = ""
		  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"
		  "opqrstuvwxyz0123456789";

		static const unsigned char vector[] = {
			0xD1U, 0x74U, 0xABU, 0x98U, 0xD2U, 0x77U, 0xD9U, 0xF5U,
			0xA5U, 0x61U, 0x1CU, 0x2CU, 0x9FU, 0x41U, 0x9DU, 0x9FU,
		};

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_MD5, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const char data[80] = ""
		  "1234567890123456789012345678901234567890"
		  "1234567890123456789012345678901234567890";

		static const unsigned char vector[] = {
			0x57U, 0xEDU, 0xF4U, 0xA2U, 0x2BU, 0xE3U, 0xC9U, 0x55U,
			0xACU, 0x49U, 0xDAU, 0x2EU, 0x21U, 0x07U, 0xB6U, 0x7AU,
		};

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_MD5, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	if (mdlen != sizeof result)
		return false;

	return true;
}

static bool
digest_testsuite_run_sha1(void)
{
	unsigned char result[DIGEST_MDLEN_SHA1];

	size_t mdlen = sizeof result;

	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char vector[] = {
			0xDAU, 0x39U, 0xA3U, 0xEEU, 0x5EU, 0x6BU, 0x4BU, 0x0DU,
			0x32U, 0x55U, 0xBFU, 0xEFU, 0x95U, 0x60U, 0x18U, 0x90U,
			0xAFU, 0xD8U, 0x07U, 0x09U,
		};

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA1, NULL, 0, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const char data[3] = "abc";

		static const unsigned char vector[] = {
			0xA9U, 0x99U, 0x3EU, 0x36U, 0x47U, 0x06U, 0x81U, 0x6AU,
			0xBAU, 0x3EU, 0x25U, 0x71U, 0x78U, 0x50U, 0xC2U, 0x6CU,
			0x9CU, 0xD0U, 0xD8U, 0x9DU,
		};

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA1, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const char data[56] = ""
		  "abcdbcdecdefdefgefghfghighij"
		  "hijkijkljklmklmnlmnomnopnopq";

		static const unsigned char vector[] = {
			0x84U, 0x98U, 0x3EU, 0x44U, 0x1CU, 0x3BU, 0xD2U, 0x6EU,
			0xBAU, 0xAEU, 0x4AU, 0xA1U, 0xF9U, 0x51U, 0x29U, 0xE5U,
			0xE5U, 0x46U, 0x70U, 0xF1U,
		};

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA1, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const char data[200] = ""
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

		static const unsigned char vector[] = {
			0x34U, 0xAAU, 0x97U, 0x3CU, 0xD4U, 0xC4U, 0xDAU, 0xA4U,
			0xF6U, 0x1EU, 0xEBU, 0x2BU, 0xDBU, 0xADU, 0x27U, 0x31U,
			0x65U, 0x34U, 0x01U, 0x6FU,
		};

		const struct digest_vector data_vec[] = {
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
		};

		const size_t data_vec_len = (sizeof data_vec) / (sizeof data_vec[0]);

		struct digest_context ctx;

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_init(&ctx, DIGALG_SHA1))
			return false;

		for (size_t i = 0; i < 500; i++)
			if (! digest_update_vector(&ctx, data_vec, data_vec_len))
				return false;

		if (! digest_final(&ctx, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const char data[64] = ""
		  "01234567012345670123456701234567"
		  "01234567012345670123456701234567";

		static const unsigned char vector[] = {
			0xDEU, 0xA3U, 0x56U, 0xA2U, 0xCDU, 0xDDU, 0x90U, 0xC7U,
			0xA7U, 0xECU, 0xEDU, 0xC5U, 0xEBU, 0xB5U, 0x63U, 0x93U,
			0x4FU, 0x46U, 0x04U, 0x52U,
		};

		const struct digest_vector data_vec[] = {
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
		};

		const size_t data_vec_len = (sizeof data_vec) / (sizeof data_vec[0]);

		struct digest_context ctx;

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_init(&ctx, DIGALG_SHA1))
			return false;

		if (! digest_update_vector(&ctx, data_vec, data_vec_len))
			return false;

		if (! digest_final(&ctx, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	if (mdlen != sizeof result)
		return false;

	return true;
}

static bool
digest_testsuite_run_sha2_256(void)
{
	unsigned char result[DIGEST_MDLEN_SHA2_256];

	size_t mdlen = sizeof result;

	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char vector[] = {
			0xE3U, 0xB0U, 0xC4U, 0x42U, 0x98U, 0xFCU, 0x1CU, 0x14U,
			0x9AU, 0xFBU, 0xF4U, 0xC8U, 0x99U, 0x6FU, 0xB9U, 0x24U,
			0x27U, 0xAEU, 0x41U, 0xE4U, 0x64U, 0x9BU, 0x93U, 0x4CU,
			0xA4U, 0x95U, 0x99U, 0x1BU, 0x78U, 0x52U, 0xB8U, 0x55U,
		};

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA2_256, NULL, 0, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const char data[3] = "abc";

		static const unsigned char vector[] = {
			0xBAU, 0x78U, 0x16U, 0xBFU, 0x8FU, 0x01U, 0xCFU, 0xEAU,
			0x41U, 0x41U, 0x40U, 0xDEU, 0x5DU, 0xAEU, 0x22U, 0x23U,
			0xB0U, 0x03U, 0x61U, 0xA3U, 0x96U, 0x17U, 0x7AU, 0x9CU,
			0xB4U, 0x10U, 0xFFU, 0x61U, 0xF2U, 0x00U, 0x15U, 0xADU,
		};

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA2_256, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const char data[56] = ""
		  "abcdbcdecdefdefgefghfghighij"
		  "hijkijkljklmklmnlmnomnopnopq";

		static const unsigned char vector[] = {
			0x24U, 0x8DU, 0x6AU, 0x61U, 0xD2U, 0x06U, 0x38U, 0xB8U,
			0xE5U, 0xC0U, 0x26U, 0x93U, 0x0CU, 0x3EU, 0x60U, 0x39U,
			0xA3U, 0x3CU, 0xE4U, 0x59U, 0x64U, 0xFFU, 0x21U, 0x67U,
			0xF6U, 0xECU, 0xEDU, 0xD4U, 0x19U, 0xDBU, 0x06U, 0xC1U,
		};

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA2_256, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const char data[112] = ""
		  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
		  "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";

		static const unsigned char vector[] = {
			0xCFU, 0x5BU, 0x16U, 0xA7U, 0x78U, 0xAFU, 0x83U, 0x80U,
			0x03U, 0x6CU, 0xE5U, 0x9EU, 0x7BU, 0x04U, 0x92U, 0x37U,
			0x0BU, 0x24U, 0x9BU, 0x11U, 0xE8U, 0xF0U, 0x7AU, 0x51U,
			0xAFU, 0xACU, 0x45U, 0x03U, 0x7AU, 0xFEU, 0xE9U, 0xD1U,
		};

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA2_256, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const char data[200] = ""
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

		static const unsigned char vector[] = {
			0xCDU, 0xC7U, 0x6EU, 0x5CU, 0x99U, 0x14U, 0xFBU, 0x92U,
			0x81U, 0xA1U, 0xC7U, 0xE2U, 0x84U, 0xD7U, 0x3EU, 0x67U,
			0xF1U, 0x80U, 0x9AU, 0x48U, 0xA4U, 0x97U, 0x20U, 0x0EU,
			0x04U, 0x6DU, 0x39U, 0xCCU, 0xC7U, 0x11U, 0x2CU, 0xD0U,
		};

		const struct digest_vector data_vec[] = {
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
		};

		const size_t data_vec_len = (sizeof data_vec) / (sizeof data_vec[0]);

		struct digest_context ctx;

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_init(&ctx, DIGALG_SHA2_256))
			return false;

		for (size_t i = 0; i < 500; i++)
			if (! digest_update_vector(&ctx, data_vec, data_vec_len))
				return false;

		if (! digest_final(&ctx, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	if (mdlen != sizeof result)
		return false;

	return true;
}

static bool
digest_testsuite_run_sha2_512(void)
{
	unsigned char result[DIGEST_MDLEN_SHA2_512];

	size_t mdlen = sizeof result;

	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char vector[] = {
			0xCFU, 0x83U, 0xE1U, 0x35U, 0x7EU, 0xEFU, 0xB8U, 0xBDU,
			0xF1U, 0x54U, 0x28U, 0x50U, 0xD6U, 0x6DU, 0x80U, 0x07U,
			0xD6U, 0x20U, 0xE4U, 0x05U, 0x0BU, 0x57U, 0x15U, 0xDCU,
			0x83U, 0xF4U, 0xA9U, 0x21U, 0xD3U, 0x6CU, 0xE9U, 0xCEU,
			0x47U, 0xD0U, 0xD1U, 0x3CU, 0x5DU, 0x85U, 0xF2U, 0xB0U,
			0xFFU, 0x83U, 0x18U, 0xD2U, 0x87U, 0x7EU, 0xECU, 0x2FU,
			0x63U, 0xB9U, 0x31U, 0xBDU, 0x47U, 0x41U, 0x7AU, 0x81U,
			0xA5U, 0x38U, 0x32U, 0x7AU, 0xF9U, 0x27U, 0xDAU, 0x3EU,
		};

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA2_512, NULL, 0, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const char data[3] = "abc";

		static const unsigned char vector[] = {
			0xDDU, 0xAFU, 0x35U, 0xA1U, 0x93U, 0x61U, 0x7AU, 0xBAU,
			0xCCU, 0x41U, 0x73U, 0x49U, 0xAEU, 0x20U, 0x41U, 0x31U,
			0x12U, 0xE6U, 0xFAU, 0x4EU, 0x89U, 0xA9U, 0x7EU, 0xA2U,
			0x0AU, 0x9EU, 0xEEU, 0xE6U, 0x4BU, 0x55U, 0xD3U, 0x9AU,
			0x21U, 0x92U, 0x99U, 0x2AU, 0x27U, 0x4FU, 0xC1U, 0xA8U,
			0x36U, 0xBAU, 0x3CU, 0x23U, 0xA3U, 0xFEU, 0xEBU, 0xBDU,
			0x45U, 0x4DU, 0x44U, 0x23U, 0x64U, 0x3CU, 0xE8U, 0x0EU,
			0x2AU, 0x9AU, 0xC9U, 0x4FU, 0xA5U, 0x4CU, 0xA4U, 0x9FU,
		};

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA2_512, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const char data[56] = ""
		  "abcdbcdecdefdefgefghfghighij"
		  "hijkijkljklmklmnlmnomnopnopq";

		static const unsigned char vector[] = {
			0x20U, 0x4AU, 0x8FU, 0xC6U, 0xDDU, 0xA8U, 0x2FU, 0x0AU,
			0x0CU, 0xEDU, 0x7BU, 0xEBU, 0x8EU, 0x08U, 0xA4U, 0x16U,
			0x57U, 0xC1U, 0x6EU, 0xF4U, 0x68U, 0xB2U, 0x28U, 0xA8U,
			0x27U, 0x9BU, 0xE3U, 0x31U, 0xA7U, 0x03U, 0xC3U, 0x35U,
			0x96U, 0xFDU, 0x15U, 0xC1U, 0x3BU, 0x1BU, 0x07U, 0xF9U,
			0xAAU, 0x1DU, 0x3BU, 0xEAU, 0x57U, 0x78U, 0x9CU, 0xA0U,
			0x31U, 0xADU, 0x85U, 0xC7U, 0xA7U, 0x1DU, 0xD7U, 0x03U,
			0x54U, 0xECU, 0x63U, 0x12U, 0x38U, 0xCAU, 0x34U, 0x45U,
		};

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA2_512, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const char data[112] = ""
		  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
		  "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";

		static const unsigned char vector[] = {
			0x8EU, 0x95U, 0x9BU, 0x75U, 0xDAU, 0xE3U, 0x13U, 0xDAU,
			0x8CU, 0xF4U, 0xF7U, 0x28U, 0x14U, 0xFCU, 0x14U, 0x3FU,
			0x8FU, 0x77U, 0x79U, 0xC6U, 0xEBU, 0x9FU, 0x7FU, 0xA1U,
			0x72U, 0x99U, 0xAEU, 0xADU, 0xB6U, 0x88U, 0x90U, 0x18U,
			0x50U, 0x1DU, 0x28U, 0x9EU, 0x49U, 0x00U, 0xF7U, 0xE4U,
			0x33U, 0x1BU, 0x99U, 0xDEU, 0xC4U, 0xB5U, 0x43U, 0x3AU,
			0xC7U, 0xD3U, 0x29U, 0xEEU, 0xB6U, 0xDDU, 0x26U, 0x54U,
			0x5EU, 0x96U, 0xE5U, 0x5BU, 0x87U, 0x4BU, 0xE9U, 0x09U,
		};

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_oneshot(DIGALG_SHA2_512, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const char data[200] = ""
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
		  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

		static const unsigned char vector[] = {
			0xE7U, 0x18U, 0x48U, 0x3DU, 0x0CU, 0xE7U, 0x69U, 0x64U,
			0x4EU, 0x2EU, 0x42U, 0xC7U, 0xBCU, 0x15U, 0xB4U, 0x63U,
			0x8EU, 0x1FU, 0x98U, 0xB1U, 0x3BU, 0x20U, 0x44U, 0x28U,
			0x56U, 0x32U, 0xA8U, 0x03U, 0xAFU, 0xA9U, 0x73U, 0xEBU,
			0xDEU, 0x0FU, 0xF2U, 0x44U, 0x87U, 0x7EU, 0xA6U, 0x0AU,
			0x4CU, 0xB0U, 0x43U, 0x2CU, 0xE5U, 0x77U, 0xC3U, 0x1BU,
			0xEBU, 0x00U, 0x9CU, 0x5CU, 0x2CU, 0x49U, 0xAAU, 0x2EU,
			0x4EU, 0xADU, 0xB2U, 0x17U, 0xADU, 0x8CU, 0xC0U, 0x9BU,
		};

		const struct digest_vector data_vec[] = {
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
			{ .ptr = data, .len = sizeof data },
		};

		const size_t data_vec_len = (sizeof data_vec) / (sizeof data_vec[0]);

		struct digest_context ctx;

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_init(&ctx, DIGALG_SHA2_512))
			return false;

		for (size_t i = 0; i < 500; i++)
			if (! digest_update_vector(&ctx, data_vec, data_vec_len))
				return false;

		if (! digest_final(&ctx, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	if (mdlen != sizeof result)
		return false;

	return true;
}

static bool
digest_testsuite_run_hmac_md5(void)
{
	unsigned char result[DIGEST_MDLEN_MD5];

	size_t mdlen = sizeof result;

	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char key[] = {
			0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
			0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
		};

		static const char data[8] = "Hi There";

		static const unsigned char vector[] = {
			0x92U, 0x94U, 0x72U, 0x7AU, 0x36U, 0x38U, 0xBBU, 0x1CU,
			0x13U, 0xF4U, 0x8EU, 0xF8U, 0x15U, 0x8BU, 0xFCU, 0x9DU,
		};

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_MD5, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const char key[4] = "Jefe";

		static const char data[28] = "what do ya want for nothing?";

		static const unsigned char vector[] = {
			0x75U, 0x0CU, 0x78U, 0x3EU, 0x6AU, 0xB0U, 0xB5U, 0x03U,
			0xEAU, 0xA8U, 0x6EU, 0x31U, 0x0AU, 0x5DU, 0xB7U, 0x38U,
		};

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_MD5, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
		};

		static const unsigned char data[] = {
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU,
		};

		static const unsigned char vector[] = {
			0x56U, 0xBEU, 0x34U, 0x52U, 0x1DU, 0x14U, 0x4CU, 0x88U,
			0xDBU, 0xB8U, 0xC7U, 0x33U, 0xF0U, 0xE8U, 0xB3U, 0xF6U,
		};

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_MD5, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const unsigned char key[] = {
			0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U,
			0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU, 0x10U,
			0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U, 0x18U,
			0x19U,
		};

		static const unsigned char data[] = {
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU,
		};

		static const unsigned char vector[] = {
			0x69U, 0x7EU, 0xAFU, 0x0AU, 0xCAU, 0x3AU, 0x3AU, 0xEAU,
			0x3AU, 0x75U, 0x16U, 0x47U, 0x46U, 0xFFU, 0xAAU, 0x79U,
		};

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_MD5, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const unsigned char key[] = {
			0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU,
			0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU,
		};

		static const char data[20] = "Test With Truncation";

		static const unsigned char vector[] = {
			0x56U, 0x46U, 0x1EU, 0xF2U, 0x34U, 0x2EU, 0xDCU, 0x00U,
			0xF9U, 0xBAU, 0xB9U, 0x95U, 0x69U, 0x0EU, 0xFDU, 0x4CU,
		};

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_MD5, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
		};

		static const char data[54] = ""
		  "Test Using Larger Than Block-Size Key "
		  "- Hash Key First";

		static const unsigned char vector[] = {
			0x6BU, 0x1AU, 0xB7U, 0xFEU, 0x4BU, 0xD7U, 0xBFU, 0x8FU,
			0x0BU, 0x62U, 0xE6U, 0xCEU, 0x61U, 0xB9U, 0xD0U, 0xCDU,
		};

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_MD5, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
		};

		static const char data[73] = ""
		  "Test Using Larger Than Block-Size Key "
		  "and Larger Than One Block-Size Data";

		static const unsigned char vector[] = {
			0x6FU, 0x63U, 0x0FU, 0xADU, 0x67U, 0xCDU, 0xA0U, 0xEEU,
			0x1FU, 0xB1U, 0xF5U, 0x62U, 0xDBU, 0x3AU, 0xA5U, 0x3EU,
		};

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_MD5, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	if (mdlen != sizeof result)
		return false;

	return true;
}

static bool
digest_testsuite_run_hmac_sha1(void)
{
	unsigned char result[DIGEST_MDLEN_SHA1];

	size_t mdlen = sizeof result;

	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char key[] = {
			0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
			0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
			0x0BU, 0x0BU, 0x0BU, 0x0BU,
		};

		static const char data[8] = "Hi There";

		static const unsigned char vector[] = {
			0xB6U, 0x17U, 0x31U, 0x86U, 0x55U, 0x05U, 0x72U, 0x64U,
			0xE2U, 0x8BU, 0xC0U, 0xB6U, 0xFBU, 0x37U, 0x8CU, 0x8EU,
			0xF1U, 0x46U, 0xBEU, 0x00U,
		};

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA1, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const char key[4] = "Jefe";

		static const char data[28] = "what do ya want for nothing?";

		static const unsigned char vector[] = {
			0xEFU, 0xFCU, 0xDFU, 0x6AU, 0xE5U, 0xEBU, 0x2FU, 0xA2U,
			0xD2U, 0x74U, 0x16U, 0xD5U, 0xF1U, 0x84U, 0xDFU, 0x9CU,
			0x25U, 0x9AU, 0x7CU, 0x79U,
		};

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA1, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU,
		};

		static const unsigned char data[] = {
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU,
		};

		static const unsigned char vector[] = {
			0x12U, 0x5DU, 0x73U, 0x42U, 0xB9U, 0xACU, 0x11U, 0xCDU,
			0x91U, 0xA3U, 0x9AU, 0xF4U, 0x8AU, 0xA1U, 0x7BU, 0x4FU,
			0x63U, 0xF1U, 0x75U, 0xD3U,
		};

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA1, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const unsigned char key[] = {
			0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U,
			0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU, 0x10U,
			0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U, 0x18U,
			0x19U,
		};

		static const unsigned char data[] = {
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU,
		};

		static const unsigned char vector[] = {
			0x4CU, 0x90U, 0x07U, 0xF4U, 0x02U, 0x62U, 0x50U, 0xC6U,
			0xBCU, 0x84U, 0x14U, 0xF9U, 0xBFU, 0x50U, 0xC8U, 0x6CU,
			0x2DU, 0x72U, 0x35U, 0xDAU,
		};

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA1, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const unsigned char key[] = {
			0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU,
			0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU,
			0x0CU, 0x0CU, 0x0CU, 0x0CU,
		};

		static const char data[20] = "Test With Truncation";

		static const unsigned char vector[] = {
			0x4CU, 0x1AU, 0x03U, 0x42U, 0x4BU, 0x55U, 0xE0U, 0x7FU,
			0xE7U, 0xF2U, 0x7BU, 0xE1U, 0xD5U, 0x8BU, 0xB9U, 0x32U,
			0x4AU, 0x9AU, 0x5AU, 0x04U,
		};

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA1, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
		};

		static const char data[54] = ""
		  "Test Using Larger Than Block-Size Key "
		  "- Hash Key First";

		static const unsigned char vector[] = {
			0xAAU, 0x4AU, 0xE5U, 0xE1U, 0x52U, 0x72U, 0xD0U, 0x0EU,
			0x95U, 0x70U, 0x56U, 0x37U, 0xCEU, 0x8AU, 0x3BU, 0x55U,
			0xEDU, 0x40U, 0x21U, 0x12U,
		};

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA1, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
		};

		static const char data[73] = ""
		  "Test Using Larger Than Block-Size Key "
		  "and Larger Than One Block-Size Data";

		static const unsigned char vector[] = {
			0xE8U, 0xE9U, 0x9DU, 0x0FU, 0x45U, 0x23U, 0x7DU, 0x78U,
			0x6DU, 0x6BU, 0xBAU, 0xA7U, 0x96U, 0x5CU, 0x78U, 0x08U,
			0xBBU, 0xFFU, 0x1AU, 0x91U,
		};

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA1, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	if (mdlen != sizeof result)
		return false;

	return true;
}

static bool
digest_testsuite_run_hmac_sha2_256(void)
{
	unsigned char result[DIGEST_MDLEN_SHA2_256];

	size_t mdlen = sizeof result;

	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char key[] = {
			0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
			0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
			0x0BU, 0x0BU, 0x0BU, 0x0BU,
		};

		static const char data[8] = "Hi There";

		static const unsigned char vector[] = {
			0xB0U, 0x34U, 0x4CU, 0x61U, 0xD8U, 0xDBU, 0x38U, 0x53U,
			0x5CU, 0xA8U, 0xAFU, 0xCEU, 0xAFU, 0x0BU, 0xF1U, 0x2BU,
			0x88U, 0x1DU, 0xC2U, 0x00U, 0xC9U, 0x83U, 0x3DU, 0xA7U,
			0x26U, 0xE9U, 0x37U, 0x6CU, 0x2EU, 0x32U, 0xCFU, 0xF7U,
		};

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_256, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const char key[4] = "Jefe";

		static const char data[28] = "what do ya want for nothing?";

		static const unsigned char vector[] = {
			0x5BU, 0xDCU, 0xC1U, 0x46U, 0xBFU, 0x60U, 0x75U, 0x4EU,
			0x6AU, 0x04U, 0x24U, 0x26U, 0x08U, 0x95U, 0x75U, 0xC7U,
			0x5AU, 0x00U, 0x3FU, 0x08U, 0x9DU, 0x27U, 0x39U, 0x83U,
			0x9DU, 0xECU, 0x58U, 0xB9U, 0x64U, 0xECU, 0x38U, 0x43U,
		};

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_256, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU,
		};

		static const unsigned char data[] = {
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU,
		};

		static const unsigned char vector[] = {
			0x77U, 0x3EU, 0xA9U, 0x1EU, 0x36U, 0x80U, 0x0EU, 0x46U,
			0x85U, 0x4DU, 0xB8U, 0xEBU, 0xD0U, 0x91U, 0x81U, 0xA7U,
			0x29U, 0x59U, 0x09U, 0x8BU, 0x3EU, 0xF8U, 0xC1U, 0x22U,
			0xD9U, 0x63U, 0x55U, 0x14U, 0xCEU, 0xD5U, 0x65U, 0xFEU,
		};

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_256, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const unsigned char key[] = {
			0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U,
			0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU, 0x10U,
			0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U, 0x18U,
			0x19U,
		};

		static const unsigned char data[] = {
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU,
		};

		static const unsigned char vector[] = {
			0x82U, 0x55U, 0x8AU, 0x38U, 0x9AU, 0x44U, 0x3CU, 0x0EU,
			0xA4U, 0xCCU, 0x81U, 0x98U, 0x99U, 0xF2U, 0x08U, 0x3AU,
			0x85U, 0xF0U, 0xFAU, 0xA3U, 0xE5U, 0x78U, 0xF8U, 0x07U,
			0x7AU, 0x2EU, 0x3FU, 0xF4U, 0x67U, 0x29U, 0x66U, 0x5BU,
		};

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_256, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const unsigned char key[] = {
			0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU,
			0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU,
			0x0CU, 0x0CU, 0x0CU, 0x0CU,
		};

		static const char data[20] = "Test With Truncation";

		static const unsigned char vector[] = {
			0xA3U, 0xB6U, 0x16U, 0x74U, 0x73U, 0x10U, 0x0EU, 0xE0U,
			0x6EU, 0x0CU, 0x79U, 0x6CU, 0x29U, 0x55U, 0x55U, 0x2BU,
		};

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_256, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU,
		};

		static const char data[54] = ""
		  "Test Using Larger Than Block-Size Key "
		  "- Hash Key First";

		static const unsigned char vector[] = {
			0x60U, 0xE4U, 0x31U, 0x59U, 0x1EU, 0xE0U, 0xB6U, 0x7FU,
			0x0DU, 0x8AU, 0x26U, 0xAAU, 0xCBU, 0xF5U, 0xB7U, 0x7FU,
			0x8EU, 0x0BU, 0xC6U, 0x21U, 0x37U, 0x28U, 0xC5U, 0x14U,
			0x05U, 0x46U, 0x04U, 0x0FU, 0x0EU, 0xE3U, 0x7FU, 0x54U,
		};

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_256, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU,
		};

		static const char data[152] = ""
		  "This is a test using a larger than block-size key"
		  " and a larger than block-size data. The key needs"
		  " to be hashed before being used by the HMAC algor"
		  "ithm.";

		static const unsigned char vector[] = {
			0x9BU, 0x09U, 0xFFU, 0xA7U, 0x1BU, 0x94U, 0x2FU, 0xCBU,
			0x27U, 0x63U, 0x5FU, 0xBCU, 0xD5U, 0xB0U, 0xE9U, 0x44U,
			0xBFU, 0xDCU, 0x63U, 0x64U, 0x4FU, 0x07U, 0x13U, 0x93U,
			0x8AU, 0x7FU, 0x51U, 0x53U, 0x5CU, 0x3AU, 0x35U, 0xE2U,
		};

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_256, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	if (mdlen != sizeof result)
		return false;

	return true;
}

static bool
digest_testsuite_run_hmac_sha2_512(void)
{
	unsigned char result[DIGEST_MDLEN_SHA2_512];

	size_t mdlen = sizeof result;

	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char key[] = {
			0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
			0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU, 0x0BU,
			0x0BU, 0x0BU, 0x0BU, 0x0BU,
		};

		static const char data[8] = "Hi There";

		static const unsigned char vector[] = {
			0x87U, 0xAAU, 0x7CU, 0xDEU, 0xA5U, 0xEFU, 0x61U, 0x9DU,
			0x4FU, 0xF0U, 0xB4U, 0x24U, 0x1AU, 0x1DU, 0x6CU, 0xB0U,
			0x23U, 0x79U, 0xF4U, 0xE2U, 0xCEU, 0x4EU, 0xC2U, 0x78U,
			0x7AU, 0xD0U, 0xB3U, 0x05U, 0x45U, 0xE1U, 0x7CU, 0xDEU,
			0xDAU, 0xA8U, 0x33U, 0xB7U, 0xD6U, 0xB8U, 0xA7U, 0x02U,
			0x03U, 0x8BU, 0x27U, 0x4EU, 0xAEU, 0xA3U, 0xF4U, 0xE4U,
			0xBEU, 0x9DU, 0x91U, 0x4EU, 0xEBU, 0x61U, 0xF1U, 0x70U,
			0x2EU, 0x69U, 0x6CU, 0x20U, 0x3AU, 0x12U, 0x68U, 0x54U,
		};

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_512, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const char key[4] = "Jefe";

		static const char data[28] = "what do ya want for nothing?";

		static const unsigned char vector[] = {
			0x16U, 0x4BU, 0x7AU, 0x7BU, 0xFCU, 0xF8U, 0x19U, 0xE2U,
			0xE3U, 0x95U, 0xFBU, 0xE7U, 0x3BU, 0x56U, 0xE0U, 0xA3U,
			0x87U, 0xBDU, 0x64U, 0x22U, 0x2EU, 0x83U, 0x1FU, 0xD6U,
			0x10U, 0x27U, 0x0CU, 0xD7U, 0xEAU, 0x25U, 0x05U, 0x54U,
			0x97U, 0x58U, 0xBFU, 0x75U, 0xC0U, 0x5AU, 0x99U, 0x4AU,
			0x6DU, 0x03U, 0x4FU, 0x65U, 0xF8U, 0xF0U, 0xE6U, 0xFDU,
			0xCAU, 0xEAU, 0xB1U, 0xA3U, 0x4DU, 0x4AU, 0x6BU, 0x4BU,
			0x63U, 0x6EU, 0x07U, 0x0AU, 0x38U, 0xBCU, 0xE7U, 0x37U,
		};

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_512, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU,
		};

		static const unsigned char data[] = {
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU, 0xDDU,
			0xDDU, 0xDDU,
		};

		static const unsigned char vector[] = {
			0xFAU, 0x73U, 0xB0U, 0x08U, 0x9DU, 0x56U, 0xA2U, 0x84U,
			0xEFU, 0xB0U, 0xF0U, 0x75U, 0x6CU, 0x89U, 0x0BU, 0xE9U,
			0xB1U, 0xB5U, 0xDBU, 0xDDU, 0x8EU, 0xE8U, 0x1AU, 0x36U,
			0x55U, 0xF8U, 0x3EU, 0x33U, 0xB2U, 0x27U, 0x9DU, 0x39U,
			0xBFU, 0x3EU, 0x84U, 0x82U, 0x79U, 0xA7U, 0x22U, 0xC8U,
			0x06U, 0xB4U, 0x85U, 0xA4U, 0x7EU, 0x67U, 0xC8U, 0x07U,
			0xB9U, 0x46U, 0xA3U, 0x37U, 0xBEU, 0xE8U, 0x94U, 0x26U,
			0x74U, 0x27U, 0x88U, 0x59U, 0xE1U, 0x32U, 0x92U, 0xFBU,
		};

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_512, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const unsigned char key[] = {
			0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U,
			0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU, 0x10U,
			0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U, 0x18U,
			0x19U,
		};

		static const unsigned char data[] = {
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU, 0xCDU,
			0xCDU, 0xCDU,
		};

		static const unsigned char vector[] = {
			0xB0U, 0xBAU, 0x46U, 0x56U, 0x37U, 0x45U, 0x8CU, 0x69U,
			0x90U, 0xE5U, 0xA8U, 0xC5U, 0xF6U, 0x1DU, 0x4AU, 0xF7U,
			0xE5U, 0x76U, 0xD9U, 0x7FU, 0xF9U, 0x4BU, 0x87U, 0x2DU,
			0xE7U, 0x6FU, 0x80U, 0x50U, 0x36U, 0x1EU, 0xE3U, 0xDBU,
			0xA9U, 0x1CU, 0xA5U, 0xC1U, 0x1AU, 0xA2U, 0x5EU, 0xB4U,
			0xD6U, 0x79U, 0x27U, 0x5CU, 0xC5U, 0x78U, 0x80U, 0x63U,
			0xA5U, 0xF1U, 0x97U, 0x41U, 0x12U, 0x0CU, 0x4FU, 0x2DU,
			0xE2U, 0xADU, 0xEBU, 0xEBU, 0x10U, 0xA2U, 0x98U, 0xDDU,
		};

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_512, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const unsigned char key[] = {
			0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU,
			0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU, 0x0CU,
			0x0CU, 0x0CU, 0x0CU, 0x0CU,
		};

		static const char data[20] = "Test With Truncation";

		static const unsigned char vector[] = {
			0x41U, 0x5FU, 0xADU, 0x62U, 0x71U, 0x58U, 0x0AU, 0x53U,
			0x1DU, 0x41U, 0x79U, 0xBCU, 0x89U, 0x1DU, 0x87U, 0xA6U,
		};

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_512, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU,
		};

		static const char data[54] = ""
		  "Test Using Larger Than Block-Size Key "
		  "- Hash Key First";

		static const unsigned char vector[] = {
			0x80U, 0xB2U, 0x42U, 0x63U, 0xC7U, 0xC1U, 0xA3U, 0xEBU,
			0xB7U, 0x14U, 0x93U, 0xC1U, 0xDDU, 0x7BU, 0xE8U, 0xB4U,
			0x9BU, 0x46U, 0xD1U, 0xF4U, 0x1BU, 0x4AU, 0xEEU, 0xC1U,
			0x12U, 0x1BU, 0x01U, 0x37U, 0x83U, 0xF8U, 0xF3U, 0x52U,
			0x6BU, 0x56U, 0xD0U, 0x37U, 0xE0U, 0x5FU, 0x25U, 0x98U,
			0xBDU, 0x0FU, 0xD2U, 0x21U, 0x5DU, 0x6AU, 0x1EU, 0x52U,
			0x95U, 0xE6U, 0x4FU, 0x73U, 0xF6U, 0x3FU, 0x0AU, 0xECU,
			0x8BU, 0x91U, 0x5AU, 0x98U, 0x5DU, 0x78U, 0x65U, 0x98U,
		};

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_512, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const unsigned char key[] = {
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU,
			0xAAU, 0xAAU, 0xAAU,
		};

		static const char data[152] = ""
		  "This is a test using a larger than block-size key"
		  " and a larger than block-size data. The key needs"
		  " to be hashed before being used by the HMAC algor"
		  "ithm.";

		static const unsigned char vector[] = {
			0xE3U, 0x7BU, 0x6AU, 0x77U, 0x5DU, 0xC8U, 0x7DU, 0xBAU,
			0xA4U, 0xDFU, 0xA9U, 0xF9U, 0x6EU, 0x5EU, 0x3FU, 0xFDU,
			0xDEU, 0xBDU, 0x71U, 0xF8U, 0x86U, 0x72U, 0x89U, 0x86U,
			0x5DU, 0xF5U, 0xA3U, 0x2DU, 0x20U, 0xCDU, 0xC9U, 0x44U,
			0xB6U, 0x02U, 0x2CU, 0xACU, 0x3CU, 0x49U, 0x82U, 0xB1U,
			0x0DU, 0x5EU, 0xEBU, 0x55U, 0xC3U, 0xE4U, 0xDEU, 0x15U,
			0x13U, 0x46U, 0x76U, 0xFBU, 0x6DU, 0xE0U, 0x44U, 0x60U,
			0x65U, 0xC9U, 0x74U, 0x40U, 0xFAU, 0x8CU, 0x6AU, 0x58U,
		};

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_oneshot_hmac(DIGALG_SHA2_512, key, sizeof key, data, sizeof data, result, &mdlen))
			return false;

		if (memcmp(result, vector, sizeof vector) != 0)
			return false;
	}

	if (mdlen != sizeof result)
		return false;

	return true;
}

static bool
digest_testsuite_run_hkdf_md5(void)
{
	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char ikm[] = {
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		};

		static const unsigned char salt[] = {
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		};

		static const unsigned char info[] = {
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
		};

		static const unsigned char prk[] = {
			0x3AU, 0x3EU, 0x61U, 0x4EU, 0x62U, 0xC0U, 0x9CU, 0xCCU,
			0x73U, 0xAAU, 0x74U, 0xAFU, 0x4CU, 0x9BU, 0x4CU, 0x7EU,
		};

		static const unsigned char okm[] = {
			0x2BU, 0xA0U, 0x8AU, 0x06U, 0x3BU, 0xC4U, 0xB1U, 0xCDU,
			0x5FU, 0x53U, 0x07U, 0x47U, 0x0EU, 0x35U, 0x4DU, 0x68U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_MD5, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 1: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 1: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_MD5, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 1: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 1: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const unsigned char ikm[] = {
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		};

		static const unsigned char salt[] = {
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
		};

		static const unsigned char prk[] = {
			0xE7U, 0x12U, 0x98U, 0xE7U, 0x52U, 0x88U, 0x2DU, 0x63U,
			0x5DU, 0x6DU, 0x65U, 0xCEU, 0xE5U, 0xBCU, 0x2DU, 0x58U,
		};

		static const unsigned char okm[] = {
			0x21U, 0xA5U, 0xCDU, 0x26U, 0xF8U, 0x4FU, 0xEFU, 0x0FU,
			0x23U, 0xD5U, 0xC6U, 0xCEU, 0xB3U, 0x4EU, 0xA7U, 0x0DU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_MD5, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 2: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 2: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_MD5, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 2: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 2: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const unsigned char ikm[] = {
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		};

		static const unsigned char info[] = {
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
		};

		static const unsigned char prk[] = {
			0xF1U, 0xDBU, 0xBDU, 0xB5U, 0x8AU, 0x19U, 0xCFU, 0x50U,
			0x22U, 0xD9U, 0x60U, 0xC8U, 0x78U, 0x77U, 0xB0U, 0x07U,
		};

		static const unsigned char okm[] = {
			0x5DU, 0x76U, 0x5EU, 0xA7U, 0x04U, 0xE8U, 0x4BU, 0xDCU,
			0xB9U, 0xF0U, 0x52U, 0x8FU, 0xC5U, 0xF6U, 0x39U, 0x60U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_MD5, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 3: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 3: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_MD5, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 3: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 3: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const unsigned char ikm[] = {
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
		};

		static const unsigned char prk[] = {
			0xC0U, 0x7DU, 0x54U, 0xA1U, 0x3AU, 0x97U, 0x4DU, 0x81U,
			0xCFU, 0xD7U, 0x87U, 0x3CU, 0x9FU, 0x70U, 0xCFU, 0x3FU,
		};

		static const unsigned char okm[] = {
			0x59U, 0x8CU, 0x89U, 0x56U, 0x15U, 0xBFU, 0xCFU, 0x03U,
			0x0BU, 0x19U, 0xA2U, 0x76U, 0xC6U, 0x66U, 0x47U, 0xA9U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_MD5, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 4: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 4: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_MD5, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 4: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 4: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const unsigned char ikm[] = {
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		};

		static const unsigned char salt[] = {
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
		};

		static const unsigned char info[] = {
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
		};

		static const unsigned char prk[] = {
			0xE8U, 0xC6U, 0x98U, 0xEFU, 0xCBU, 0x36U, 0x16U, 0x46U,
			0x1AU, 0xF7U, 0xEFU, 0x27U, 0xD4U, 0x63U, 0xBCU, 0xB0U,
		};

		static const unsigned char okm[] = {
			0x46U, 0x6DU, 0x10U, 0x73U, 0xEDU, 0xF7U, 0x3CU, 0x65U,
			0xECU, 0xA6U, 0xBFU, 0x48U, 0x82U, 0x8FU, 0x8EU, 0x1BU,
			0xDDU, 0x60U, 0x13U, 0xEDU, 0xF6U, 0x3BU, 0xBCU, 0xF5U,
			0x46U, 0xCEU, 0xBCU, 0x29U, 0xD2U, 0x7EU, 0x7AU, 0xF4U,
			0x47U, 0xCDU, 0xBEU, 0x74U, 0x67U, 0x47U, 0xFFU, 0xA0U,
			0x22U, 0x0AU, 0x4CU, 0x71U, 0x29U, 0xB8U, 0xE8U, 0xD3U,
			0x3BU, 0xABU, 0xE2U, 0xFAU, 0xB4U, 0xB7U, 0xA9U, 0x51U,
			0xBFU, 0x1CU, 0x37U, 0x47U, 0xF1U, 0xDBU, 0x14U, 0xD3U,
			0x6FU, 0x6CU, 0xD7U, 0xE1U, 0xC0U, 0xB1U, 0xCAU, 0x74U,
			0x96U, 0xD9U, 0x53U, 0xD7U, 0x28U, 0xC7U, 0x91U, 0x8AU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_MD5, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 5: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 5: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_MD5, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 5: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 5: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const unsigned char ikm[] = {
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		};

		static const unsigned char salt[] = {
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
		};

		static const unsigned char prk[] = {
			0xE4U, 0xC4U, 0xCBU, 0x90U, 0x82U, 0x93U, 0xBAU, 0xE3U,
			0xFDU, 0x32U, 0x62U, 0x0BU, 0x3DU, 0xACU, 0x1BU, 0xC9U,
		};

		static const unsigned char okm[] = {
			0xBFU, 0x61U, 0xC8U, 0x37U, 0xAFU, 0x9BU, 0x1AU, 0xB4U,
			0x88U, 0xB6U, 0x9AU, 0x73U, 0xFEU, 0xC7U, 0xA7U, 0x18U,
			0xDCU, 0x74U, 0xDCU, 0xF7U, 0x02U, 0xBBU, 0xE1U, 0x8AU,
			0x1AU, 0x92U, 0x9CU, 0xB6U, 0x68U, 0xE8U, 0x57U, 0xBAU,
			0xF0U, 0xECU, 0x0CU, 0x9DU, 0xE4U, 0x11U, 0xCEU, 0xFDU,
			0x66U, 0xB3U, 0xCDU, 0x5EU, 0x7CU, 0x75U, 0x74U, 0xC7U,
			0x40U, 0x93U, 0xCFU, 0xB1U, 0x57U, 0xEDU, 0x97U, 0x4CU,
			0x5DU, 0xFAU, 0xFCU, 0xFDU, 0x3AU, 0x93U, 0x2DU, 0xE8U,
			0xC0U, 0xE2U, 0x3AU, 0x1DU, 0xBAU, 0x70U, 0x69U, 0xC6U,
			0x6AU, 0x7AU, 0x75U, 0xAEU, 0x63U, 0xA8U, 0xFFU, 0xE7U,
			0xFAU, 0x36U, 0xA0U, 0x32U, 0x1BU, 0x45U, 0xB8U, 0x06U,
			0x92U, 0x9DU, 0xA4U, 0xD7U, 0xC0U, 0xA4U, 0xE1U, 0x4EU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_MD5, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 6: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 6: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_MD5, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 6: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 6: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const unsigned char ikm[] = {
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		};

		static const unsigned char info[] = {
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
		};

		static const unsigned char prk[] = {
			0x10U, 0x19U, 0x22U, 0xA8U, 0x2FU, 0x5CU, 0xC2U, 0x66U,
			0x12U, 0x51U, 0x94U, 0x1CU, 0xBFU, 0xF4U, 0x55U, 0x2BU,
		};

		static const unsigned char okm[] = {
			0xC9U, 0xF9U, 0xAAU, 0x60U, 0xD6U, 0x9AU, 0x9DU, 0xE8U,
			0xE0U, 0x52U, 0xBAU, 0x67U, 0x83U, 0x33U, 0x29U, 0x79U,
			0x01U, 0x95U, 0x17U, 0x66U, 0xA3U, 0x33U, 0x83U, 0x43U,
			0x05U, 0x35U, 0x56U, 0xC8U, 0x2CU, 0xF6U, 0xA5U, 0x03U,
			0xEAU, 0x3EU, 0x50U, 0x68U, 0xDAU, 0x1DU, 0x13U, 0xE7U,
			0x80U, 0x28U, 0x9EU, 0x8AU, 0x7BU, 0x91U, 0x01U, 0x1DU,
			0xF4U, 0xCEU, 0xC9U, 0x9DU, 0x5BU, 0x1FU, 0x21U, 0x0DU,
			0x6DU, 0xCEU, 0x0FU, 0x73U, 0xBBU, 0xCDU, 0x0FU, 0xBAU,
			0xB5U, 0x66U, 0x14U, 0x83U, 0x2CU, 0x9FU, 0x2FU, 0xF0U,
			0xD8U, 0x56U, 0x7AU, 0xADU, 0xBBU, 0xEEU, 0xCEU, 0xCBU,
			0xA8U, 0x64U, 0x4EU, 0x3EU, 0x69U, 0x79U, 0x24U, 0x0BU,
			0x1FU, 0x7BU, 0x16U, 0x38U, 0xF7U, 0x28U, 0x49U, 0xEBU,
			0x50U, 0x29U, 0x9DU, 0x74U, 0xBBU, 0xCFU, 0x2CU, 0xA1U,
			0xC7U, 0xE4U, 0x5EU, 0xD9U, 0x48U, 0x1AU, 0xC9U, 0xFCU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_MD5, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 7: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 7: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_MD5, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 7: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 7: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 8 *
		 *****************/

		static const unsigned char ikm[] = {
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		};

		static const unsigned char prk[] = {
			0x28U, 0x03U, 0xE4U, 0x39U, 0x58U, 0x94U, 0x86U, 0xC0U,
			0xAEU, 0xA4U, 0x43U, 0x01U, 0x11U, 0x49U, 0xE7U, 0x25U,
		};

		static const unsigned char okm[] = {
			0xD3U, 0xB8U, 0x02U, 0xDDU, 0x0FU, 0x77U, 0xA7U, 0xB3U,
			0xCEU, 0x03U, 0x8EU, 0x0DU, 0x6FU, 0xD4U, 0x17U, 0x45U,
			0xEBU, 0xBEU, 0x95U, 0x5EU, 0x39U, 0xAFU, 0x27U, 0xBEU,
			0xD2U, 0x6FU, 0x36U, 0xD9U, 0xADU, 0xA0U, 0x44U, 0xF9U,
			0xE8U, 0x04U, 0x39U, 0xABU, 0xE3U, 0x7EU, 0x21U, 0x09U,
			0x3BU, 0xDFU, 0x1AU, 0xF1U, 0x68U, 0x6DU, 0x42U, 0x79U,
			0x2BU, 0x4FU, 0xDAU, 0x22U, 0x68U, 0x3AU, 0xDDU, 0xB9U,
			0x02U, 0xDFU, 0xF6U, 0x11U, 0xD1U, 0x04U, 0x39U, 0xDFU,
			0x8AU, 0x27U, 0x71U, 0x8EU, 0xFEU, 0xB7U, 0xE6U, 0x56U,
			0x64U, 0xA0U, 0x18U, 0xF4U, 0x5FU, 0x8FU, 0x9BU, 0x0AU,
			0x91U, 0x1CU, 0xF8U, 0x33U, 0x28U, 0x40U, 0xA1U, 0xBEU,
			0x4AU, 0x7FU, 0x7EU, 0xC6U, 0x27U, 0xBEU, 0xD9U, 0x65U,
			0x69U, 0xD8U, 0x90U, 0x93U, 0x7AU, 0x6EU, 0x31U, 0x6BU,
			0x73U, 0x2CU, 0xF2U, 0x11U, 0x3CU, 0x1DU, 0x83U, 0x44U,
			0x9CU, 0xD0U, 0x7BU, 0x00U, 0x66U, 0x08U, 0xF6U, 0x9FU,
			0x0EU, 0x98U, 0x5EU, 0x44U, 0x63U, 0xA0U, 0x6AU, 0x2BU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 8", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_MD5, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 8: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 8: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_MD5, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 8: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 8: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	return true;
}

static bool
digest_testsuite_run_hkdf_sha1(void)
{
	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char ikm[] = {
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U,
		};

		static const unsigned char salt[] = {
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U,
		};

		static const unsigned char info[] = {
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U,
		};

		static const unsigned char prk[] = {
			0xCAU, 0x1FU, 0xF0U, 0x43U, 0xCCU, 0x95U, 0x1DU, 0xA2U,
			0x8FU, 0xD4U, 0x56U, 0xD4U, 0x50U, 0x28U, 0x04U, 0xBAU,
			0x09U, 0x15U, 0xC1U, 0xDAU,
		};

		static const unsigned char okm[] = {
			0x0BU, 0x54U, 0xF8U, 0x2CU, 0x6DU, 0x75U, 0x4DU, 0x17U,
			0xC5U, 0x8EU, 0x71U, 0x47U, 0x16U, 0xDAU, 0x7BU, 0xF5U,
			0xD6U, 0x97U, 0xBBU, 0x7FU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA1, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 1: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 1: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA1, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 1: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 1: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const unsigned char ikm[] = {
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU,
		};

		static const unsigned char salt[] = {
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
		};

		static const unsigned char prk[] = {
			0xACU, 0x66U, 0xF9U, 0x12U, 0xCBU, 0xD2U, 0x34U, 0x26U,
			0x8CU, 0x64U, 0x57U, 0x7AU, 0x33U, 0x52U, 0x26U, 0x69U,
			0x8DU, 0x2CU, 0x29U, 0x32U,
		};

		static const unsigned char okm[] = {
			0xE1U, 0x2FU, 0xD1U, 0xADU, 0x0CU, 0x24U, 0x93U, 0xF0U,
			0xFCU, 0x2EU, 0xCCU, 0x8BU, 0xADU, 0x05U, 0x4EU, 0x34U,
			0x33U, 0x7FU, 0x42U, 0xA1U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA1, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 2: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 2: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA1, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 2: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 2: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const unsigned char ikm[] = {
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U,
		};

		static const unsigned char info[] = {
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
		};

		static const unsigned char prk[] = {
			0xA0U, 0x57U, 0x6BU, 0xCCU, 0xC7U, 0xE5U, 0x34U, 0xA3U,
			0xDAU, 0xAEU, 0x42U, 0x9BU, 0xBBU, 0x3CU, 0x7EU, 0x3FU,
			0x04U, 0x30U, 0xC1U, 0xF3U,
		};

		static const unsigned char okm[] = {
			0x7EU, 0xB0U, 0x56U, 0x30U, 0xE3U, 0x74U, 0x89U, 0xCBU,
			0x17U, 0x25U, 0xB9U, 0xE9U, 0x07U, 0xC1U, 0x00U, 0x97U,
			0xCDU, 0xB1U, 0x91U, 0x2DU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA1, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 3: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 3: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA1, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 3: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 3: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const unsigned char ikm[] = {
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU,
		};

		static const unsigned char prk[] = {
			0x6FU, 0x5AU, 0x4BU, 0xF4U, 0x45U, 0xB4U, 0x69U, 0xB8U,
			0xA9U, 0x07U, 0xEBU, 0xCFU, 0xB5U, 0xDBU, 0xD6U, 0x41U,
			0xD6U, 0xC9U, 0x76U, 0xA2U,
		};

		static const unsigned char okm[] = {
			0xD4U, 0xF6U, 0x9BU, 0x56U, 0x0CU, 0xD9U, 0xC2U, 0x56U,
			0x15U, 0x34U, 0x85U, 0xE9U, 0x05U, 0x09U, 0x1BU, 0x03U,
			0xBDU, 0x7EU, 0x17U, 0x0EU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA1, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 4: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 4: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA1, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 4: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 4: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const unsigned char ikm[] = {
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		};

		static const unsigned char salt[] = {
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
		};

		static const unsigned char info[] = {
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		};

		static const unsigned char prk[] = {
			0xC8U, 0x06U, 0xA1U, 0x98U, 0xB3U, 0xAAU, 0x15U, 0xC7U,
			0x27U, 0x8BU, 0x6FU, 0xEAU, 0x6CU, 0x63U, 0xA0U, 0x58U,
			0x81U, 0xCDU, 0xFBU, 0xE0U,
		};

		static const unsigned char okm[] = {
			0x77U, 0xCDU, 0x70U, 0x01U, 0x18U, 0x3BU, 0x46U, 0x78U,
			0x7EU, 0x2BU, 0xDDU, 0x42U, 0x59U, 0xA0U, 0x18U, 0x30U,
			0x09U, 0xE3U, 0x92U, 0xE3U, 0x7DU, 0x7AU, 0x0BU, 0x70U,
			0xEDU, 0xDBU, 0xECU, 0x74U, 0xE9U, 0x76U, 0x4EU, 0x17U,
			0x73U, 0xCEU, 0x13U, 0xE6U, 0xDBU, 0xDDU, 0xE8U, 0x60U,
			0x18U, 0xC3U, 0xE8U, 0xBCU, 0x1FU, 0xCAU, 0x5BU, 0x0EU,
			0xB1U, 0x00U, 0xEAU, 0xC1U, 0x07U, 0x2BU, 0x66U, 0xE8U,
			0x18U, 0x57U, 0x04U, 0xF3U, 0x1DU, 0xA6U, 0x89U, 0xF2U,
			0x5BU, 0x77U, 0x98U, 0xA4U, 0x4CU, 0xF6U, 0xEDU, 0x5EU,
			0xF3U, 0xE9U, 0x3CU, 0x6DU, 0x45U, 0x81U, 0x97U, 0xF7U,
			0x6CU, 0xBCU, 0xB1U, 0x67U, 0x16U, 0xC7U, 0x06U, 0x18U,
			0xD9U, 0xD1U, 0x8BU, 0xB7U, 0x9BU, 0x56U, 0x19U, 0x6FU,
			0x62U, 0x35U, 0xA2U, 0xAFU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA1, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 5: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 5: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA1, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 5: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 5: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const unsigned char ikm[] = {
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		};

		static const unsigned char salt[] = {
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
		};

		static const unsigned char prk[] = {
			0x7FU, 0x9DU, 0x19U, 0xD9U, 0x9AU, 0x68U, 0x53U, 0x57U,
			0x8EU, 0x82U, 0x73U, 0xBAU, 0x1EU, 0x54U, 0xF1U, 0x03U,
			0x37U, 0xCDU, 0x1EU, 0x3FU,
		};

		static const unsigned char okm[] = {
			0xDEU, 0x5CU, 0x1EU, 0xBEU, 0xB0U, 0x64U, 0x9AU, 0x91U,
			0xEEU, 0x36U, 0x6CU, 0xB4U, 0xB5U, 0x24U, 0xFFU, 0x4CU,
			0x6FU, 0x4AU, 0x44U, 0xF7U, 0x1DU, 0x19U, 0x5AU, 0x34U,
			0x7AU, 0x9FU, 0x7EU, 0x32U, 0x5BU, 0x57U, 0xF2U, 0x89U,
			0xFAU, 0x26U, 0xD6U, 0xAFU, 0x98U, 0x95U, 0x42U, 0xFFU,
			0xB8U, 0xA2U, 0xCCU, 0x83U, 0x35U, 0x9AU, 0x2BU, 0x49U,
			0x91U, 0x7BU, 0xC0U, 0x86U, 0xB5U, 0x0CU, 0x42U, 0xE5U,
			0xCFU, 0x5AU, 0x0EU, 0xDAU, 0x01U, 0x35U, 0xEDU, 0x81U,
			0x16U, 0x2DU, 0xE1U, 0xDDU, 0x07U, 0xD2U, 0xC8U, 0x40U,
			0xEDU, 0xCAU, 0xA9U, 0x37U, 0x46U, 0xEDU, 0x78U, 0xF3U,
			0xADU, 0x66U, 0xABU, 0x3BU, 0x19U, 0xDBU, 0x3CU, 0x40U,
			0xD4U, 0xE1U, 0x6CU, 0xE4U, 0x52U, 0xC5U, 0xDFU, 0x96U,
			0xA0U, 0x15U, 0xEAU, 0x13U, 0x7DU, 0xD5U, 0x78U, 0x86U,
			0x99U, 0x7FU, 0x13U, 0x0EU, 0x38U, 0x34U, 0x8EU, 0x4AU,
			0xE2U, 0xAFU, 0x29U, 0xDEU, 0x7EU, 0xDFU, 0x2EU, 0xD1U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA1, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 6: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 6: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA1, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 6: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 6: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const unsigned char ikm[] = {
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		};

		static const unsigned char info[] = {
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		};

		static const unsigned char prk[] = {
			0x65U, 0x2CU, 0x21U, 0x71U, 0xC9U, 0xA5U, 0xBBU, 0x69U,
			0x5BU, 0x79U, 0x95U, 0xA5U, 0x75U, 0x75U, 0x36U, 0x2BU,
			0x5FU, 0x37U, 0xE7U, 0x57U,
		};

		static const unsigned char okm[] = {
			0x09U, 0x7DU, 0xBDU, 0x2BU, 0x82U, 0x30U, 0x6EU, 0xB7U,
			0x4AU, 0xF9U, 0x0CU, 0xA7U, 0xDAU, 0x08U, 0x30U, 0x65U,
			0x5EU, 0x8EU, 0x47U, 0x30U, 0x69U, 0xADU, 0x90U, 0x97U,
			0x96U, 0x83U, 0x5DU, 0xDFU, 0x2DU, 0x7EU, 0xF0U, 0x36U,
			0x17U, 0x16U, 0x62U, 0xB0U, 0x16U, 0xBCU, 0x99U, 0x35U,
			0x91U, 0xBBU, 0xB4U, 0x2EU, 0x4DU, 0x12U, 0x4FU, 0x4CU,
			0xE8U, 0x41U, 0xF9U, 0x07U, 0x7DU, 0x52U, 0x3EU, 0x34U,
			0xCAU, 0x10U, 0x4BU, 0x2BU, 0x0BU, 0xA8U, 0xC3U, 0x63U,
			0x8DU, 0x20U, 0x28U, 0x4EU, 0x86U, 0xF1U, 0x80U, 0x4EU,
			0xAAU, 0x61U, 0x04U, 0x07U, 0x86U, 0x2DU, 0x67U, 0x27U,
			0xD6U, 0x7FU, 0x7AU, 0x8DU, 0xBFU, 0xC9U, 0x6EU, 0xCBU,
			0x83U, 0x85U, 0xE8U, 0xC9U, 0x64U, 0xEBU, 0x13U, 0xD2U,
			0x7CU, 0x94U, 0xEDU, 0x4AU, 0x95U, 0xCDU, 0x97U, 0x38U,
			0xDBU, 0xCFU, 0xD5U, 0xF7U, 0xEBU, 0x1EU, 0x2BU, 0x32U,
			0x30U, 0xF3U, 0x1DU, 0x6CU, 0x45U, 0x71U, 0x54U, 0xDAU,
			0xE4U, 0x2DU, 0x3FU, 0x14U, 0xE2U, 0xCBU, 0x38U, 0x4FU,
			0x4DU, 0x2FU, 0x03U, 0xABU, 0x03U, 0xA3U, 0x9DU, 0xC2U,
			0xDEU, 0x5DU, 0x6CU, 0x20U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA1, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 7: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 7: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA1, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 7: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 7: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 8 *
		 *****************/

		static const unsigned char ikm[] = {
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		};

		static const unsigned char prk[] = {
			0xAEU, 0x84U, 0xF4U, 0x7EU, 0x3CU, 0x2EU, 0xEFU, 0x08U,
			0xE8U, 0x45U, 0xBEU, 0xC9U, 0x54U, 0xB6U, 0x4CU, 0xFEU,
			0xA0U, 0x81U, 0x41U, 0xA7U,
		};

		static const unsigned char okm[] = {
			0x79U, 0xADU, 0xF9U, 0xD6U, 0x76U, 0x16U, 0xBAU, 0x70U,
			0x08U, 0xBEU, 0x5AU, 0x2BU, 0x53U, 0x7AU, 0xB3U, 0x4AU,
			0x64U, 0x46U, 0x30U, 0x89U, 0x7AU, 0x38U, 0x6CU, 0x8BU,
			0x02U, 0x7BU, 0xC5U, 0xFBU, 0xABU, 0x3AU, 0x83U, 0x80U,
			0x9AU, 0x08U, 0x42U, 0x56U, 0x2EU, 0x9DU, 0x5CU, 0xD0U,
			0x9AU, 0xB7U, 0x28U, 0x5DU, 0x3DU, 0x3CU, 0x97U, 0x05U,
			0x5FU, 0xF3U, 0x4EU, 0xFCU, 0x32U, 0x2DU, 0x37U, 0xAEU,
			0x47U, 0x37U, 0x39U, 0x7FU, 0xDFU, 0xAEU, 0x34U, 0xA5U,
			0xDFU, 0xCBU, 0xDEU, 0xD3U, 0x61U, 0xD4U, 0xA3U, 0x86U,
			0xB9U, 0x0DU, 0xEAU, 0x25U, 0x0EU, 0x5CU, 0xE6U, 0x58U,
			0x9AU, 0x76U, 0xBCU, 0x84U, 0x99U, 0x30U, 0x60U, 0xD9U,
			0x29U, 0x28U, 0xCAU, 0x6EU, 0x42U, 0xD9U, 0xCFU, 0x1DU,
			0x6AU, 0xB4U, 0x1CU, 0x9AU, 0x80U, 0xCCU, 0xD9U, 0xCCU,
			0x23U, 0x27U, 0xCBU, 0xECU, 0x6EU, 0xE6U, 0xBEU, 0xDFU,
			0xBBU, 0xC7U, 0x0CU, 0x41U, 0x1AU, 0x1CU, 0x62U, 0xC5U,
			0x3BU, 0x21U, 0x00U, 0x0FU, 0x27U, 0xE5U, 0x09U, 0x14U,
			0xBAU, 0x84U, 0x11U, 0x08U, 0x33U, 0xE7U, 0x45U, 0x95U,
			0xECU, 0xE1U, 0x02U, 0x08U, 0xD1U, 0x21U, 0xC5U, 0x55U,
			0xECU, 0xD1U, 0x7CU, 0xE9U, 0xBEU, 0x92U, 0x11U, 0xEDU,
			0x35U, 0xF9U, 0xBEU, 0x5DU, 0x16U, 0xF3U, 0xF2U, 0xD6U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 8", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA1, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 8: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 8: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA1, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 8: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 8: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	return true;
}

static bool
digest_testsuite_run_hkdf_sha2_256(void)
{
	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char ikm[] = {
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		};

		static const unsigned char salt[] = {
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		};

		static const unsigned char info[] = {
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
		};

		static const unsigned char prk[] = {
			0x8DU, 0xCAU, 0xA3U, 0xC5U, 0x07U, 0x5CU, 0x39U, 0xD7U,
			0x95U, 0x19U, 0x48U, 0xC3U, 0xDFU, 0xCDU, 0x80U, 0x7FU,
			0x9AU, 0x3BU, 0x97U, 0x38U, 0xD2U, 0x63U, 0x84U, 0x6EU,
			0x74U, 0x43U, 0x33U, 0x7FU, 0x2EU, 0x31U, 0x6DU, 0x03U,
		};

		static const unsigned char okm[] = {
			0x50U, 0x4EU, 0xD5U, 0xF2U, 0xEDU, 0x34U, 0x0DU, 0xC9U,
			0x7EU, 0xD9U, 0xF1U, 0xDAU, 0xF3U, 0xBDU, 0x95U, 0x67U,
			0x9CU, 0x24U, 0x3FU, 0x32U, 0x25U, 0x84U, 0x61U, 0xAEU,
			0x90U, 0x21U, 0x01U, 0x72U, 0x58U, 0xB2U, 0x97U, 0x7EU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_256, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 1: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 1: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_256, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 1: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 1: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const unsigned char ikm[] = {
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
		};

		static const unsigned char salt[] = {
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
		};

		static const unsigned char prk[] = {
			0xB3U, 0x4BU, 0x9DU, 0xEEU, 0xF1U, 0x22U, 0x29U, 0x70U,
			0x61U, 0x00U, 0x08U, 0x3AU, 0xF9U, 0x6CU, 0xA1U, 0xDEU,
			0x5FU, 0x8CU, 0x2BU, 0x2BU, 0xB5U, 0xF0U, 0x1BU, 0x13U,
			0xA1U, 0x7BU, 0x87U, 0x94U, 0x0AU, 0x4EU, 0x35U, 0x2AU,
		};

		static const unsigned char okm[] = {
			0x95U, 0xF6U, 0x00U, 0x3CU, 0x74U, 0x89U, 0x60U, 0xCFU,
			0xD8U, 0xFEU, 0x9FU, 0x77U, 0xFFU, 0xEEU, 0x78U, 0x81U,
			0x62U, 0x61U, 0xCFU, 0x26U, 0xA8U, 0x79U, 0x94U, 0xE3U,
			0x39U, 0xF9U, 0x29U, 0x7AU, 0xCEU, 0x91U, 0xE6U, 0xBBU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_256, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 2: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 2: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_256, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 2: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 2: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const unsigned char ikm[] = {
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
		};

		static const unsigned char info[] = {
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
		};

		static const unsigned char prk[] = {
			0x45U, 0x27U, 0xFAU, 0x54U, 0x3BU, 0x2DU, 0x04U, 0x54U,
			0x33U, 0xC8U, 0xD7U, 0x09U, 0x1FU, 0x82U, 0x17U, 0x42U,
			0xF7U, 0x99U, 0x16U, 0x49U, 0x1AU, 0x18U, 0x23U, 0xE2U,
			0x1BU, 0xCBU, 0xA7U, 0x02U, 0x35U, 0x08U, 0xC4U, 0x88U,
		};

		static const unsigned char okm[] = {
			0x38U, 0xE0U, 0x42U, 0x06U, 0x9CU, 0x62U, 0x41U, 0x39U,
			0xBEU, 0x82U, 0xC0U, 0x93U, 0x25U, 0x39U, 0x86U, 0xDAU,
			0x81U, 0x36U, 0x0BU, 0x38U, 0x95U, 0xB8U, 0x23U, 0x3AU,
			0x94U, 0x06U, 0x5EU, 0x9DU, 0x68U, 0x6BU, 0x9FU, 0xB5U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_256, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 3: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 3: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_256, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 3: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 3: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const unsigned char ikm[] = {
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
		};

		static const unsigned char prk[] = {
			0x55U, 0xCFU, 0x5BU, 0xF7U, 0x26U, 0x20U, 0x1DU, 0x01U,
			0x4CU, 0xA7U, 0x38U, 0xB0U, 0x86U, 0x8EU, 0xB3U, 0x7CU,
			0x83U, 0xADU, 0xB4U, 0x65U, 0xAEU, 0x5DU, 0x0CU, 0x9DU,
			0x60U, 0x17U, 0xFBU, 0x13U, 0x0EU, 0xB5U, 0x98U, 0x9AU,
		};

		static const unsigned char okm[] = {
			0x44U, 0x0BU, 0xEEU, 0x14U, 0x2EU, 0xFDU, 0x75U, 0x3AU,
			0xF5U, 0x52U, 0x41U, 0x84U, 0x95U, 0x8EU, 0x07U, 0x3CU,
			0x29U, 0xE4U, 0x73U, 0x2EU, 0x86U, 0xCFU, 0xDAU, 0x77U,
			0x4AU, 0x2FU, 0x6FU, 0xC3U, 0xC1U, 0xD0U, 0x57U, 0x57U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_256, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 4: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 4: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_256, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 4: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 4: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const unsigned char ikm[] = {
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		};

		static const unsigned char salt[] = {
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		};

		static const unsigned char info[] = {
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		};

		static const unsigned char prk[] = {
			0xBDU, 0x8BU, 0x0FU, 0xBFU, 0x3EU, 0xA1U, 0xB3U, 0x0CU,
			0x4AU, 0x04U, 0x72U, 0xAEU, 0x66U, 0x08U, 0x47U, 0x15U,
			0xE5U, 0x72U, 0xEBU, 0xF7U, 0x7AU, 0xDBU, 0x57U, 0x59U,
			0xF6U, 0x5FU, 0x39U, 0x34U, 0xA4U, 0x6BU, 0x46U, 0x4DU,
		};

		static const unsigned char okm[] = {
			0x80U, 0xC4U, 0xE7U, 0x43U, 0xE3U, 0x50U, 0xDDU, 0x8EU,
			0x5BU, 0x29U, 0x96U, 0xA1U, 0xA7U, 0x57U, 0x0AU, 0x99U,
			0x0AU, 0x07U, 0x2EU, 0xD2U, 0x0AU, 0x9AU, 0x2BU, 0x24U,
			0xFDU, 0x8FU, 0x0CU, 0xF6U, 0x2FU, 0xE3U, 0x24U, 0x6CU,
			0x0CU, 0xB0U, 0x0BU, 0x37U, 0x9BU, 0x82U, 0x03U, 0xE9U,
			0xB7U, 0x7CU, 0x38U, 0xF7U, 0x4AU, 0xE6U, 0x09U, 0xC9U,
			0xCBU, 0x4EU, 0x57U, 0x02U, 0xD5U, 0x01U, 0xEDU, 0x03U,
			0x92U, 0x0EU, 0x7DU, 0x27U, 0x37U, 0x61U, 0x1BU, 0x20U,
			0xAEU, 0xBBU, 0x77U, 0xFAU, 0x6EU, 0xC2U, 0x9CU, 0xB3U,
			0x7AU, 0x0AU, 0xEFU, 0x77U, 0x3CU, 0x77U, 0x0FU, 0xE9U,
			0xB1U, 0xB7U, 0x56U, 0x1FU, 0xF9U, 0xF7U, 0xF4U, 0x31U,
			0x18U, 0x38U, 0xF5U, 0x1FU, 0x86U, 0x0DU, 0x6DU, 0x2BU,
			0x96U, 0xDBU, 0xEAU, 0xA4U, 0xDCU, 0x71U, 0x42U, 0x4FU,
			0x19U, 0xBDU, 0x29U, 0x58U, 0x14U, 0xF2U, 0x49U, 0xBEU,
			0xC4U, 0xABU, 0x74U, 0x5AU, 0xEFU, 0x2DU, 0x3EU, 0x98U,
			0x1AU, 0xE0U, 0x25U, 0xC1U, 0x1DU, 0x9AU, 0xF8U, 0x03U,
			0x5BU, 0x3DU, 0x06U, 0x48U, 0x75U, 0x1CU, 0x9CU, 0xE5U,
			0x7CU, 0x04U, 0x4BU, 0x4CU, 0xC2U, 0x9EU, 0xE4U, 0x4AU,
			0xBAU, 0x12U, 0x04U, 0x49U, 0x94U, 0xA4U, 0xECU, 0xCEU,
			0x4BU, 0xE7U, 0xF2U, 0x71U, 0x32U, 0xCCU, 0x40U, 0x81U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_256, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 5: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 5: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_256, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 5: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 5: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const unsigned char ikm[] = {
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
		};

		static const unsigned char salt[] = {
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		};

		static const unsigned char prk[] = {
			0xD9U, 0x2EU, 0x01U, 0x37U, 0xA1U, 0xA6U, 0xD2U, 0x66U,
			0xC9U, 0x2AU, 0x3CU, 0x96U, 0x34U, 0x43U, 0x9DU, 0x94U,
			0xABU, 0x72U, 0xA4U, 0xAAU, 0xDDU, 0x06U, 0xE1U, 0x8AU,
			0xD1U, 0x7FU, 0x6EU, 0x6FU, 0xFCU, 0xFCU, 0x1AU, 0x5AU,
		};

		static const unsigned char okm[] = {
			0x55U, 0x6CU, 0xABU, 0xE6U, 0x04U, 0x9FU, 0x83U, 0xB7U,
			0xFDU, 0xA1U, 0x58U, 0xB0U, 0xD7U, 0x37U, 0x3BU, 0xFFU,
			0x15U, 0x3BU, 0x3DU, 0x97U, 0x02U, 0x67U, 0x68U, 0x3EU,
			0xA5U, 0xE0U, 0xD5U, 0x62U, 0xD8U, 0x50U, 0x8DU, 0xEEU,
			0x11U, 0x61U, 0xF8U, 0xEDU, 0x47U, 0x44U, 0x1BU, 0x5BU,
			0xEDU, 0xBBU, 0x8EU, 0x08U, 0x4DU, 0x80U, 0x90U, 0x3CU,
			0x1FU, 0xBAU, 0x38U, 0x54U, 0x72U, 0xFFU, 0x2FU, 0xDAU,
			0xAAU, 0xEFU, 0x4AU, 0x69U, 0x16U, 0xA1U, 0xC3U, 0xA7U,
			0x69U, 0x81U, 0x01U, 0xFCU, 0xC8U, 0x37U, 0x82U, 0xB4U,
			0x07U, 0xB6U, 0x59U, 0x21U, 0xA5U, 0x73U, 0x1DU, 0xF5U,
			0x6BU, 0xECU, 0xBFU, 0x2AU, 0xE2U, 0x66U, 0x20U, 0x58U,
			0xF3U, 0x2DU, 0x0BU, 0x0AU, 0x04U, 0x6AU, 0x5CU, 0x87U,
			0x11U, 0xDDU, 0x9EU, 0xD2U, 0x8BU, 0x41U, 0x00U, 0x55U,
			0xE4U, 0xF8U, 0xCAU, 0x1CU, 0xA3U, 0x3DU, 0x77U, 0xB5U,
			0x44U, 0x60U, 0x56U, 0x51U, 0xCAU, 0x99U, 0x18U, 0xB0U,
			0xBAU, 0x37U, 0xD8U, 0x1DU, 0x97U, 0x5EU, 0xB9U, 0x6DU,
			0xC1U, 0x49U, 0x6EU, 0xC7U, 0xC3U, 0x6FU, 0x85U, 0x0CU,
			0x44U, 0x6CU, 0xCDU, 0x4CU, 0xB7U, 0x0DU, 0xB0U, 0x9DU,
			0xEEU, 0xC3U, 0x15U, 0x3BU, 0x2BU, 0x8CU, 0xF9U, 0x07U,
			0x38U, 0x1AU, 0x25U, 0xDCU, 0xBBU, 0x6EU, 0xD1U, 0x1AU,
			0xCEU, 0xF3U, 0xBDU, 0xB5U, 0x75U, 0x63U, 0x29U, 0x49U,
			0x19U, 0xA5U, 0x62U, 0x8BU, 0x80U, 0xB3U, 0x09U, 0x1FU,
			0x44U, 0x57U, 0x46U, 0x8DU, 0x90U, 0x7AU, 0x75U, 0x8CU,
			0x2CU, 0x9FU, 0x34U, 0xB6U, 0x45U, 0x36U, 0x0CU, 0x7DU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_256, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 6: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 6: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_256, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 6: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 6: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const unsigned char ikm[] = {
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
		};

		static const unsigned char info[] = {
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
		};

		static const unsigned char prk[] = {
			0x2BU, 0x18U, 0x6CU, 0x67U, 0xE4U, 0x0FU, 0xB3U, 0x10U,
			0x88U, 0x86U, 0xF2U, 0xE7U, 0xDDU, 0x88U, 0x0CU, 0x7FU,
			0x4BU, 0x36U, 0x33U, 0xC1U, 0x95U, 0x92U, 0x7FU, 0xB2U,
			0x9DU, 0x8EU, 0xBAU, 0xF6U, 0xCFU, 0x6FU, 0xB5U, 0xF3U,
		};

		static const unsigned char okm[] = {
			0xDDU, 0xE0U, 0xD6U, 0x00U, 0x24U, 0xBDU, 0x32U, 0x8AU,
			0x65U, 0x09U, 0x24U, 0x1CU, 0x40U, 0xF4U, 0xC5U, 0x0EU,
			0xF0U, 0xD3U, 0x1AU, 0xF2U, 0x67U, 0x7DU, 0xB7U, 0x7CU,
			0x67U, 0xB1U, 0x5CU, 0xD6U, 0xEDU, 0xA9U, 0xD9U, 0xC4U,
			0xB0U, 0xD3U, 0x82U, 0xBDU, 0xEFU, 0x96U, 0xB2U, 0xB8U,
			0x90U, 0x70U, 0xC9U, 0x4EU, 0x4AU, 0x08U, 0x7EU, 0x5BU,
			0x47U, 0x11U, 0xB6U, 0x7AU, 0x2FU, 0x22U, 0x1EU, 0xE8U,
			0x82U, 0x7BU, 0x6CU, 0xFFU, 0x60U, 0xADU, 0x8CU, 0x33U,
			0x02U, 0x6CU, 0x0CU, 0xA3U, 0x44U, 0x2FU, 0x60U, 0x14U,
			0x80U, 0x78U, 0xBDU, 0x12U, 0x03U, 0x51U, 0x05U, 0xF4U,
			0xDAU, 0xB6U, 0x86U, 0x86U, 0xF9U, 0x91U, 0x99U, 0xB2U,
			0x09U, 0xFCU, 0x82U, 0x8CU, 0x90U, 0x4DU, 0x0BU, 0x7CU,
			0xAEU, 0xB5U, 0xD5U, 0x39U, 0xE8U, 0xD6U, 0xB4U, 0x63U,
			0x38U, 0x69U, 0xA7U, 0x14U, 0xF7U, 0x2EU, 0xD2U, 0x90U,
			0xC8U, 0x4CU, 0x6DU, 0x9EU, 0xE1U, 0xE5U, 0xE0U, 0xD8U,
			0xC6U, 0x71U, 0x7FU, 0x56U, 0xB2U, 0xB5U, 0x47U, 0xDDU,
			0x9BU, 0xB3U, 0x08U, 0xA5U, 0xEBU, 0x9FU, 0xBEU, 0xCBU,
			0xEBU, 0x68U, 0x2CU, 0xC4U, 0xDDU, 0x14U, 0x1FU, 0x56U,
			0x26U, 0x4FU, 0xA4U, 0x12U, 0x6CU, 0x7CU, 0x9AU, 0x72U,
			0x6BU, 0xFDU, 0x64U, 0x00U, 0x3FU, 0x6AU, 0x9FU, 0x9AU,
			0x7CU, 0x57U, 0x7BU, 0xC0U, 0x4AU, 0x3DU, 0xE8U, 0x52U,
			0xCFU, 0x31U, 0x32U, 0xADU, 0xC4U, 0xC4U, 0xDBU, 0x6DU,
			0xB0U, 0xE1U, 0x8EU, 0x4CU, 0x59U, 0x16U, 0x33U, 0x9BU,
			0xEAU, 0xAFU, 0x0BU, 0x31U, 0xADU, 0x3DU, 0x42U, 0xF6U,
			0x73U, 0x40U, 0x04U, 0x11U, 0xE8U, 0x9CU, 0x2CU, 0x34U,
			0x25U, 0x74U, 0xDFU, 0x79U, 0x76U, 0x1BU, 0x8FU, 0x0EU,
			0x10U, 0x1CU, 0xE7U, 0x6FU, 0x90U, 0xA0U, 0x9AU, 0x5CU,
			0x3CU, 0x4BU, 0xA5U, 0x88U, 0x38U, 0x7FU, 0xF8U, 0x20U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_256, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 7: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 7: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_256, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 7: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 7: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 8 *
		 *****************/

		static const unsigned char ikm[] = {
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
		};

		static const unsigned char prk[] = {
			0x41U, 0x59U, 0xE0U, 0x96U, 0x0EU, 0x96U, 0x71U, 0x28U,
			0x13U, 0xF0U, 0x3BU, 0x5BU, 0x4FU, 0xAEU, 0xFFU, 0x2FU,
			0x05U, 0xCAU, 0xF8U, 0x31U, 0x9AU, 0x1EU, 0xD3U, 0xD7U,
			0xE9U, 0xA1U, 0xBEU, 0xD9U, 0x4BU, 0x94U, 0x24U, 0x02U,
		};

		static const unsigned char okm[] = {
			0x67U, 0x92U, 0x38U, 0x93U, 0x78U, 0x65U, 0x0CU, 0x8EU,
			0x9EU, 0xC9U, 0x3AU, 0x7AU, 0x43U, 0x14U, 0x82U, 0xF0U,
			0x09U, 0x5CU, 0x0EU, 0x76U, 0xE2U, 0x56U, 0xBDU, 0xEFU,
			0x3BU, 0x46U, 0x19U, 0x37U, 0xBDU, 0xDFU, 0x9FU, 0xFBU,
			0x59U, 0x9CU, 0xC9U, 0x5AU, 0x8DU, 0x58U, 0x4BU, 0xD2U,
			0x88U, 0x00U, 0x6DU, 0x23U, 0x08U, 0x57U, 0x65U, 0xCDU,
			0x57U, 0x7FU, 0x70U, 0xD0U, 0xB5U, 0x4FU, 0xF8U, 0x21U,
			0xECU, 0x47U, 0x12U, 0x44U, 0x24U, 0x83U, 0xFAU, 0x39U,
			0xB1U, 0xB5U, 0x91U, 0x73U, 0x4BU, 0x15U, 0xB5U, 0x49U,
			0x83U, 0xEDU, 0x6BU, 0xA1U, 0xDAU, 0xFFU, 0xB8U, 0x5CU,
			0x75U, 0x29U, 0x24U, 0x68U, 0xC6U, 0x5FU, 0x5FU, 0x7AU,
			0xD4U, 0xBCU, 0x1EU, 0x21U, 0x06U, 0xFDU, 0x54U, 0x6EU,
			0xA3U, 0xD4U, 0xC5U, 0xFFU, 0x48U, 0xA4U, 0x94U, 0xE5U,
			0xB8U, 0x54U, 0xF4U, 0x27U, 0x30U, 0xFEU, 0x5CU, 0x40U,
			0xF7U, 0x26U, 0x15U, 0xBAU, 0x49U, 0x37U, 0x50U, 0xDDU,
			0x28U, 0xEAU, 0xB8U, 0x68U, 0x4BU, 0xBEU, 0xCEU, 0x2AU,
			0x4CU, 0x8CU, 0xB2U, 0xF2U, 0x50U, 0xD5U, 0xE5U, 0x53U,
			0x6DU, 0x0BU, 0x17U, 0x5CU, 0x96U, 0x46U, 0xC9U, 0x5FU,
			0x4DU, 0x7BU, 0x75U, 0x04U, 0x2CU, 0x34U, 0x8FU, 0x65U,
			0x4EU, 0x92U, 0xE7U, 0x5FU, 0x47U, 0x1AU, 0x3BU, 0x20U,
			0x50U, 0x19U, 0x0BU, 0x76U, 0xAEU, 0xCFU, 0x4CU, 0x5FU,
			0x8AU, 0x4CU, 0x8AU, 0xE8U, 0x09U, 0x3BU, 0x12U, 0x2EU,
			0x9DU, 0xC7U, 0x0FU, 0x16U, 0x30U, 0xF1U, 0xCCU, 0x00U,
			0x17U, 0x40U, 0x1BU, 0x96U, 0x6AU, 0xFCU, 0xD3U, 0x26U,
			0x15U, 0x9BU, 0x0FU, 0xBAU, 0x39U, 0x63U, 0x51U, 0x7AU,
			0xDEU, 0xD7U, 0x7BU, 0x19U, 0xA5U, 0xFAU, 0x17U, 0x0FU,
			0x67U, 0x40U, 0xD8U, 0x8AU, 0x89U, 0x52U, 0x52U, 0xC1U,
			0xDDU, 0xCDU, 0xBAU, 0xC4U, 0xCFU, 0xA9U, 0x16U, 0xFCU,
			0xC9U, 0x67U, 0xAAU, 0xFCU, 0x50U, 0x89U, 0x27U, 0x72U,
			0xC0U, 0x1DU, 0xECU, 0xACU, 0xA0U, 0x96U, 0xA4U, 0xF9U,
			0x07U, 0x6EU, 0x3BU, 0x7DU, 0x2CU, 0xC9U, 0x4EU, 0xFBU,
			0x37U, 0xCBU, 0x5BU, 0x2CU, 0x7EU, 0x2DU, 0x9BU, 0xE0U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 8", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_256, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 8: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 8: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_256, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 8: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 8: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	return true;
}

static bool
digest_testsuite_run_hkdf_sha2_512(void)
{
	{
		/*****************
		 * TEST VECTOR 1 *
		 *****************/

		static const unsigned char ikm[] = {
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		};

		static const unsigned char salt[] = {
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
		};

		static const unsigned char info[] = {
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
		};

		static const unsigned char prk[] = {
			0xDFU, 0xE6U, 0xAAU, 0xF3U, 0xE2U, 0x83U, 0xD2U, 0xFAU,
			0x3DU, 0xE4U, 0x6EU, 0x8AU, 0x64U, 0x7EU, 0xBBU, 0x85U,
			0x82U, 0x12U, 0x69U, 0x1BU, 0x8EU, 0xE8U, 0x4CU, 0x24U,
			0xECU, 0x1FU, 0xE3U, 0x97U, 0x1DU, 0x18U, 0xE3U, 0x37U,
			0xEDU, 0x7CU, 0x3AU, 0x67U, 0x47U, 0xABU, 0x45U, 0xC4U,
			0x02U, 0x11U, 0xCCU, 0x77U, 0xD0U, 0xD7U, 0xB1U, 0xD9U,
			0xF1U, 0x98U, 0x52U, 0x72U, 0x6FU, 0xB1U, 0x28U, 0x66U,
			0x27U, 0xB0U, 0xF8U, 0x28U, 0x45U, 0x54U, 0x8FU, 0x79U,
		};

		static const unsigned char okm[] = {
			0x45U, 0xF3U, 0xE1U, 0x9FU, 0xA0U, 0x46U, 0x5AU, 0x76U,
			0x44U, 0xF3U, 0x32U, 0x3FU, 0x00U, 0xBAU, 0x31U, 0x52U,
			0x4DU, 0xB1U, 0xBFU, 0xB8U, 0x91U, 0xF6U, 0x13U, 0xA9U,
			0xB0U, 0x4FU, 0x97U, 0xC7U, 0xEDU, 0xFEU, 0xEDU, 0x09U,
			0x1BU, 0xEBU, 0xA4U, 0x95U, 0x4CU, 0x3EU, 0x22U, 0x5CU,
			0x40U, 0x5CU, 0xF5U, 0xA9U, 0xF3U, 0x73U, 0xF5U, 0x36U,
			0x0CU, 0x22U, 0x6AU, 0x98U, 0x48U, 0xB8U, 0x01U, 0x1EU,
			0x98U, 0x89U, 0xDEU, 0x06U, 0x2BU, 0x7FU, 0x39U, 0x32U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_512, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 1: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 1: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_512, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 1: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 1: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 2 *
		 *****************/

		static const unsigned char ikm[] = {
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		};

		static const unsigned char salt[] = {
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		};

		static const unsigned char prk[] = {
			0xD6U, 0x2FU, 0x75U, 0x29U, 0x01U, 0xD1U, 0x5AU, 0x57U,
			0x62U, 0xC4U, 0x66U, 0x83U, 0xB0U, 0x43U, 0x7CU, 0xBFU,
			0x2AU, 0xD7U, 0x73U, 0x35U, 0xB9U, 0xE8U, 0x93U, 0xFCU,
			0xEDU, 0x75U, 0xA7U, 0xD7U, 0xCDU, 0x6CU, 0xEEU, 0x79U,
			0xBDU, 0xD6U, 0xBDU, 0x10U, 0xBBU, 0x25U, 0x2FU, 0x28U,
			0x2BU, 0xF6U, 0x9CU, 0xA4U, 0x33U, 0x9EU, 0x35U, 0xAEU,
			0x8AU, 0xDAU, 0x36U, 0x21U, 0xCBU, 0x26U, 0x1FU, 0x55U,
			0x58U, 0x5BU, 0x7AU, 0x38U, 0x18U, 0x8FU, 0x5BU, 0xE8U,
		};

		static const unsigned char okm[] = {
			0x3BU, 0x69U, 0x60U, 0x92U, 0x5AU, 0xFCU, 0xA3U, 0x13U,
			0xDDU, 0xF6U, 0xD0U, 0xDCU, 0x70U, 0x4AU, 0xAAU, 0x5DU,
			0x69U, 0x30U, 0xD2U, 0x84U, 0x20U, 0xD9U, 0x3AU, 0xAEU,
			0x92U, 0x64U, 0x18U, 0xB5U, 0xB4U, 0x25U, 0xA8U, 0x41U,
			0x06U, 0xE0U, 0x80U, 0x70U, 0xDCU, 0xFFU, 0x2AU, 0x06U,
			0x38U, 0x47U, 0x55U, 0xC7U, 0xEFU, 0x14U, 0x1DU, 0x12U,
			0x01U, 0xF7U, 0x91U, 0x5AU, 0x91U, 0xA9U, 0xCBU, 0xEFU,
			0x1DU, 0xA5U, 0x5CU, 0xA9U, 0x46U, 0x85U, 0x06U, 0xEBU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 2", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_512, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 2: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 2: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_512, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 2: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 2: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 3 *
		 *****************/

		static const unsigned char ikm[] = {
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		};

		static const unsigned char info[] = {
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
		};

		static const unsigned char prk[] = {
			0x77U, 0x22U, 0x47U, 0x26U, 0x20U, 0xF7U, 0x6EU, 0xA9U,
			0x37U, 0xF5U, 0x89U, 0x5FU, 0xB1U, 0x44U, 0x43U, 0x7EU,
			0x5CU, 0x8FU, 0x1CU, 0x44U, 0x3BU, 0xF7U, 0x1CU, 0x56U,
			0x50U, 0x20U, 0x56U, 0x80U, 0x14U, 0xF3U, 0xE1U, 0x9FU,
			0xB0U, 0xA9U, 0x8EU, 0x00U, 0x88U, 0x2EU, 0xC5U, 0xEFU,
			0x42U, 0xC8U, 0x9CU, 0x9FU, 0x50U, 0xA1U, 0xBFU, 0x6BU,
			0x60U, 0xDCU, 0x40U, 0x7CU, 0x7AU, 0x09U, 0x18U, 0x8FU,
			0xCCU, 0x66U, 0xEBU, 0xA8U, 0x6BU, 0xF6U, 0xD1U, 0x89U,
		};

		static const unsigned char okm[] = {
			0xF2U, 0x23U, 0x82U, 0x4EU, 0x6CU, 0x4BU, 0x42U, 0xD7U,
			0x79U, 0x76U, 0xBBU, 0x51U, 0x4EU, 0x67U, 0x83U, 0x35U,
			0x71U, 0x47U, 0x2BU, 0xDDU, 0x90U, 0xE0U, 0x7EU, 0xCBU,
			0xA7U, 0xC3U, 0x20U, 0xA3U, 0x00U, 0x54U, 0x74U, 0x39U,
			0xCEU, 0x7CU, 0x1DU, 0x39U, 0x66U, 0x00U, 0x54U, 0xE0U,
			0x07U, 0xEBU, 0x9DU, 0x6DU, 0xB1U, 0x9AU, 0x68U, 0xD1U,
			0xA8U, 0x1FU, 0x1DU, 0xB2U, 0xCEU, 0xE4U, 0xC8U, 0xC2U,
			0xAAU, 0x25U, 0x14U, 0x21U, 0x42U, 0x28U, 0x0FU, 0x51U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 3", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_512, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 3: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 3: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_512, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 3: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 3: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 4 *
		 *****************/

		static const unsigned char ikm[] = {
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		};

		static const unsigned char prk[] = {
			0x7FU, 0x81U, 0xB2U, 0xAAU, 0x0AU, 0xC7U, 0x0AU, 0x51U,
			0x29U, 0xD3U, 0x95U, 0x35U, 0xE4U, 0x65U, 0x78U, 0x25U,
			0x04U, 0x34U, 0xCDU, 0xEDU, 0x86U, 0x44U, 0xBEU, 0xB2U,
			0x58U, 0x57U, 0x9AU, 0xD8U, 0xECU, 0x8FU, 0xC7U, 0x29U,
			0x0EU, 0x45U, 0xD0U, 0x8EU, 0xC8U, 0x60U, 0xC2U, 0x4AU,
			0xDAU, 0xEEU, 0x90U, 0x26U, 0x3EU, 0xE7U, 0x11U, 0xFEU,
			0x62U, 0xE8U, 0x5CU, 0x71U, 0xB5U, 0x5DU, 0x08U, 0x73U,
			0xCFU, 0x8DU, 0x09U, 0x5CU, 0x70U, 0x26U, 0xD5U, 0xD1U,
		};

		static const unsigned char okm[] = {
			0x9AU, 0xDAU, 0x1CU, 0x8FU, 0xB6U, 0xEBU, 0x61U, 0x83U,
			0xCAU, 0xB5U, 0x99U, 0x2FU, 0xA9U, 0xCEU, 0x7BU, 0x4DU,
			0xB5U, 0x0EU, 0x06U, 0x04U, 0x7AU, 0x2CU, 0x99U, 0xB7U,
			0x56U, 0xF3U, 0xB5U, 0x18U, 0x74U, 0x40U, 0xA6U, 0x0BU,
			0x6EU, 0xFCU, 0xEFU, 0x59U, 0x79U, 0xB8U, 0x67U, 0xBAU,
			0x4AU, 0x4EU, 0x26U, 0x36U, 0x9AU, 0x2FU, 0xEDU, 0xFDU,
			0xC9U, 0x16U, 0xBCU, 0x54U, 0x33U, 0x1BU, 0x6AU, 0x4AU,
			0xD8U, 0x15U, 0xCFU, 0x6AU, 0x1FU, 0x70U, 0xF8U, 0x1BU,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 4", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_512, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 4: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 4: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_512, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 4: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 4: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 5 *
		 *****************/

		static const unsigned char ikm[] = {
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
		};

		static const unsigned char salt[] = {
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
		};

		static const unsigned char info[] = {
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		};

		static const unsigned char prk[] = {
			0x3BU, 0x64U, 0xA3U, 0x71U, 0xB1U, 0x27U, 0x09U, 0x99U,
			0x4EU, 0x94U, 0xECU, 0xCDU, 0xB5U, 0x5AU, 0x4DU, 0x5BU,
			0xAAU, 0x54U, 0xB4U, 0x77U, 0xB7U, 0xACU, 0x47U, 0xF4U,
			0x67U, 0xF6U, 0x83U, 0x0EU, 0x37U, 0x60U, 0x83U, 0x4BU,
			0x6DU, 0xD4U, 0x19U, 0x1BU, 0xA6U, 0xB7U, 0xE8U, 0x2EU,
			0x91U, 0x2BU, 0x8CU, 0x05U, 0x75U, 0x8AU, 0x73U, 0xD8U,
			0x14U, 0x3EU, 0xAAU, 0x0EU, 0x69U, 0x33U, 0xBFU, 0xF2U,
			0x80U, 0x27U, 0x9AU, 0x22U, 0x1BU, 0xF6U, 0xFFU, 0x28U,
		};

		static const unsigned char okm[] = {
			0x20U, 0x3EU, 0xA3U, 0x91U, 0xD2U, 0xE7U, 0x8DU, 0xC4U,
			0x23U, 0xE1U, 0xC2U, 0x80U, 0xAEU, 0x62U, 0x53U, 0x29U,
			0x2EU, 0x64U, 0x83U, 0xD3U, 0x0BU, 0x9CU, 0x68U, 0xA2U,
			0xF0U, 0xB6U, 0x98U, 0xC4U, 0xDEU, 0x44U, 0xF5U, 0x55U,
			0x6AU, 0xC7U, 0xDDU, 0x8BU, 0x31U, 0xBCU, 0x62U, 0x78U,
			0xDDU, 0xC0U, 0x0CU, 0x23U, 0xD3U, 0x21U, 0xE5U, 0x9DU,
			0x92U, 0x0BU, 0x6CU, 0xCFU, 0x55U, 0x99U, 0x94U, 0x79U,
			0x28U, 0x81U, 0xC0U, 0xEBU, 0xA6U, 0xA5U, 0x2FU, 0xB5U,
			0x1DU, 0xA5U, 0x65U, 0x5AU, 0xCAU, 0x44U, 0x65U, 0x41U,
			0x7FU, 0xE7U, 0x4AU, 0x5CU, 0xB9U, 0x52U, 0x23U, 0xB2U,
			0xF3U, 0x8FU, 0x6AU, 0xA4U, 0x81U, 0x0EU, 0xD9U, 0xB3U,
			0x96U, 0x68U, 0xC0U, 0xE6U, 0x52U, 0xA8U, 0xB8U, 0x30U,
			0x68U, 0xCEU, 0x1BU, 0x8EU, 0x77U, 0x4BU, 0x57U, 0x6AU,
			0x2BU, 0x2AU, 0x13U, 0xAFU, 0x44U, 0x1DU, 0xC3U, 0x25U,
			0x65U, 0xE1U, 0x90U, 0xAFU, 0x0EU, 0xCCU, 0x8EU, 0x4BU,
			0xF2U, 0x25U, 0x47U, 0x5FU, 0x62U, 0x9AU, 0xF0U, 0x34U,
			0xB5U, 0xB7U, 0xE1U, 0x21U, 0x63U, 0xBFU, 0xA6U, 0x41U,
			0x2CU, 0x00U, 0xF0U, 0x55U, 0x09U, 0x96U, 0x66U, 0x54U,
			0xD5U, 0x69U, 0x1CU, 0x43U, 0x28U, 0x7FU, 0x77U, 0xBEU,
			0x98U, 0xE4U, 0x69U, 0x84U, 0x70U, 0x2CU, 0x47U, 0x68U,
			0x4AU, 0xEFU, 0x39U, 0x40U, 0x2EU, 0xFBU, 0x9AU, 0x4FU,
			0xDDU, 0x05U, 0xA4U, 0x54U, 0x3BU, 0x92U, 0xCBU, 0x95U,
			0xE8U, 0xD1U, 0x7DU, 0xF0U, 0x9EU, 0x3BU, 0xF1U, 0xB8U,
			0xE4U, 0x81U, 0xD6U, 0x36U, 0x6FU, 0x04U, 0x12U, 0x27U,
			0x28U, 0xEAU, 0xD4U, 0x80U, 0x57U, 0xA7U, 0xACU, 0x0FU,
			0x49U, 0x1BU, 0xA4U, 0x1CU, 0xDCU, 0xA1U, 0x39U, 0xA8U,
			0xC6U, 0xF7U, 0xE3U, 0x32U, 0x38U, 0x9FU, 0xC7U, 0xFCU,
			0xCEU, 0x72U, 0x2AU, 0x6DU, 0x93U, 0xC7U, 0x11U, 0x95U,
			0x12U, 0xF7U, 0x04U, 0xC4U, 0x17U, 0xF0U, 0x83U, 0xCFU,
			0xDCU, 0xE7U, 0x32U, 0xABU, 0xADU, 0x38U, 0x53U, 0xBEU,
			0x42U, 0x11U, 0x2DU, 0xD5U, 0x22U, 0x6BU, 0x56U, 0xD8U,
			0x88U, 0x04U, 0xE3U, 0xB0U, 0x0AU, 0x8DU, 0xDFU, 0xC1U,
			0xF2U, 0x0DU, 0x75U, 0x80U, 0xDEU, 0x37U, 0x64U, 0x5FU,
			0x59U, 0x4FU, 0x00U, 0x1CU, 0x70U, 0xAEU, 0x5BU, 0x12U,
			0x9EU, 0xB7U, 0x89U, 0x3CU, 0xE6U, 0x84U, 0x88U, 0x9CU,
			0xD3U, 0x95U, 0x3EU, 0x59U, 0x80U, 0x0CU, 0x4EU, 0x8BU,
			0xEEU, 0xBBU, 0x5EU, 0x16U, 0x1BU, 0xC4U, 0x8CU, 0x05U,
			0xD9U, 0x96U, 0x15U, 0x53U, 0x89U, 0xDCU, 0x7CU, 0xEFU,
			0xA1U, 0x06U, 0x0FU, 0xE4U, 0xC0U, 0xBDU, 0x36U, 0x5CU,
			0x04U, 0x71U, 0xDBU, 0x18U, 0xE9U, 0x8DU, 0x8BU, 0xD6U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 5", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_512, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 5: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 5: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_512, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 5: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 5: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 6 *
		 *****************/

		static const unsigned char ikm[] = {
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
		};

		static const unsigned char salt[] = {
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		};

		static const unsigned char prk[] = {
			0x13U, 0x72U, 0xD2U, 0xBCU, 0x3DU, 0xF4U, 0xABU, 0x5FU,
			0x55U, 0x8CU, 0x2EU, 0xC9U, 0x51U, 0x46U, 0xD5U, 0x2CU,
			0xF5U, 0x20U, 0x09U, 0x8DU, 0x6CU, 0x4FU, 0x52U, 0x43U,
			0x25U, 0x61U, 0xA5U, 0x84U, 0xAFU, 0x96U, 0x50U, 0x5CU,
			0xCEU, 0xC2U, 0x52U, 0x31U, 0x01U, 0x3BU, 0x98U, 0xA8U,
			0xFBU, 0x6DU, 0x3EU, 0x4CU, 0x16U, 0x3DU, 0x8AU, 0xD9U,
			0xFDU, 0x60U, 0x7FU, 0x38U, 0xF3U, 0xDAU, 0x34U, 0xCAU,
			0xF0U, 0xEEU, 0x73U, 0xBAU, 0x21U, 0x30U, 0xB3U, 0xA8U,
		};

		static const unsigned char okm[] = {
			0xD6U, 0x71U, 0x62U, 0x05U, 0xC6U, 0x7DU, 0xBBU, 0xF3U,
			0x30U, 0x31U, 0x45U, 0xF1U, 0x2FU, 0x15U, 0xAEU, 0x8EU,
			0xC0U, 0xB1U, 0xB2U, 0x87U, 0x3BU, 0x60U, 0xA5U, 0xF2U,
			0xAEU, 0x60U, 0x17U, 0x78U, 0x7DU, 0xA2U, 0xACU, 0xA3U,
			0x3AU, 0x54U, 0x37U, 0x31U, 0x59U, 0x59U, 0xE3U, 0xF6U,
			0x32U, 0xBCU, 0x81U, 0xB0U, 0x16U, 0x32U, 0x89U, 0x3DU,
			0x97U, 0xB3U, 0xBAU, 0x62U, 0x16U, 0xB0U, 0x9FU, 0x27U,
			0xFEU, 0x81U, 0xF0U, 0xEAU, 0x32U, 0x3BU, 0x0FU, 0xD7U,
			0x4DU, 0x7EU, 0x00U, 0x82U, 0x88U, 0x70U, 0xFBU, 0x18U,
			0x4EU, 0x3CU, 0x21U, 0x4CU, 0x48U, 0xFFU, 0x35U, 0x26U,
			0xBCU, 0x56U, 0xF6U, 0x41U, 0xC6U, 0xAFU, 0xDBU, 0x67U,
			0x8BU, 0x9EU, 0xBBU, 0x7AU, 0xE8U, 0x24U, 0xF7U, 0x76U,
			0x75U, 0x4AU, 0x92U, 0xB7U, 0x3AU, 0x62U, 0xCAU, 0x67U,
			0x80U, 0xE9U, 0xA5U, 0xA1U, 0x1EU, 0x65U, 0xBCU, 0x7CU,
			0xD3U, 0x4EU, 0x20U, 0x03U, 0x0CU, 0xF3U, 0x37U, 0x58U,
			0x6CU, 0xDBU, 0xFFU, 0xD1U, 0x16U, 0x3CU, 0xB3U, 0x9DU,
			0x43U, 0x9DU, 0x33U, 0x28U, 0x58U, 0x56U, 0x02U, 0x43U,
			0xAAU, 0xFDU, 0x61U, 0xDFU, 0xA1U, 0x1BU, 0xA6U, 0xDDU,
			0x8DU, 0xDCU, 0x0AU, 0xB2U, 0x6CU, 0xE5U, 0x57U, 0x8DU,
			0xA6U, 0x5FU, 0x9EU, 0xAFU, 0xF0U, 0xF8U, 0x98U, 0x48U,
			0xA5U, 0x1DU, 0x31U, 0x8CU, 0xD2U, 0x3BU, 0x45U, 0xF0U,
			0x3AU, 0xD4U, 0xECU, 0x24U, 0xDAU, 0xE5U, 0x7BU, 0xADU,
			0xCCU, 0x6EU, 0xDCU, 0xF0U, 0xBBU, 0x59U, 0xE5U, 0x94U,
			0x3BU, 0xA2U, 0x88U, 0x39U, 0xB9U, 0x30U, 0xA2U, 0xFFU,
			0x48U, 0x8CU, 0xA8U, 0x27U, 0x28U, 0x0CU, 0x85U, 0x41U,
			0x68U, 0x64U, 0xFAU, 0xAEU, 0x8CU, 0xD5U, 0xACU, 0xA3U,
			0xBFU, 0x85U, 0x40U, 0x9AU, 0x41U, 0x17U, 0x1BU, 0x7BU,
			0x00U, 0x5FU, 0x92U, 0x2FU, 0x81U, 0x97U, 0x48U, 0x3FU,
			0xECU, 0xFEU, 0x60U, 0x44U, 0x20U, 0xD7U, 0xA0U, 0x45U,
			0xFFU, 0x95U, 0xF7U, 0x1AU, 0x85U, 0xA8U, 0xE0U, 0x4FU,
			0xD3U, 0x82U, 0x69U, 0x73U, 0x67U, 0x94U, 0xEAU, 0x8AU,
			0x30U, 0x41U, 0x27U, 0x00U, 0x47U, 0xA9U, 0x16U, 0x47U,
			0xBAU, 0x28U, 0xE2U, 0x43U, 0xA4U, 0x96U, 0x4FU, 0xB4U,
			0xE4U, 0x1CU, 0x15U, 0xFFU, 0xA2U, 0x5DU, 0x40U, 0x2FU,
			0x9AU, 0x7DU, 0x9AU, 0xF0U, 0xD7U, 0xC2U, 0xF3U, 0x48U,
			0x6AU, 0x27U, 0x80U, 0xF7U, 0xE0U, 0xEFU, 0xB6U, 0xEAU,
			0x07U, 0x80U, 0xE0U, 0xEEU, 0x58U, 0x0EU, 0x25U, 0xF2U,
			0xA5U, 0xA8U, 0x44U, 0xE0U, 0x56U, 0xF0U, 0xA7U, 0x99U,
			0xCFU, 0xCAU, 0x6CU, 0xFFU, 0x04U, 0x27U, 0xB5U, 0x33U,
			0x6AU, 0xF2U, 0xFDU, 0xD3U, 0x98U, 0x1DU, 0x1CU, 0x38U,
			0x29U, 0xCFU, 0xAFU, 0x62U, 0x33U, 0xDCU, 0x2EU, 0x20U,
			0xACU, 0x60U, 0x29U, 0xC3U, 0x5AU, 0x46U, 0xC0U, 0x02U,
			0x05U, 0xE3U, 0xE3U, 0x85U, 0x20U, 0x38U, 0xD7U, 0xD6U,
			0x59U, 0xBCU, 0xAFU, 0x4AU, 0xA4U, 0x45U, 0xA2U, 0x8EU,
			0x9BU, 0x97U, 0x6DU, 0x15U, 0x14U, 0xB7U, 0x7EU, 0x47U,
			0xC6U, 0x76U, 0x91U, 0x95U, 0xBAU, 0x89U, 0x3EU, 0x31U,
			0x1FU, 0x73U, 0x2CU, 0x2CU, 0x65U, 0xB7U, 0x52U, 0xDAU,
			0x2EU, 0x4FU, 0xF7U, 0xCBU, 0xB1U, 0x73U, 0x1CU, 0xA9U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 6", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_512, ikm, sizeof ikm, salt, sizeof salt, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 6: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 6: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_512, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 6: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 6: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 7 *
		 *****************/

		static const unsigned char ikm[] = {
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
		};

		static const unsigned char info[] = {
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
			0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
			0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
			0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
			0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
			0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
			0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
			0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
			0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
			0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
			0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
			0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
			0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
			0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
			0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
			0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
			0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
		};

		static const unsigned char prk[] = {
			0x88U, 0xA7U, 0xF4U, 0xCFU, 0xCBU, 0x2AU, 0xC3U, 0x87U,
			0x98U, 0x47U, 0xFEU, 0x16U, 0x9BU, 0x57U, 0x1AU, 0x03U,
			0x9BU, 0x98U, 0x30U, 0xE4U, 0x57U, 0x3AU, 0x8FU, 0x7EU,
			0x28U, 0xB6U, 0xD7U, 0xC1U, 0xDEU, 0x8EU, 0xFDU, 0xB6U,
			0x91U, 0x35U, 0xFEU, 0x27U, 0xCAU, 0x30U, 0x18U, 0x67U,
			0xEBU, 0xC1U, 0xCEU, 0x8FU, 0x09U, 0x10U, 0xAFU, 0x5FU,
			0x32U, 0x42U, 0x69U, 0x6BU, 0x97U, 0xC5U, 0xD3U, 0xE4U,
			0xD6U, 0xFFU, 0xA9U, 0xEEU, 0xBFU, 0xF9U, 0xCDU, 0xB2U,
		};

		static const unsigned char okm[] = {
			0xCCU, 0x08U, 0xB8U, 0x1FU, 0x73U, 0xA7U, 0x36U, 0x33U,
			0x05U, 0x0EU, 0x63U, 0xFCU, 0xACU, 0x44U, 0xE6U, 0x4BU,
			0x3BU, 0xD5U, 0x38U, 0x7BU, 0x28U, 0x4BU, 0x35U, 0x93U,
			0xF6U, 0xA9U, 0x45U, 0x6DU, 0x0CU, 0x48U, 0x94U, 0x6BU,
			0x7CU, 0xF7U, 0x57U, 0x7DU, 0xB9U, 0xEEU, 0x56U, 0x71U,
			0x5BU, 0xDBU, 0x22U, 0x79U, 0xDCU, 0x6FU, 0xA1U, 0x43U,
			0x03U, 0xE0U, 0xEFU, 0xB7U, 0xE1U, 0xE9U, 0xB5U, 0xB5U,
			0x38U, 0xCEU, 0xCFU, 0x53U, 0xB3U, 0xCBU, 0xB7U, 0x4AU,
			0x7BU, 0x57U, 0xA4U, 0x31U, 0x85U, 0x43U, 0xDDU, 0x30U,
			0x08U, 0x05U, 0xFEU, 0xE1U, 0x8EU, 0xCAU, 0xA2U, 0xB0U,
			0x79U, 0x51U, 0x22U, 0xC4U, 0x18U, 0xA9U, 0x9BU, 0x76U,
			0xB6U, 0x11U, 0x0DU, 0x82U, 0x55U, 0xDDU, 0xBAU, 0xDDU,
			0x0FU, 0x90U, 0xACU, 0xF5U, 0x25U, 0xB0U, 0x0DU, 0xF6U,
			0x4EU, 0xA9U, 0x9FU, 0x41U, 0xF3U, 0xF2U, 0xDDU, 0x94U,
			0x3EU, 0x7DU, 0x19U, 0xBCU, 0x94U, 0x51U, 0xA4U, 0x50U,
			0xD6U, 0x6DU, 0x10U, 0x01U, 0x54U, 0x90U, 0x48U, 0xF3U,
			0x23U, 0x47U, 0x35U, 0xCAU, 0xA0U, 0xBDU, 0x9DU, 0x95U,
			0x2DU, 0x23U, 0x17U, 0x67U, 0xB7U, 0x08U, 0x56U, 0x98U,
			0xE9U, 0x77U, 0x55U, 0x31U, 0xB1U, 0x35U, 0xABU, 0x95U,
			0xEEU, 0x7CU, 0x74U, 0x32U, 0x6FU, 0x31U, 0x17U, 0x8DU,
			0x94U, 0xEFU, 0x3EU, 0xBAU, 0x8CU, 0x9FU, 0xF8U, 0xE4U,
			0xA8U, 0x1FU, 0xF5U, 0x97U, 0xABU, 0x9DU, 0xE0U, 0xBEU,
			0x1DU, 0x20U, 0xE1U, 0x0EU, 0x45U, 0x43U, 0xB1U, 0x1FU,
			0x1AU, 0xAAU, 0xC1U, 0xC1U, 0x40U, 0xC5U, 0xC7U, 0x00U,
			0x83U, 0x14U, 0xB9U, 0x2FU, 0xA8U, 0xEBU, 0xF9U, 0x2DU,
			0x63U, 0xF1U, 0xC8U, 0x07U, 0xBDU, 0xE4U, 0xD0U, 0x86U,
			0xB4U, 0x47U, 0x99U, 0x84U, 0x14U, 0x0AU, 0x63U, 0x08U,
			0xE8U, 0x6CU, 0xAEU, 0xCAU, 0xF6U, 0xC3U, 0xDDU, 0x3FU,
			0xC1U, 0x95U, 0xFAU, 0x93U, 0xF7U, 0x07U, 0x77U, 0xAFU,
			0x7FU, 0x87U, 0xF0U, 0x08U, 0x10U, 0x42U, 0x48U, 0x81U,
			0x6BU, 0x12U, 0x71U, 0x77U, 0x42U, 0x5EU, 0xDEU, 0x39U,
			0xB7U, 0x2DU, 0x11U, 0xC6U, 0x43U, 0x71U, 0x8DU, 0xCEU,
			0x96U, 0xABU, 0x65U, 0xE6U, 0xC4U, 0xEBU, 0x15U, 0xCFU,
			0xB9U, 0xF8U, 0x6BU, 0x72U, 0xCDU, 0xE6U, 0x1EU, 0x87U,
			0x9DU, 0x4AU, 0xB8U, 0x6CU, 0x60U, 0x2EU, 0x40U, 0x5FU,
			0x26U, 0x5DU, 0x6EU, 0x03U, 0xC8U, 0xE6U, 0x2EU, 0x05U,
			0xEDU, 0x59U, 0xD8U, 0x3FU, 0xC1U, 0xB4U, 0x13U, 0x81U,
			0x87U, 0x2AU, 0xA0U, 0x98U, 0x12U, 0x1FU, 0x06U, 0x15U,
			0xCBU, 0x97U, 0xAEU, 0xFFU, 0x5EU, 0xF7U, 0x70U, 0x1CU,
			0x49U, 0x23U, 0x86U, 0x66U, 0x67U, 0x23U, 0x5FU, 0xB3U,
			0xAAU, 0xA0U, 0xC5U, 0x89U, 0x7FU, 0x49U, 0x31U, 0x09U,
			0x9FU, 0x88U, 0x71U, 0x67U, 0xBFU, 0xB1U, 0x74U, 0x56U,
			0xB5U, 0xD7U, 0xE1U, 0x1EU, 0xA6U, 0x8BU, 0xF9U, 0xB9U,
			0x28U, 0x8AU, 0xC4U, 0xACU, 0xDAU, 0xA1U, 0x0EU, 0x07U,
			0x69U, 0x62U, 0x41U, 0xADU, 0xD0U, 0x95U, 0x22U, 0x4CU,
			0xB6U, 0x82U, 0x95U, 0x27U, 0xC6U, 0x44U, 0xA7U, 0xA8U,
			0x7FU, 0x55U, 0xB7U, 0xC6U, 0x05U, 0xFAU, 0x10U, 0xC3U,
			0xF5U, 0xA8U, 0xA3U, 0xB9U, 0xFEU, 0x7BU, 0x89U, 0x4FU,
			0x8DU, 0x6FU, 0xA5U, 0x8AU, 0x2FU, 0x95U, 0xDDU, 0xF4U,
			0xDFU, 0x05U, 0x60U, 0x27U, 0x55U, 0x17U, 0x9FU, 0xE9U,
			0xC3U, 0xDBU, 0xE7U, 0xB9U, 0x41U, 0x79U, 0xB3U, 0x3DU,
			0x53U, 0x7FU, 0xECU, 0xCEU, 0xA4U, 0xF5U, 0xAEU, 0x90U,
			0x9EU, 0x0EU, 0x93U, 0xC3U, 0x0AU, 0xB2U, 0xE9U, 0x96U,
			0xAFU, 0x27U, 0xFDU, 0x57U, 0xDDU, 0x7EU, 0xF8U, 0x3EU,
			0x56U, 0xA8U, 0x55U, 0x46U, 0xEFU, 0x28U, 0x9CU, 0xF9U,
			0x77U, 0x6BU, 0x95U, 0x15U, 0xFEU, 0xF0U, 0xA9U, 0xF1U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 7", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_512, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 7: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 7: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_512, prk, sizeof prk, info, sizeof info, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 7: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 7: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	{
		/*****************
		 * TEST VECTOR 8 *
		 *****************/

		static const unsigned char ikm[] = {
			0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
			0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
			0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
			0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
			0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
			0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
			0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
			0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
			0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
			0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
			0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
			0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
			0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
			0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
			0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
			0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
		};

		static const unsigned char prk[] = {
			0xA4U, 0x69U, 0xBBU, 0x2AU, 0x9DU, 0x0CU, 0x4DU, 0x8AU,
			0x06U, 0x4AU, 0xBAU, 0x18U, 0xC4U, 0xE4U, 0x90U, 0x2EU,
			0x1BU, 0x88U, 0x9AU, 0x9AU, 0x28U, 0x76U, 0x28U, 0x00U,
			0xD6U, 0xF5U, 0x6EU, 0xEFU, 0x45U, 0xEBU, 0xC8U, 0xE1U,
			0xD0U, 0x8CU, 0x05U, 0xE4U, 0xFDU, 0xC7U, 0x48U, 0x58U,
			0x51U, 0x45U, 0x94U, 0x1BU, 0xE8U, 0xCDU, 0x4EU, 0x00U,
			0x6BU, 0xA9U, 0x94U, 0xE5U, 0x7DU, 0xB7U, 0xA0U, 0xB3U,
			0x2CU, 0xD2U, 0xBFU, 0xF5U, 0x9DU, 0x65U, 0x29U, 0x7CU,
		};

		static const unsigned char okm[] = {
			0x0FU, 0x3DU, 0x6CU, 0xE9U, 0x06U, 0x8DU, 0x18U, 0x2FU,
			0x43U, 0x12U, 0x2BU, 0x34U, 0x83U, 0x77U, 0x1BU, 0x15U,
			0x5EU, 0x6CU, 0x48U, 0xCBU, 0xC7U, 0x9EU, 0x09U, 0x15U,
			0x8AU, 0x2EU, 0x9CU, 0xECU, 0xB6U, 0xCDU, 0x0CU, 0xB6U,
			0xD2U, 0xA8U, 0x90U, 0xD5U, 0x31U, 0xE0U, 0xC8U, 0x53U,
			0xFBU, 0x75U, 0xCFU, 0x8BU, 0x3EU, 0xA4U, 0x5BU, 0x0AU,
			0x05U, 0x43U, 0xD4U, 0x20U, 0x34U, 0x04U, 0xB7U, 0xB0U,
			0xF0U, 0x50U, 0x3DU, 0x9FU, 0x2AU, 0x2DU, 0x28U, 0x63U,
			0xE1U, 0xB2U, 0x17U, 0x82U, 0x35U, 0x90U, 0x3CU, 0x8DU,
			0x16U, 0xAAU, 0x03U, 0xE7U, 0x02U, 0x7AU, 0x5DU, 0x0CU,
			0x94U, 0xFAU, 0xEFU, 0xFAU, 0x1CU, 0x01U, 0x18U, 0xD7U,
			0xE9U, 0x37U, 0xD0U, 0xC5U, 0x91U, 0xF1U, 0x37U, 0x5CU,
			0x0BU, 0x08U, 0x76U, 0x78U, 0x16U, 0xA7U, 0x76U, 0x61U,
			0x9DU, 0x28U, 0x1BU, 0x6BU, 0x5EU, 0x04U, 0x01U, 0x00U,
			0x42U, 0x09U, 0xCEU, 0xA4U, 0xE9U, 0x17U, 0xD9U, 0x03U,
			0xC3U, 0x25U, 0x5AU, 0x0FU, 0x93U, 0x1EU, 0x6BU, 0xA1U,
			0xF3U, 0x37U, 0x78U, 0xD7U, 0x53U, 0x9AU, 0xF6U, 0x1EU,
			0x19U, 0x9BU, 0x41U, 0x2BU, 0xF9U, 0x9EU, 0xCAU, 0xC3U,
			0x13U, 0xC0U, 0xE7U, 0x6CU, 0xEDU, 0xEAU, 0xB7U, 0x8EU,
			0xD1U, 0x1CU, 0xABU, 0x46U, 0xD9U, 0x72U, 0xE3U, 0x21U,
			0x4FU, 0xE0U, 0x10U, 0xE1U, 0xF5U, 0xBEU, 0x6DU, 0xF9U,
			0x6FU, 0xB9U, 0x1BU, 0xC8U, 0xE8U, 0x79U, 0xF1U, 0xC9U,
			0x3BU, 0xE7U, 0x63U, 0xD8U, 0x73U, 0xEFU, 0xB1U, 0xDCU,
			0x79U, 0xBAU, 0xCCU, 0x53U, 0x20U, 0x9EU, 0x75U, 0xB8U,
			0x78U, 0xA8U, 0xF1U, 0x92U, 0xE6U, 0x04U, 0xA6U, 0x99U,
			0x11U, 0x56U, 0x2AU, 0xA0U, 0x8CU, 0x8DU, 0x29U, 0x9CU,
			0x6EU, 0x07U, 0xEAU, 0x9FU, 0x15U, 0x30U, 0x3BU, 0x2AU,
			0x80U, 0x99U, 0xDDU, 0x47U, 0xEBU, 0xB4U, 0x83U, 0xDDU,
			0xB5U, 0x6FU, 0x4CU, 0x4EU, 0xFBU, 0xE8U, 0x3CU, 0x78U,
			0xF5U, 0x44U, 0xC4U, 0x69U, 0xB6U, 0x29U, 0x1EU, 0xFCU,
			0xC1U, 0xE2U, 0x0BU, 0x2BU, 0x36U, 0xEFU, 0xF3U, 0x1DU,
			0x69U, 0x25U, 0x52U, 0xF3U, 0x84U, 0x73U, 0xC7U, 0x78U,
			0x1AU, 0x89U, 0x92U, 0xECU, 0xBFU, 0x62U, 0x17U, 0x33U,
			0x5BU, 0x00U, 0xD9U, 0x39U, 0x9DU, 0x06U, 0xFDU, 0x53U,
			0xF7U, 0x80U, 0x86U, 0x85U, 0xD3U, 0xD4U, 0x5BU, 0x37U,
			0x8BU, 0xA7U, 0x59U, 0x3DU, 0x6FU, 0xF2U, 0xD1U, 0x52U,
			0x0EU, 0xE7U, 0xCCU, 0x14U, 0x6FU, 0x7CU, 0xBBU, 0xA2U,
			0xB0U, 0x36U, 0x4EU, 0x66U, 0x78U, 0xCFU, 0x40U, 0xAFU,
			0x3AU, 0x15U, 0x94U, 0xBAU, 0x9EU, 0xA8U, 0x0CU, 0xF9U,
			0xC1U, 0x4CU, 0xCCU, 0xBFU, 0xBDU, 0x36U, 0xBAU, 0x28U,
			0x55U, 0xC5U, 0x32U, 0x21U, 0x23U, 0x4EU, 0x6DU, 0x72U,
			0xC0U, 0xBFU, 0xE0U, 0xF4U, 0x10U, 0x2CU, 0xC8U, 0x3DU,
			0xDFU, 0xADU, 0x3CU, 0xC9U, 0x8CU, 0xF6U, 0xCFU, 0x3EU,
			0x9CU, 0x79U, 0x63U, 0x9FU, 0x5AU, 0xF0U, 0x8CU, 0x81U,
			0x70U, 0xAAU, 0x7DU, 0x21U, 0x23U, 0x67U, 0xDAU, 0xA8U,
			0x33U, 0x93U, 0x51U, 0x05U, 0xE3U, 0x62U, 0xB2U, 0xF5U,
			0x6AU, 0xADU, 0xBBU, 0x4FU, 0x58U, 0x8FU, 0xBBU, 0x0BU,
			0xF6U, 0x0CU, 0xFAU, 0x26U, 0xE4U, 0xDBU, 0x33U, 0x80U,
			0x59U, 0xC1U, 0x3CU, 0xB6U, 0x68U, 0x55U, 0x7FU, 0xD5U,
			0xFDU, 0x98U, 0x1EU, 0xB4U, 0x6AU, 0x3DU, 0x59U, 0xC7U,
			0x42U, 0xBFU, 0x4DU, 0x8EU, 0x22U, 0x1CU, 0x12U, 0x9CU,
			0x6DU, 0xD7U, 0xA3U, 0xC2U, 0x1CU, 0x13U, 0xBEU, 0xBDU,
			0x8AU, 0xA9U, 0x19U, 0xEEU, 0x14U, 0x16U, 0x26U, 0x5CU,
			0x27U, 0x04U, 0x3AU, 0x7DU, 0xA5U, 0x6BU, 0x38U, 0xBAU,
			0x94U, 0x5BU, 0xF0U, 0x7FU, 0xF5U, 0x0BU, 0x10U, 0x72U,
			0xDCU, 0x6FU, 0x6CU, 0x65U, 0xB0U, 0x23U, 0xD1U, 0xD9U,
			0xFDU, 0xA1U, 0x47U, 0x18U, 0x66U, 0x27U, 0x3CU, 0x8BU,
			0xC8U, 0x46U, 0x2CU, 0xFBU, 0x3FU, 0x66U, 0xF0U, 0xB3U,
			0xA3U, 0x3DU, 0x63U, 0xE9U, 0x4EU, 0x0CU, 0xB4U, 0x15U,
			0x6AU, 0x31U, 0xF9U, 0xF8U, 0x03U, 0x19U, 0x4EU, 0x9AU,
			0x30U, 0xE4U, 0xF6U, 0x15U, 0xC8U, 0xC2U, 0x38U, 0x53U,
			0x63U, 0x4FU, 0x23U, 0xF9U, 0x06U, 0x8BU, 0xB9U, 0xB9U,
			0x1DU, 0xC5U, 0x34U, 0x31U, 0xB0U, 0xF1U, 0x94U, 0x7AU,
			0x89U, 0xFBU, 0x85U, 0x08U, 0xB4U, 0x9BU, 0x6DU, 0xE8U,
		};

		unsigned char result[sizeof prk + sizeof okm];

		(void) slog(LG_DEBUG, "%s: vector 8", MOWGLI_FUNC_NAME);

		if (! digest_hkdf_extract(DIGALG_SHA2_512, ikm, sizeof ikm, NULL, 0, result, sizeof prk))
		{
			(void) slog(LG_ERROR, "%s: vector 8: digest_hkdf_extract() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result, prk, sizeof prk) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 8: memcmp(3) mismatch on prk", MOWGLI_FUNC_NAME);
			return false;
		}
		if (! digest_hkdf_expand(DIGALG_SHA2_512, prk, sizeof prk, NULL, 0, result + sizeof prk, sizeof okm))
		{
			(void) slog(LG_ERROR, "%s: vector 8: digest_hkdf_expand() failed", MOWGLI_FUNC_NAME);
			return false;
		}
		if (memcmp(result + sizeof prk, okm, sizeof okm) != 0)
		{
			(void) slog(LG_ERROR, "%s: vector 8: memcmp(3) mismatch on okm", MOWGLI_FUNC_NAME);
			return false;
		}
	}

	return true;
}

static bool
digest_testsuite_run_pbkdf2_md5(void)
{
	static const unsigned char key[] = {
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
		0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
		0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
		0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
		0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
		0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
		0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
	};

	static const unsigned char salt[] = {
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
	};

	static const uint32_t iter = 4;

	static const unsigned char vector[] = {
		0x32U, 0xC9U, 0xF0U, 0xABU, 0xD3U, 0x16U, 0xBFU, 0x47U,
		0xDDU, 0x93U, 0xEAU, 0x90U, 0x6DU, 0x8DU, 0xBDU, 0xA2U,
		0x43U, 0x2CU, 0x86U, 0xDAU, 0xBBU, 0x98U, 0x11U, 0x83U,
		0x04U, 0x83U, 0x9DU, 0xABU, 0x37U, 0x88U, 0xC0U, 0x88U,
		0xB2U, 0x82U, 0xDBU, 0x8FU, 0x98U, 0xF7U, 0xF7U, 0x6DU,
		0xCFU, 0x59U, 0x61U, 0xEDU, 0xB2U, 0x19U, 0x80U, 0x0EU,
		0x6AU, 0x8EU, 0x83U, 0x43U, 0xD4U, 0x67U, 0x5AU, 0xE5U,
		0x58U, 0x44U, 0x03U, 0x66U, 0xAFU, 0x65U, 0xB2U, 0x5CU,
		0xB6U, 0x41U, 0xFBU, 0xF9U, 0xF0U, 0x8FU, 0xF7U, 0xC2U,
		0x21U, 0x90U, 0xCEU, 0x64U, 0x43U, 0x76U, 0xBEU, 0xCDU,
		0x96U, 0xAFU, 0x75U, 0xFEU, 0x5CU, 0x45U, 0xE9U, 0x92U,
	};

	unsigned char result[sizeof vector];

	(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

	if (! digest_oneshot_pbkdf2(DIGALG_MD5, key, sizeof key, salt, sizeof salt, iter, result, sizeof result))
		return false;

	if (memcmp(result, vector, sizeof vector) != 0)
		return false;

	return true;
}

static bool
digest_testsuite_run_pbkdf2_sha1(void)
{
	static const unsigned char key[] = {
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
		0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
		0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
		0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
		0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
		0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
		0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
	};

	static const unsigned char salt[] = {
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
	};

	static const uint32_t iter = 5;

	static const unsigned char vector[] = {
		0x77U, 0x86U, 0xB9U, 0x70U, 0xAEU, 0x65U, 0xEEU, 0xF6U,
		0xD0U, 0x21U, 0x3CU, 0x34U, 0xF8U, 0x01U, 0x6AU, 0x8CU,
		0xBAU, 0x46U, 0xEAU, 0x6BU, 0x08U, 0x8EU, 0x93U, 0x78U,
		0xFCU, 0xCFU, 0xAFU, 0x71U, 0x7BU, 0x7DU, 0x2CU, 0x10U,
		0xBFU, 0xCEU, 0xE3U, 0x30U, 0x4BU, 0x69U, 0x64U, 0xD3U,
		0xBDU, 0x4BU, 0x11U, 0x21U, 0xD1U, 0xC0U, 0xD3U, 0xB1U,
		0x4CU, 0x93U, 0x31U, 0xD5U, 0x46U, 0x6BU, 0xD7U, 0x5DU,
		0x22U, 0x0FU, 0x0FU, 0x17U, 0x2BU, 0x16U, 0xC7U, 0xC4U,
		0x16U, 0xEEU, 0xF1U, 0x19U, 0x44U, 0x87U, 0x5EU, 0x30U,
		0x49U, 0x67U, 0xD4U, 0x51U, 0x55U, 0xCDU, 0x63U, 0xC5U,
		0xA3U, 0xCAU, 0xA4U, 0x54U, 0xD7U, 0x46U, 0x85U, 0xE6U,
	};

	unsigned char result[sizeof vector];

	(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

	if (! digest_oneshot_pbkdf2(DIGALG_SHA1, key, sizeof key, salt, sizeof salt, iter, result, sizeof result))
		return false;

	if (memcmp(result, vector, sizeof vector) != 0)
		return false;

	return true;
}

static bool
digest_testsuite_run_pbkdf2_sha2_256(void)
{
	static const unsigned char key[] = {
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
		0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
		0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
		0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
		0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
		0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
		0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
		0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
		0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
		0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
		0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
		0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
		0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
		0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
		0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
		0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
		0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
		0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
		0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
		0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
		0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
		0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
		0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
		0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
		0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
		0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
		0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
		0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
		0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
		0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
		0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
		0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
		0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
		0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
		0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
		0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
		0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
		0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
		0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
		0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
		0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
		0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
		0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
		0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
		0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
	};

	static const unsigned char salt[] = {
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
	};

	static const uint32_t iter = 8;

	static const unsigned char vector[] = {
		0x23U, 0x70U, 0xC3U, 0x07U, 0x7BU, 0xDBU, 0x70U, 0x23U,
		0xD5U, 0x0DU, 0xC2U, 0x19U, 0xB4U, 0x4BU, 0xBCU, 0xC9U,
		0x32U, 0x16U, 0xA3U, 0x16U, 0xC0U, 0x0DU, 0x93U, 0x80U,
		0x2DU, 0xBEU, 0x6FU, 0x02U, 0xF6U, 0xC8U, 0xE3U, 0xFBU,
		0xC8U, 0x0AU, 0xECU, 0xA8U, 0xE7U, 0xCCU, 0x28U, 0x92U,
		0xBFU, 0x3DU, 0x76U, 0xB7U, 0x35U, 0xE6U, 0x07U, 0x8AU,
		0x8FU, 0x5DU, 0x82U, 0x6BU, 0x00U, 0x8DU, 0x88U, 0x46U,
		0x96U, 0xD2U, 0xE2U, 0xD9U, 0xE0U, 0x65U, 0x7FU, 0x58U,
		0xEBU, 0x90U, 0x7BU, 0xB2U, 0xB6U, 0x14U, 0x45U, 0xF7U,
		0xD6U, 0x5BU, 0xB0U, 0x24U, 0x25U, 0x32U, 0xF9U, 0xC2U,
		0x57U, 0x44U, 0x6CU, 0x52U, 0x60U, 0xD5U, 0xF3U, 0xDFU,
	};

	unsigned char result[sizeof vector];

	(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

	if (! digest_oneshot_pbkdf2(DIGALG_SHA2_256, key, sizeof key, salt, sizeof salt, iter, result, sizeof result))
		return false;

	if (memcmp(result, vector, sizeof vector) != 0)
		return false;

	return true;
}

static bool
digest_testsuite_run_pbkdf2_sha2_512(void)
{
	static const unsigned char key[] = {
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
		0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
		0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
		0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
		0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
		0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
		0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
		0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
		0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
		0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
		0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
		0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
		0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
		0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
		0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
		0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
		0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
		0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
		0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
		0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
		0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
		0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
		0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
		0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U,
		0x28U, 0x29U, 0x2AU, 0x2BU, 0x2CU, 0x2DU, 0x2EU, 0x2FU,
		0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U,
		0x38U, 0x39U, 0x3AU, 0x3BU, 0x3CU, 0x3DU, 0x3EU, 0x3FU,
		0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
		0x48U, 0x49U, 0x4AU, 0x4BU, 0x4CU, 0x4DU, 0x4EU, 0x4FU,
		0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
		0x58U, 0x59U, 0x5AU, 0x5BU, 0x5CU, 0x5DU, 0x5EU, 0x5FU,
		0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U,
		0x68U, 0x69U, 0x6AU, 0x6BU, 0x6CU, 0x6DU, 0x6EU, 0x6FU,
		0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U,
		0x78U, 0x79U, 0x7AU, 0x7BU, 0x7CU, 0x7DU, 0x7EU, 0x7FU,
		0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
		0x88U, 0x89U, 0x8AU, 0x8BU, 0x8CU, 0x8DU, 0x8EU, 0x8FU,
		0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
		0x98U, 0x99U, 0x9AU, 0x9BU, 0x9CU, 0x9DU, 0x9EU, 0x9FU,
		0xA0U, 0xA1U, 0xA2U, 0xA3U, 0xA4U, 0xA5U, 0xA6U, 0xA7U,
		0xA8U, 0xA9U, 0xAAU, 0xABU, 0xACU, 0xADU, 0xAEU, 0xAFU,
		0xB0U, 0xB1U, 0xB2U, 0xB3U, 0xB4U, 0xB5U, 0xB6U, 0xB7U,
		0xB8U, 0xB9U, 0xBAU, 0xBBU, 0xBCU, 0xBDU, 0xBEU, 0xBFU,
		0xC0U, 0xC1U, 0xC2U, 0xC3U, 0xC4U, 0xC5U, 0xC6U, 0xC7U,
		0xC8U, 0xC9U, 0xCAU, 0xCBU, 0xCCU, 0xCDU, 0xCEU, 0xCFU,
		0xD0U, 0xD1U, 0xD2U, 0xD3U, 0xD4U, 0xD5U, 0xD6U, 0xD7U,
		0xD8U, 0xD9U, 0xDAU, 0xDBU, 0xDCU, 0xDDU, 0xDEU, 0xDFU,
		0xE0U, 0xE1U, 0xE2U, 0xE3U, 0xE4U, 0xE5U, 0xE6U, 0xE7U,
		0xE8U, 0xE9U, 0xEAU, 0xEBU, 0xECU, 0xEDU, 0xEEU, 0xEFU,
		0xF0U, 0xF1U, 0xF2U, 0xF3U, 0xF4U, 0xF5U, 0xF6U, 0xF7U,
		0xF8U, 0xF9U, 0xFAU, 0xFBU, 0xFCU, 0xFDU, 0xFEU, 0xFFU,
	};

	static const unsigned char salt[] = {
		0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U,
		0x08U, 0x09U, 0x0AU, 0x0BU, 0x0CU, 0x0DU, 0x0EU, 0x0FU,
		0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
		0x18U, 0x19U, 0x1AU, 0x1BU, 0x1CU, 0x1DU, 0x1EU, 0x1FU,
	};

	static const uint32_t iter = 8;

	static const unsigned char vector[] = {
		0x66U, 0xBBU, 0x29U, 0x88U, 0x44U, 0xB5U, 0x05U, 0x94U,
		0xE9U, 0xAEU, 0x54U, 0x28U, 0x63U, 0xECU, 0x2FU, 0x2AU,
		0xD1U, 0xDBU, 0x39U, 0x4BU, 0x01U, 0x74U, 0x97U, 0x86U,
		0x78U, 0xF2U, 0x4DU, 0x85U, 0x92U, 0x22U, 0xCAU, 0x4DU,
		0x9EU, 0xDBU, 0x7CU, 0xBEU, 0xABU, 0x16U, 0x97U, 0x2DU,
		0xF8U, 0x15U, 0x5BU, 0xEAU, 0xE1U, 0xF8U, 0x05U, 0xFFU,
		0x14U, 0x2DU, 0x47U, 0x71U, 0x1CU, 0xA8U, 0xCFU, 0x60U,
		0xD0U, 0x8DU, 0xDFU, 0x93U, 0xD2U, 0xE0U, 0x94U, 0xBFU,
		0x7EU, 0xE8U, 0x57U, 0xB8U, 0xC0U, 0x3CU, 0xE4U, 0x63U,
		0x04U, 0x54U, 0x33U, 0xD7U, 0xAFU, 0x09U, 0xD6U, 0x1EU,
		0xE4U, 0x53U, 0x5FU, 0xB6U, 0x91U, 0xBFU, 0x7FU, 0x5AU,
	};

	unsigned char result[sizeof vector];

	(void) slog(LG_DEBUG, "%s: vector 1", MOWGLI_FUNC_NAME);

	if (! digest_oneshot_pbkdf2(DIGALG_SHA2_512, key, sizeof key, salt, sizeof salt, iter, result, sizeof result))
		return false;

	if (memcmp(result, vector, sizeof vector) != 0)
		return false;

	return true;
}

bool
digest_testsuite_run(void)
{
	if (! digest_testsuite_run_md5())
		return false;

	if (! digest_testsuite_run_hmac_md5())
		return false;

	if (! digest_testsuite_run_hkdf_md5())
		return false;

	if (! digest_testsuite_run_pbkdf2_md5())
		return false;


	if (! digest_testsuite_run_sha1())
		return false;

	if (! digest_testsuite_run_hmac_sha1())
		return false;

	if (! digest_testsuite_run_hkdf_sha1())
		return false;

	if (! digest_testsuite_run_pbkdf2_sha1())
		return false;


	if (! digest_testsuite_run_sha2_256())
		return false;

	if (! digest_testsuite_run_hmac_sha2_256())
		return false;

	if (! digest_testsuite_run_hkdf_sha2_256())
		return false;

	if (! digest_testsuite_run_pbkdf2_sha2_256())
		return false;


	if (! digest_testsuite_run_sha2_512())
		return false;

	if (! digest_testsuite_run_hmac_sha2_512())
		return false;

	if (! digest_testsuite_run_hkdf_sha2_512())
		return false;

	if (! digest_testsuite_run_pbkdf2_sha2_512())
		return false;


	return true;
}
