summaryrefslogtreecommitdiff
path: root/egg
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2011-02-24 10:35:58 +0100
committerStef Walter <stefw@collabora.co.uk>2011-02-27 07:43:43 +0100
commit54d4781a415b6e12d882667e373be851a435c5a3 (patch)
tree9bd4ca55f10531261949367f8457add228603c5a /egg
parentb6c94d5f4560d672f355366a7144056aaf764e8e (diff)
downloadgnome-keyring-54d4781a415b6e12d882667e373be851a435c5a3.tar.gz
Implement HKDF for transport encryption security.
This is to hash the results of the DH key agreement, since the generated key size rarely matches the size of our bulk encryption key size. * Add PKCS#11 algorithm CKM_G_HKDF_SHA256_DERIVE * Change DH code so it always generates keys of prime size. * Change CKM_DH_PKCS11_DERIVE mechanism to support truncating or expanding keys on its own (without help from underlying implementation) in accordance with PKCS#11. Although we no longer use this. * Add support for CKK_GENERIC_SECRET keys. * Update prompt code to use HKDF in key negotiation. * Add secret service dh-ietf1024-sha256-aes128-cbc-pkcs7 algo which replaces the previous.
Diffstat (limited to 'egg')
-rw-r--r--egg/Makefile.am2
-rw-r--r--egg/egg-dh.c16
-rw-r--r--egg/egg-dh.h2
-rw-r--r--egg/egg-hkdf.c109
-rw-r--r--egg/tests/test-dh.c70
-rw-r--r--egg/tests/test-hkdf.c345
6 files changed, 497 insertions, 47 deletions
diff --git a/egg/Makefile.am b/egg/Makefile.am
index 8b3bd242..3d8e1498 100644
--- a/egg/Makefile.am
+++ b/egg/Makefile.am
@@ -30,6 +30,7 @@ libegg_la_SOURCES = \
egg-dn.c egg-dn.h \
egg-error.h \
egg-hex.c egg-hex.h \
+ egg-hkdf.c egg-hkdf.h \
egg-libgcrypt.c egg-libgcrypt.h \
egg-mkdtemp.c egg-mkdtemp.h \
egg-oid.c egg-oid.h \
@@ -98,6 +99,7 @@ libegg_dbus_la_LIBADD = \
libegg_prompt_la_SOURCES = \
egg-dh.c egg-dh.h \
egg-hex.c egg-hex.h \
+ egg-hkdf.c egg-hkdf.h \
egg-libgcrypt.c egg-libgcrypt.h \
egg-padding.c egg-padding.h \
egg-secure-memory.c egg-secure-memory.h
diff --git a/egg/egg-dh.c b/egg/egg-dh.c
index d192aeb6..bed524e8 100644
--- a/egg/egg-dh.c
+++ b/egg/egg-dh.c
@@ -306,12 +306,11 @@ egg_dh_gen_pair (gcry_mpi_t prime, gcry_mpi_t base, guint bits,
gpointer
egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
- gcry_mpi_t prime, gsize bytes)
+ gcry_mpi_t prime, gsize *bytes)
{
gcry_error_t gcry;
guchar *value;
gsize n_value;
- gsize offset = 0;
gcry_mpi_t k;
gint bits;
@@ -329,11 +328,8 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
/* Write out the secret */
gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n_value, k);
g_return_val_if_fail (gcry == 0, NULL);
- if (n_value < bytes)
- offset = bytes - n_value;
- value = egg_secure_alloc (n_value + offset);
- memset (value, 0, n_value + offset);
- gcry = gcry_mpi_print (GCRYMPI_FMT_USG, value + offset, n_value, &n_value, k);
+ value = egg_secure_alloc (n_value);
+ gcry = gcry_mpi_print (GCRYMPI_FMT_USG, value, n_value, &n_value, k);
g_return_val_if_fail (gcry == 0, NULL);
#if DEBUG_DH_SECRET
@@ -342,11 +338,7 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
gcry_mpi_release (k);
#endif
- if (bytes != 0 && bytes < n_value) {
- offset = n_value - bytes;
- memmove (value, value + offset, bytes);
- egg_secure_clear (value + bytes, offset);
- }
+ *bytes = n_value;
#if DEBUG_DH_SECRET
gcry_mpi_scan (&k, GCRYMPI_FMT_USG, value, bytes, NULL);
diff --git a/egg/egg-dh.h b/egg/egg-dh.h
index cfdb3d01..ee315e27 100644
--- a/egg/egg-dh.h
+++ b/egg/egg-dh.h
@@ -45,6 +45,6 @@ gboolean egg_dh_gen_pair (gcry_mpi_t prime,
gpointer egg_dh_gen_secret (gcry_mpi_t peer,
gcry_mpi_t priv,
gcry_mpi_t prime,
- gsize bytes);
+ gsize *bytes);
#endif /* EGG_DH_H_ */
diff --git a/egg/egg-hkdf.c b/egg/egg-hkdf.c
new file mode 100644
index 00000000..eaa90fce
--- /dev/null
+++ b/egg/egg-hkdf.c
@@ -0,0 +1,109 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include "egg-hkdf.h"
+#include "egg-secure-memory.h"
+
+#include <gcrypt.h>
+
+#include <string.h>
+
+gboolean
+egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
+ gconstpointer salt, gsize n_salt, gconstpointer info,
+ gsize n_info, gpointer output, gsize n_output)
+{
+ gpointer alloc = NULL;
+ gpointer buffer = NULL;
+ gcry_md_hd_t md1, md2;
+ guint hash_len;
+ guchar i;
+ gint flags, algo;
+ gsize step, n_buffer;
+ guchar *at;
+ gcry_error_t gcry;
+
+ algo = gcry_md_map_name (hash_algo);
+ g_return_val_if_fail (algo != 0, FALSE);
+
+ hash_len = gcry_md_get_algo_dlen (algo);
+ g_return_val_if_fail (hash_len != 0, FALSE);
+ g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);
+
+ /* Buffer we need to for intermediate stuff */
+ if (gcry_is_secure (input)) {
+ flags = GCRY_MD_FLAG_SECURE;
+ buffer = gcry_malloc_secure (hash_len);
+ } else {
+ flags = 0;
+ buffer = gcry_malloc (hash_len);
+ }
+
+ g_return_val_if_fail (buffer, FALSE);
+ n_buffer = 0;
+
+ /* Salt defaults to hash_len zeros */
+ if (!salt) {
+ salt = alloc = g_malloc0 (hash_len);
+ n_salt = hash_len;
+ }
+
+ /* Step 1: Extract */
+ gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ gcry = gcry_md_setkey (md1, salt, n_salt);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ gcry_md_write (md1, input, n_input);
+
+ /* Step 2: Expand */
+ gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ gcry_md_close (md1);
+
+ at = output;
+ for (i = 1; i < 256; ++i) {
+ gcry_md_reset (md2);
+ gcry_md_write (md2, buffer, n_buffer);
+ gcry_md_write (md2, info, n_info);
+ gcry_md_write (md2, &i, 1);
+
+ n_buffer = hash_len;
+ memcpy (buffer, gcry_md_read (md2, algo), n_buffer);
+
+ step = MIN (n_buffer, n_output);
+ memcpy (at, buffer, step);
+ n_output -= step;
+ at += step;
+
+ if (!n_output)
+ break;
+ }
+
+ g_free (alloc);
+ gcry_free (buffer);
+ return TRUE;
+}
diff --git a/egg/tests/test-dh.c b/egg/tests/test-dh.c
index 6a2b37f5..4a62fd17 100644
--- a/egg/tests/test-dh.c
+++ b/egg/tests/test-dh.c
@@ -27,22 +27,24 @@
#include "egg-secure-memory.h"
#include "egg-testing.h"
+#include <glib.h>
+#include <gcrypt.h>
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <gcrypt.h>
-
EGG_SECURE_GLIB_DEFINITIONS ();
static void
-test_perform (void)
+test_dh_perform (void)
{
gcry_mpi_t p, g;
gcry_mpi_t x1, X1;
gcry_mpi_t x2, X2;
gpointer k1, k2;
gboolean ret;
+ gsize n1, n2;
/* Load up the parameters */
if (!egg_dh_default_params ("ietf-ike-grp-modp-768", &p, &g))
@@ -55,13 +57,14 @@ test_perform (void)
g_assert (ret);
/* Calculate keys */
- k1 = egg_dh_gen_secret (X2, x1, p, 96);
+ k1 = egg_dh_gen_secret (X2, x1, p, &n1);
g_assert (k1);
- k2 = egg_dh_gen_secret (X1, x2, p, 96);
+ k2 = egg_dh_gen_secret (X1, x2, p, &n2);
g_assert (k2);
/* Keys must be the same */
- g_assert (memcmp (k1, k2, 96) == 0);
+ egg_assert_cmpsize (n1, ==, n2);
+ g_assert (memcmp (k1, k2, n1) == 0);
gcry_mpi_release (p);
gcry_mpi_release (g);
@@ -74,7 +77,7 @@ test_perform (void)
}
static void
-test_short_pair (void)
+test_dh_short_pair (void)
{
gcry_mpi_t p, g;
gcry_mpi_t x1, X1;
@@ -97,7 +100,7 @@ test_short_pair (void)
}
static void
-test_dh_default (const gchar *name, guint bits)
+check_dh_default (const gchar *name, guint bits)
{
gboolean ret;
gcry_mpi_t p, g, check;
@@ -132,50 +135,49 @@ test_dh_default (const gchar *name, guint bits)
}
static void
-test_default_768 (void)
+test_dh_default_768 (void)
{
- test_dh_default ("ietf-ike-grp-modp-768", 768);
+ check_dh_default ("ietf-ike-grp-modp-768", 768);
}
static void
-test_default_1024 (void)
+test_dh_default_1024 (void)
{
- test_dh_default ("ietf-ike-grp-modp-1024", 1024);
+ check_dh_default ("ietf-ike-grp-modp-1024", 1024);
}
static void
-test_default_1536 (void)
+test_dh_default_1536 (void)
{
- test_dh_default ("ietf-ike-grp-modp-1536", 1536);
+ check_dh_default ("ietf-ike-grp-modp-1536", 1536);
}
-
static void
-test_default_2048 (void)
+test_dh_default_2048 (void)
{
- test_dh_default ("ietf-ike-grp-modp-2048", 2048);
+ check_dh_default ("ietf-ike-grp-modp-2048", 2048);
}
static void
-test_default_3072 (void)
+test_dh_default_3072 (void)
{
- test_dh_default ("ietf-ike-grp-modp-3072", 3072);
+ check_dh_default ("ietf-ike-grp-modp-3072", 3072);
}
static void
-test_default_4096 (void)
+test_dh_default_4096 (void)
{
- test_dh_default ("ietf-ike-grp-modp-4096", 4096);
+ check_dh_default ("ietf-ike-grp-modp-4096", 4096);
}
static void
-test_default_8192 (void)
+test_dh_default_8192 (void)
{
- test_dh_default ("ietf-ike-grp-modp-8192", 8192);
+ check_dh_default ("ietf-ike-grp-modp-8192", 8192);
}
static void
-test_default_bad (void)
+test_dh_default_bad (void)
{
gboolean ret;
gcry_mpi_t p, g;
@@ -189,16 +191,16 @@ main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
- g_test_add_func ("/dh/perform", test_perform);
- g_test_add_func ("/dh/short_pair", test_short_pair);
- g_test_add_func ("/dh/default_768", test_default_768);
- g_test_add_func ("/dh/default_1024", test_default_1024);
- g_test_add_func ("/dh/default_1536", test_default_1536);
- g_test_add_func ("/dh/default_2048", test_default_2048);
- g_test_add_func ("/dh/default_3072", test_default_3072);
- g_test_add_func ("/dh/default_4096", test_default_4096);
- g_test_add_func ("/dh/default_8192", test_default_8192);
- g_test_add_func ("/dh/default_bad", test_default_bad);
+ g_test_add_func ("/dh/perform", test_dh_perform);
+ g_test_add_func ("/dh/short-pair", test_dh_short_pair);
+ g_test_add_func ("/dh/default-768", test_dh_default_768);
+ g_test_add_func ("/dh/default-1024", test_dh_default_1024);
+ g_test_add_func ("/dh/default-1536", test_dh_default_1536);
+ g_test_add_func ("/dh/default-2048", test_dh_default_2048);
+ g_test_add_func ("/dh/default-3072", test_dh_default_3072);
+ g_test_add_func ("/dh/default-4096", test_dh_default_4096);
+ g_test_add_func ("/dh/default-8192", test_dh_default_8192);
+ g_test_add_func ("/dh/default-bad", test_dh_default_bad);
return g_test_run ();
}
diff --git a/egg/tests/test-hkdf.c b/egg/tests/test-hkdf.c
new file mode 100644
index 00000000..44c463d3
--- /dev/null
+++ b/egg/tests/test-hkdf.c
@@ -0,0 +1,345 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* test-hkdf.c: Test egg-hkdf.c
+
+ Copyright (C) 2011 Collabora Ltd.
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stef@collabora.co.uk>
+*/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "egg-hkdf.h"
+#include "egg-secure-memory.h"
+#include "egg-testing.h"
+
+#include <gcrypt.h>
+
+EGG_SECURE_GLIB_DEFINITIONS ();
+
+static void
+test_hkdf_test_case_1 (void)
+{
+ /* RFC 5869: A.1 Test Case 1 */
+ const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
+ const guchar salt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c };
+ const guchar info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9 };
+ const guchar okm[] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
+ 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
+ 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
+ 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
+ 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
+ 0x58, 0x65 };
+ guchar buffer[sizeof (okm)];
+ gboolean ret;
+
+ egg_assert_cmpsize (sizeof (ikm), ==, 22);
+ egg_assert_cmpsize (sizeof (salt), ==, 13);
+ egg_assert_cmpsize (sizeof (info), ==, 10);
+ egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+ memset (buffer, 0, sizeof (buffer));
+ ret = egg_hkdf_perform ("sha256",
+ ikm, sizeof (ikm),
+ salt, sizeof (salt),
+ info, sizeof (info),
+ buffer, sizeof (buffer));
+ g_assert (ret);
+ egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_2 (void)
+{
+ /* RFC 5869: A.2 Test Case 2 */
+ const guchar ikm[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
+ const guchar salt[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf };
+ const guchar info[] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
+ const guchar okm[] = { 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1,
+ 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
+ 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
+ 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
+ 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72,
+ 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
+ 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
+ 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
+ 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
+ 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
+ 0x1d, 0x87 };
+ guchar buffer[sizeof (okm)];
+ gboolean ret;
+
+ egg_assert_cmpsize (sizeof (ikm), ==, 80);
+ egg_assert_cmpsize (sizeof (salt), ==, 80);
+ egg_assert_cmpsize (sizeof (info), ==, 80);
+ egg_assert_cmpsize (sizeof (okm), ==, 82);
+
+ memset (buffer, 0, sizeof (buffer));
+ ret = egg_hkdf_perform ("sha256",
+ ikm, sizeof (ikm),
+ salt, sizeof (salt),
+ info, sizeof (info),
+ buffer, sizeof (buffer));
+ g_assert (ret);
+ egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_3 (void)
+{
+ /* RFC 5869: A.3 Test Case 3 */
+ const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,};
+ const guchar salt[] = { };
+ const guchar info[] = { };
+ const guchar okm[] = { 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f,
+ 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
+ 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
+ 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
+ 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a,
+ 0x96, 0xc8 };
+ guchar buffer[sizeof (okm)];
+ gboolean ret;
+
+ egg_assert_cmpsize (sizeof (ikm), ==, 22);
+ egg_assert_cmpsize (sizeof (salt), ==, 0);
+ egg_assert_cmpsize (sizeof (info), ==, 0);
+ egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+ memset (buffer, 0, sizeof (buffer));
+ ret = egg_hkdf_perform ("sha256",
+ ikm, sizeof (ikm),
+ salt, sizeof (salt),
+ info, sizeof (info),
+ buffer, sizeof (buffer));
+ g_assert (ret);
+ egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_4 (void)
+{
+ /* RFC 5869: A.4 Test Case 4 */
+ const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b };
+ const guchar salt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c };
+ const guchar info[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9 };
+ const guchar okm[] = { 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69,
+ 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81,
+ 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
+ 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2,
+ 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3,
+ 0xf8, 0x96 };
+ guchar buffer[sizeof (okm)];
+ gboolean ret;
+
+ egg_assert_cmpsize (sizeof (ikm), ==, 11);
+ egg_assert_cmpsize (sizeof (salt), ==, 13);
+ egg_assert_cmpsize (sizeof (info), ==, 10);
+ egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+ memset (buffer, 0, sizeof (buffer));
+ ret = egg_hkdf_perform ("sha1",
+ ikm, sizeof (ikm),
+ salt, sizeof (salt),
+ info, sizeof (info),
+ buffer, sizeof (buffer));
+ g_assert (ret);
+ egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_5 (void)
+{
+ /* RFC 5869: A.5 Test Case 5 */
+ const guchar ikm[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
+ const guchar salt[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf };
+ const guchar info[] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
+ const guchar okm[] = { 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7,
+ 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb,
+ 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
+ 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe,
+ 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3,
+ 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c,
+ 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed,
+ 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e,
+ 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43,
+ 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52,
+ 0xd3, 0xb4 };
+ guchar buffer[sizeof (okm)];
+ gboolean ret;
+
+ egg_assert_cmpsize (sizeof (ikm), ==, 80);
+ egg_assert_cmpsize (sizeof (salt), ==, 80);
+ egg_assert_cmpsize (sizeof (info), ==, 80);
+ egg_assert_cmpsize (sizeof (okm), ==, 82);
+
+ memset (buffer, 0, sizeof (buffer));
+ ret = egg_hkdf_perform ("sha1",
+ ikm, sizeof (ikm),
+ salt, sizeof (salt),
+ info, sizeof (info),
+ buffer, sizeof (buffer));
+ g_assert (ret);
+ egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_6 (void)
+{
+ /* RFC 5869: A.6 Test Case 6 */
+ const guchar ikm[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
+ const guchar salt[] = { };
+ const guchar info[] = { };
+ const guchar okm[] = { 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61,
+ 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06,
+ 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
+ 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0,
+ 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3,
+ 0x49, 0x18 };
+ guchar buffer[sizeof (okm)];
+ gboolean ret;
+
+ egg_assert_cmpsize (sizeof (ikm), ==, 22);
+ egg_assert_cmpsize (sizeof (salt), ==, 0);
+ egg_assert_cmpsize (sizeof (info), ==, 0);
+ egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+ memset (buffer, 0, sizeof (buffer));
+ ret = egg_hkdf_perform ("sha1",
+ ikm, sizeof (ikm),
+ salt, sizeof (salt),
+ info, sizeof (info),
+ buffer, sizeof (buffer));
+ g_assert (ret);
+ egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+static void
+test_hkdf_test_case_7 (void)
+{
+ /* RFC 5869: A.7 Test Case 7 */
+ const guchar ikm[] = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c };
+ const guchar *salt = NULL;
+ const guchar info[] = { };
+ const guchar okm[] = { 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3,
+ 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a,
+ 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
+ 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5,
+ 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac,
+ 0xfc, 0x48 };
+ guchar buffer[sizeof (okm)];
+ gboolean ret;
+
+ egg_assert_cmpsize (sizeof (ikm), ==, 22);
+ egg_assert_cmpsize (sizeof (info), ==, 0);
+ egg_assert_cmpsize (sizeof (okm), ==, 42);
+
+ memset (buffer, 0, sizeof (buffer));
+ ret = egg_hkdf_perform ("sha1",
+ ikm, sizeof (ikm),
+ salt, sizeof (salt),
+ info, sizeof (info),
+ buffer, sizeof (buffer));
+ g_assert (ret);
+ egg_assert_cmpmem (buffer, sizeof (buffer), ==, okm, sizeof (okm));
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/hkdf/test-case-1", test_hkdf_test_case_1);
+ g_test_add_func ("/hkdf/test-case-2", test_hkdf_test_case_2);
+ g_test_add_func ("/hkdf/test-case-3", test_hkdf_test_case_3);
+ g_test_add_func ("/hkdf/test-case-4", test_hkdf_test_case_4);
+ g_test_add_func ("/hkdf/test-case-5", test_hkdf_test_case_5);
+ g_test_add_func ("/hkdf/test-case-6", test_hkdf_test_case_6);
+ g_test_add_func ("/hkdf/test-case-7", test_hkdf_test_case_7);
+
+ return g_test_run ();
+}