Makefile.in.in
missing
stamp*
+.settings
+.project
+.cproject
/po/POTFILES
cd $srcdir
PROJECT=gsecret
TEST_TYPE=-f
-FILE=library/gsecret-data.c
+FILE=library/gsecret-value.c
DIE=0
AC_INIT([gsecret],[0.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=gsecret])
-AC_CONFIG_SRCDIR([library/gsecret-data.c])
+AC_CONFIG_SRCDIR([library/gsecret-value.c])
AC_CONFIG_HEADERS([config.h])
dnl Other initialization
dnl *****************************
dnl *** done ***
dnl *****************************
-AC_CONFIG_FILES([Makefile
- egg/Makefile
- po/Makefile.in
- po/Makefile
- library/Makefile
- ])
+AC_CONFIG_FILES([
+ Makefile
+ egg/Makefile
+ po/Makefile.in
+ po/Makefile
+ library/Makefile
+ library/tests/Makefile
+])
AC_OUTPUT
-I$(top_srcdir)
libegg_la_SOURCES = \
+ egg-dh.c egg-dh.h \
+ egg-hkdf.c egg-hkdf.h \
egg-secure-memory.c egg-secure-memory.h \
$(BUILT_SOURCES)
--- /dev/null
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2009 Stefan Walter
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include "egg-dh.h"
+#include "egg-secure-memory.h"
+
+/* Enabling this is a complete security compromise */
+#define DEBUG_DH_SECRET 0
+
+EGG_SECURE_DECLARE (dh);
+
+typedef struct _DHGroup {
+ const gchar *name;
+ guint bits;
+ const guchar *prime;
+ gsize n_prime;
+ const guchar base[1];
+ gsize n_base;
+} DHGroup;
+
+static const guchar dh_group_768_prime[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static const guchar dh_group_1024_prime[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static const guchar dh_group_1536_prime[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static const guchar dh_group_2048_prime[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static const guchar dh_group_3072_prime[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static const guchar dh_group_4096_prime[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static const guchar dh_group_8192_prime[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
+ 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
+ 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
+ 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
+ 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
+ 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
+ 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
+ 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
+ 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
+ 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
+ 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
+ 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
+ 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
+ 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
+ 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
+ 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
+ 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
+ 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
+ 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
+ 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
+ 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
+ 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
+ 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static const DHGroup dh_groups[] = {
+ {
+ "ietf-ike-grp-modp-768", 768,
+ dh_group_768_prime, G_N_ELEMENTS (dh_group_768_prime),
+ { 0x02 }, 1
+ },
+ {
+ "ietf-ike-grp-modp-1024", 1024,
+ dh_group_1024_prime, G_N_ELEMENTS (dh_group_1024_prime),
+ { 0x02 }, 1
+ },
+ {
+ "ietf-ike-grp-modp-1536", 1536,
+ dh_group_1536_prime, G_N_ELEMENTS (dh_group_1536_prime),
+ { 0x02 }, 1
+ },
+ {
+ "ietf-ike-grp-modp-2048", 2048,
+ dh_group_2048_prime, G_N_ELEMENTS (dh_group_2048_prime),
+ { 0x02 }, 1
+ },
+ {
+ "ietf-ike-grp-modp-3072", 3072,
+ dh_group_3072_prime, G_N_ELEMENTS (dh_group_3072_prime),
+ { 0x02 }, 1
+ },
+ {
+ "ietf-ike-grp-modp-4096", 4096,
+ dh_group_4096_prime, G_N_ELEMENTS (dh_group_4096_prime),
+ { 0x02 }, 1
+ },
+ {
+ "ietf-ike-grp-modp-8192", 8192,
+ dh_group_8192_prime, G_N_ELEMENTS (dh_group_8192_prime),
+ { 0x02 }, 1
+ },
+ {
+ NULL
+ }
+};
+
+gboolean
+egg_dh_default_params_raw (const gchar *name, gconstpointer *prime,
+ gsize *n_prime, gconstpointer *base, gsize *n_base)
+{
+ const DHGroup *group;
+
+ g_return_val_if_fail (name, FALSE);
+ g_return_val_if_fail (prime, FALSE);
+ g_return_val_if_fail (n_prime, FALSE);
+ g_return_val_if_fail (base, FALSE);
+ g_return_val_if_fail (n_base, FALSE);
+
+ for (group = dh_groups; group->name; ++group) {
+ if (g_str_equal (group->name, name)) {
+ *prime = group->prime;
+ *n_prime = group->n_prime;
+ *base = group->base;
+ *n_base = group->n_base;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+gboolean
+egg_dh_default_params (const gchar *name, gcry_mpi_t *prime, gcry_mpi_t *base)
+{
+ const DHGroup *group;
+ gcry_error_t gcry;
+
+ g_return_val_if_fail (name, FALSE);
+
+ for (group = dh_groups; group->name; ++group) {
+ if (g_str_equal (group->name, name)) {
+ if (prime) {
+ gcry = gcry_mpi_scan (prime, GCRYMPI_FMT_USG, group->prime, group->n_prime, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ g_return_val_if_fail (gcry_mpi_get_nbits (*prime) == group->bits, FALSE);
+ }
+ if (base) {
+ gcry = gcry_mpi_scan (base, GCRYMPI_FMT_USG, group->base, group->n_base, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ }
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+gboolean
+egg_dh_gen_pair (gcry_mpi_t prime, gcry_mpi_t base, guint bits,
+ gcry_mpi_t *pub, gcry_mpi_t *priv)
+{
+ guint pbits;
+
+ g_return_val_if_fail (prime, FALSE);
+ g_return_val_if_fail (base, FALSE);
+ g_return_val_if_fail (pub, FALSE);
+ g_return_val_if_fail (priv, FALSE);
+
+ pbits = gcry_mpi_get_nbits (prime);
+ g_return_val_if_fail (pbits > 1, FALSE);
+
+ if (bits == 0) {
+ bits = pbits;
+ } else if (bits > pbits) {
+ g_return_val_if_reached (FALSE);
+ }
+
+ /*
+ * Generate a strong random number of bits, and not zero.
+ * gcry_mpi_randomize bumps up to the next byte. Since we
+ * need to have a value less than half of prime, we make sure
+ * we bump down.
+ */
+ *priv = gcry_mpi_snew (bits);
+ g_return_val_if_fail (*priv, FALSE);
+ while (gcry_mpi_cmp_ui (*priv, 0) == 0)
+ gcry_mpi_randomize (*priv, bits, GCRY_STRONG_RANDOM);
+
+ /* Secret key value must be less than half of p */
+ if (gcry_mpi_get_nbits (*priv) > bits)
+ gcry_mpi_clear_highbit (*priv, bits);
+ if (gcry_mpi_get_nbits (*priv) > pbits - 1)
+ gcry_mpi_clear_highbit (*priv, pbits - 1);
+ g_assert (gcry_mpi_cmp (prime, *priv) > 0);
+
+ *pub = gcry_mpi_new (gcry_mpi_get_nbits (*priv));
+ g_return_val_if_fail (*pub, FALSE);
+ gcry_mpi_powm (*pub, base, *priv, prime);
+
+ return TRUE;
+}
+
+gpointer
+egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv,
+ gcry_mpi_t prime, gsize *bytes)
+{
+ gcry_error_t gcry;
+ guchar *value;
+ gsize n_value;
+ gcry_mpi_t k;
+ gint bits;
+
+ g_return_val_if_fail (peer, NULL);
+ g_return_val_if_fail (priv, NULL);
+ g_return_val_if_fail (prime, NULL);
+
+ bits = gcry_mpi_get_nbits (prime);
+ g_return_val_if_fail (bits >= 0, NULL);
+
+ k = gcry_mpi_snew (bits);
+ g_return_val_if_fail (k, NULL);
+ gcry_mpi_powm (k, peer, priv, prime);
+
+ /* Write out the secret */
+ gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n_value, k);
+ g_return_val_if_fail (gcry == 0, NULL);
+ 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
+ g_printerr ("DH SECRET: ");
+ gcry_mpi_dump (k);
+ gcry_mpi_release (k);
+#endif
+
+ *bytes = n_value;
+
+#if DEBUG_DH_SECRET
+ gcry_mpi_scan (&k, GCRYMPI_FMT_USG, value, bytes, NULL);
+ g_printerr ("RAW SECRET: ");
+ gcry_mpi_dump (k);
+ gcry_mpi_release (k);
+#endif
+
+ return value;
+}
--- /dev/null
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2009 Stefan Walter
+ *
+ * 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.
+ */
+
+#ifndef EGG_DH_H_
+#define EGG_DH_H_
+
+#include <glib.h>
+
+#include <gcrypt.h>
+
+gboolean egg_dh_default_params (const gchar *name,
+ gcry_mpi_t *prime,
+ gcry_mpi_t *base);
+
+gboolean egg_dh_default_params_raw (const gchar *name,
+ gconstpointer *prime,
+ gsize *n_prime,
+ gconstpointer *base,
+ gsize *n_base);
+
+gboolean egg_dh_gen_pair (gcry_mpi_t prime,
+ gcry_mpi_t base,
+ guint bits,
+ gcry_mpi_t *pub,
+ gcry_mpi_t *priv);
+
+gpointer egg_dh_gen_secret (gcry_mpi_t peer,
+ gcry_mpi_t priv,
+ gcry_mpi_t prime,
+ gsize *bytes);
+
+#endif /* EGG_DH_H_ */
--- /dev/null
+/*
+ * 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 | flags);
+ 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 | flags);
+ 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;
+}
--- /dev/null
+/*
+ * 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>
+ */
+
+#ifndef EGG_HKDF_H_
+#define EGG_HKDF_H_
+
+#include <glib.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);
+
+#endif /* EGG_HKDF_H_ */
typedef struct _Cell {
word_t *words; /* Pointer to secure memory */
size_t n_words; /* Amount of secure memory in words */
- size_t allocated; /* Amount actually requested by app, in bytes, 0 if unused */
- struct _Cell *next; /* Next in unused memory ring, or NULL if used */
- struct _Cell *prev; /* Previous in unused memory ring, or NULL if used */
+ size_t requested; /* Amount actually requested by app, in bytes, 0 if unused */
+ const char *tag; /* Tag which describes the allocation */
+ struct _Cell *next; /* Next in memory ring */
+ struct _Cell *prev; /* Previous in memory ring */
} Cell;
/*
* A block of secure memory. This structure is the header in that block.
*/
typedef struct _Block {
- word_t *words; /* Actual memory hangs off here */
- size_t n_words; /* Number of words in block */
- size_t used; /* Number of used allocations */
- struct _Cell* unused; /* Ring of unused allocations */
- struct _Block *next; /* Next block in list */
+ word_t *words; /* Actual memory hangs off here */
+ size_t n_words; /* Number of words in block */
+ size_t n_used; /* Number of used allocations */
+ struct _Cell* used_cells; /* Ring of used allocations */
+ struct _Cell* unused_cells; /* Ring of unused allocations */
+ struct _Block *next; /* Next block in list */
} Block;
/* -----------------------------------------------------------------------------
unused_push (&pool->unused, item);
}
+#ifndef G_DISABLE_ASSERT
+
static int
pool_valid (void* item)
{
return 0;
}
+#endif /* G_DISABLE_ASSERT */
+
/* -----------------------------------------------------------------------------
* SEC ALLOCATION
*
}
static void*
-sec_alloc (Block *block, size_t length)
+sec_alloc (Block *block,
+ const char *tag,
+ size_t length)
{
Cell *cell, *other;
size_t n_words;
ASSERT (block);
ASSERT (length);
+ ASSERT (tag);
- if (!block->unused)
+ if (!block->unused_cells)
return NULL;
/*
n_words = sec_size_to_words (length) + 2;
/* Look for a cell of at least our required size */
- cell = block->unused;
+ cell = block->unused_cells;
while (cell->n_words < n_words) {
cell = cell->next;
- if (cell == block->unused) {
+ if (cell == block->unused_cells) {
cell = NULL;
break;
}
if (!cell)
return NULL;
-
- ASSERT (cell->allocated == 0);
+
+ ASSERT (cell->tag == NULL);
+ ASSERT (cell->requested == 0);
ASSERT (cell->prev);
ASSERT (cell->words);
sec_check_guards (cell);
}
if (cell->next)
- sec_remove_cell_ring (&block->unused, cell);
-
- ++block->used;
- cell->allocated = length;
+ sec_remove_cell_ring (&block->unused_cells, cell);
+
+ ++block->n_used;
+ cell->tag = tag;
+ cell->requested = length;
+ sec_insert_cell_ring (&block->used_cells, cell);
memory = sec_cell_to_memory (cell);
#ifdef WITH_VALGRIND
#endif
sec_check_guards (cell);
- sec_clear_memory (memory, 0, cell->allocated);
+ sec_clear_memory (memory, 0, cell->requested);
sec_check_guards (cell);
- ASSERT (cell->next == NULL);
- ASSERT (cell->prev == NULL);
- ASSERT (cell->allocated > 0);
+ ASSERT (cell->requested > 0);
+ ASSERT (cell->tag != NULL);
+
+ /* Remove from the used cell ring */
+ sec_remove_cell_ring (&block->used_cells, cell);
/* Find previous unallocated neighbor, and merge if possible */
other = sec_neighbor_before (block, cell);
- if (other && other->allocated == 0) {
+ if (other && other->requested == 0) {
+ ASSERT (other->tag == NULL);
ASSERT (other->next && other->prev);
other->n_words += cell->n_words;
sec_write_guards (other);
/* Find next unallocated neighbor, and merge if possible */
other = sec_neighbor_after (block, cell);
- if (other && other->allocated == 0) {
+ if (other && other->requested == 0) {
+ ASSERT (other->tag == NULL);
ASSERT (other->next && other->prev);
other->n_words += cell->n_words;
other->words = cell->words;
if (cell->next)
- sec_remove_cell_ring (&block->unused, cell);
+ sec_remove_cell_ring (&block->unused_cells, cell);
sec_write_guards (other);
pool_free (cell);
cell = other;
/* Add to the unused list if not already there */
if (!cell->next)
- sec_insert_cell_ring (&block->unused, cell);
-
- cell->allocated = 0;
- --block->used;
+ sec_insert_cell_ring (&block->unused_cells, cell);
+
+ cell->tag = NULL;
+ cell->requested = 0;
+ --block->n_used;
return NULL;
}
static void*
-sec_realloc (Block *block, void *memory, size_t length)
+sec_realloc (Block *block,
+ const char *tag,
+ void *memory,
+ size_t length)
{
Cell *cell, *other;
word_t *word;
size_t n_words;
size_t valid;
void *alloc;
-
+
/* Standard realloc behavior, should have been handled elsewhere */
ASSERT (memory != NULL);
ASSERT (length > 0);
+ ASSERT (tag != NULL);
/* Dig out where the meta should be */
word = memory;
/* Validate that it's actually for real */
sec_check_guards (cell);
- ASSERT (cell->allocated > 0);
- ASSERT (cell->next == NULL);
- ASSERT (cell->prev == NULL);
-
+ ASSERT (cell->requested > 0);
+ ASSERT (cell->tag != NULL);
+
/* The amount of valid data */
- valid = cell->allocated;
-
+ valid = cell->requested;
+
/* How many words we actually want */
n_words = sec_size_to_words (length) + 2;
if (n_words <= cell->n_words) {
/* TODO: No shrinking behavior yet */
- cell->allocated = length;
+ cell->requested = length;
alloc = sec_cell_to_memory (cell);
#ifdef WITH_VALGRIND
/* See if we have a neighbor who can give us some memory */
other = sec_neighbor_after (block, cell);
- if (!other || other->allocated != 0)
+ if (!other || other->requested != 0)
break;
/* Eat the whole neighbor if not too big */
if (n_words - cell->n_words + WASTE >= other->n_words) {
cell->n_words += other->n_words;
sec_write_guards (cell);
- sec_remove_cell_ring (&block->unused, other);
+ sec_remove_cell_ring (&block->unused_cells, other);
pool_free (other);
/* Steal from the neighbor */
}
if (cell->n_words >= n_words) {
- cell->allocated = length;
+ cell->requested = length;
+ cell->tag = tag;
alloc = sec_cell_to_memory (cell);
-
+
#ifdef WITH_VALGRIND
VALGRIND_MAKE_MEM_DEFINED (alloc, length);
#endif
return sec_clear_memory (alloc, valid, length);
}
-
+
/* That didn't work, try alloc/free */
- alloc = sec_alloc (block, length);
+ alloc = sec_alloc (block, tag, length);
if (alloc) {
memcpy (alloc, memory, valid);
sec_free (block, memory);
cell = *word;
sec_check_guards (cell);
- ASSERT (cell->next == NULL);
- ASSERT (cell->prev == NULL);
- ASSERT (cell->allocated > 0);
-
+ ASSERT (cell->requested > 0);
+ ASSERT (cell->tag != NULL);
+
#ifdef WITH_VALGRIND
VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t));
#endif
-
- return cell->allocated;
+
+ return cell->requested;
}
static void
sec_check_guards (cell);
/* Is it an allocated block? */
- if (cell->allocated > 0) {
- ASSERT (cell->next == NULL);
- ASSERT (cell->prev == NULL);
- ASSERT (cell->allocated <= (cell->n_words - 2) * sizeof (word_t));
+ if (cell->requested > 0) {
+ ASSERT (cell->tag != NULL);
+ ASSERT (cell->next != NULL);
+ ASSERT (cell->prev != NULL);
+ ASSERT (cell->next->prev == cell);
+ ASSERT (cell->prev->next == cell);
+ ASSERT (cell->requested <= (cell->n_words - 2) * sizeof (word_t));
/* An unused block */
} else {
- ASSERT (cell->next);
- ASSERT (cell->prev);
+ ASSERT (cell->tag == NULL);
+ ASSERT (cell->next != NULL);
+ ASSERT (cell->prev != NULL);
ASSERT (cell->next->prev == cell);
ASSERT (cell->prev->next == cell);
}
*/
static void*
-sec_acquire_pages (size_t *sz)
+sec_acquire_pages (size_t *sz,
+ const char *during_tag)
{
void *pages;
unsigned long pgsize;
ASSERT (sz);
ASSERT (*sz);
+ ASSERT (during_tag);
/* Make sure sz is a multiple of the page size */
pgsize = getpagesize ();
pages = mmap (0, *sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
if (pages == MAP_FAILED) {
if (lock_warning && egg_secure_warnings)
- fprintf (stderr, "couldn't map %lu bytes of private memory: %s\n",
- (unsigned long)*sz, strerror (errno));
+ fprintf (stderr, "couldn't map %lu bytes of memory (%s): %s\n",
+ (unsigned long)*sz, during_tag, strerror (errno));
lock_warning = 0;
return NULL;
}
if (mlock (pages, *sz) < 0) {
if (lock_warning && egg_secure_warnings && errno != EPERM) {
- fprintf (stderr, "couldn't lock %lu bytes of private memory: %s\n",
- (unsigned long)*sz, strerror (errno));
+ fprintf (stderr, "couldn't lock %lu bytes of memory (%s): %s\n",
+ (unsigned long)*sz, during_tag, strerror (errno));
lock_warning = 0;
}
munmap (pages, *sz);
static Block *all_blocks = NULL;
static Block*
-sec_block_create (size_t size)
+sec_block_create (size_t size,
+ const char *during_tag)
{
Block *block;
Cell *cell;
+ ASSERT (during_tag);
+
#if FORCE_FALLBACK_MEMORY
/* We can force all all memory to be malloced */
return NULL;
if (size < DEFAULT_BLOCK_SIZE)
size = DEFAULT_BLOCK_SIZE;
- block->words = sec_acquire_pages (&size);
+ block->words = sec_acquire_pages (&size, during_tag);
block->n_words = size / sizeof (word_t);
if (!block->words) {
pool_free (block);
/* The first cell to allocate from */
cell->words = block->words;
cell->n_words = block->n_words;
- cell->allocated = 0;
+ cell->requested = 0;
sec_write_guards (cell);
- sec_insert_cell_ring (&block->unused, cell);
-
+ sec_insert_cell_ring (&block->unused_cells, cell);
+
block->next = all_blocks;
all_blocks = block;
ASSERT (block);
ASSERT (block->words);
- ASSERT (block->used == 0);
+ ASSERT (block->n_used == 0);
/* Remove from the list */
for (at = &all_blocks, bl = *at; bl; at = &bl->next, bl = *at) {
/* Must have been found */
ASSERT (bl == block);
+ ASSERT (block->used_cells == NULL);
/* Release all the meta data cells */
- while (block->unused) {
- cell = block->unused;
- sec_remove_cell_ring (&block->unused, cell);
+ while (block->unused_cells) {
+ cell = block->unused_cells;
+ sec_remove_cell_ring (&block->unused_cells, cell);
pool_free (cell);
}
*/
void*
-egg_secure_alloc (size_t length)
-{
- return egg_secure_alloc_full (length, GKR_SECURE_USE_FALLBACK);
-}
-
-void*
-egg_secure_alloc_full (size_t length, int flags)
+egg_secure_alloc_full (const char *tag,
+ size_t length,
+ int flags)
{
Block *block;
void *memory = NULL;
-
+
+ if (tag == NULL)
+ tag = "?";
+
if (length > 0xFFFFFFFF / 2) {
if (egg_secure_warnings)
fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n",
DO_LOCK ();
for (block = all_blocks; block; block = block->next) {
- memory = sec_alloc (block, length);
+ memory = sec_alloc (block, tag, length);
if (memory)
break;
}
/* None of the current blocks have space, allocate new */
if (!memory) {
- block = sec_block_create (length);
+ block = sec_block_create (length, tag);
if (block)
- memory = sec_alloc (block, length);
+ memory = sec_alloc (block, tag, length);
}
#ifdef WITH_VALGRIND
#endif
DO_UNLOCK ();
-
- if (!memory && (flags & GKR_SECURE_USE_FALLBACK)) {
+
+ if (!memory && (flags & EGG_SECURE_USE_FALLBACK)) {
memory = egg_memory_fallback (NULL, length);
if (memory) /* Our returned memory is always zeroed */
memset (memory, 0, length);
}
void*
-egg_secure_realloc (void *memory, size_t length)
-{
- return egg_secure_realloc_full (memory, length, GKR_SECURE_USE_FALLBACK);
-}
-
-void*
-egg_secure_realloc_full (void *memory, size_t length, int flags)
+egg_secure_realloc_full (const char *tag,
+ void *memory,
+ size_t length,
+ int flags)
{
Block *block = NULL;
size_t previous = 0;
int donew = 0;
void *alloc = NULL;
-
+
+ if (tag == NULL)
+ tag = "?";
+
if (length > 0xFFFFFFFF / 2) {
if (egg_secure_warnings)
fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n",
}
if (memory == NULL)
- return egg_secure_alloc_full (length, flags);
+ return egg_secure_alloc_full (tag, length, flags);
if (!length) {
egg_secure_free_full (memory, flags);
return NULL;
VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t));
#endif
- alloc = sec_realloc (block, memory, length);
-
+ alloc = sec_realloc (block, tag, memory, length);
+
#ifdef WITH_VALGRIND
/* Now tell valgrind about either the new block or old one */
VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory,
if (block && !alloc)
donew = 1;
- if (block && block->used == 0)
+ if (block && block->n_used == 0)
sec_block_destroy (block);
DO_UNLOCK ();
if (!block) {
- if ((flags & GKR_SECURE_USE_FALLBACK)) {
+ if ((flags & EGG_SECURE_USE_FALLBACK)) {
/*
* In this case we can't zero the returned memory,
* because we don't know what the block size was.
return NULL;
}
}
-
+
if (donew) {
- alloc = egg_secure_alloc_full (length, flags);
+ alloc = egg_secure_alloc_full (tag, length, flags);
if (alloc) {
memcpy (alloc, memory, previous);
egg_secure_free_full (memory, flags);
void
egg_secure_free (void *memory)
{
- egg_secure_free_full (memory, GKR_SECURE_USE_FALLBACK);
+ egg_secure_free_full (memory, EGG_SECURE_USE_FALLBACK);
}
void
if (block != NULL) {
sec_free (block, memory);
- if (block->used == 0)
+ if (block->n_used == 0)
sec_block_destroy (block);
}
DO_UNLOCK ();
if (!block) {
- if ((flags & GKR_SECURE_USE_FALLBACK)) {
+ if ((flags & EGG_SECURE_USE_FALLBACK)) {
egg_memory_fallback (memory, 0);
} else {
if (egg_secure_warnings)
DO_UNLOCK ();
}
-void
-egg_secure_dump_blocks (void)
+
+static egg_secure_rec *
+records_for_ring (Cell *cell_ring,
+ egg_secure_rec *records,
+ unsigned int *count,
+ unsigned int *total)
+{
+ egg_secure_rec *new_rec;
+ unsigned int allocated = *count;
+ Cell *cell;
+
+ cell = cell_ring;
+ do {
+ if (*count >= allocated) {
+ new_rec = realloc (records, sizeof (egg_secure_rec) * (allocated + 32));
+ if (new_rec == NULL) {
+ *count = 0;
+ free (records);
+ return NULL;
+ } else {
+ records = new_rec;
+ allocated += 32;
+ }
+ }
+
+ if (cell != NULL) {
+ records[*count].request_length = cell->requested;
+ records[*count].block_length = cell->n_words * sizeof (word_t);
+ records[*count].tag = cell->tag;
+ (*count)++;
+ (*total) += cell->n_words;
+ cell = cell->next;
+ }
+ } while (cell != NULL && cell != cell_ring);
+
+ return records;
+}
+
+egg_secure_rec *
+egg_secure_records (unsigned int *count)
{
+ egg_secure_rec *records = NULL;
Block *block = NULL;
+ unsigned int total;
+
+ *count = 0;
DO_LOCK ();
-
- /* Find out where it belongs to */
- for (block = all_blocks; block; block = block->next) {
- fprintf (stderr, "----------------------------------------------------\n");
- fprintf (stderr, " BLOCK at: 0x%08lx len: %lu\n", (unsigned long)block,
- (unsigned long)block->n_words * sizeof (word_t));
- fprintf (stderr, "\n");
+
+ for (block = all_blocks; block != NULL; block = block->next) {
+ total = 0;
+
+ records = records_for_ring (block->unused_cells, records, count, &total);
+ if (records == NULL)
+ break;
+ records = records_for_ring (block->used_cells, records, count, &total);
+ if (records == NULL)
+ break;
+
+ /* Make sure this actualy accounts for all memory */
+ ASSERT (total == block->n_words);
}
-
+
DO_UNLOCK ();
+
+ return records;
}
char*
-egg_secure_strdup (const char *str)
+egg_secure_strdup_full (const char *tag,
+ const char *str,
+ int options)
{
size_t len;
char *res;
-
+
if (!str)
return NULL;
-
+
len = strlen (str) + 1;
- res = (char*)egg_secure_alloc (len);
+ res = (char *)egg_secure_alloc_full (tag, len, options);
strcpy (res, str);
return res;
}
*/
egg_secure_strclear (str);
- egg_secure_free_full (str, GKR_SECURE_USE_FALLBACK);
+ egg_secure_free_full (str, EGG_SECURE_USE_FALLBACK);
}
* Allocations return NULL on failure.
*/
-#define GKR_SECURE_USE_FALLBACK 0x0001
+#define EGG_SECURE_USE_FALLBACK 0x0001
-void* egg_secure_alloc (size_t length);
+#define EGG_SECURE_DECLARE(tag) \
+ static inline void* egg_secure_alloc (size_t length) { \
+ return egg_secure_alloc_full (G_STRINGIFY (tag), length, EGG_SECURE_USE_FALLBACK); \
+ } \
+ static inline void* egg_secure_realloc (void *p, size_t length) { \
+ return egg_secure_realloc_full (G_STRINGIFY (tag), p, length, EGG_SECURE_USE_FALLBACK); \
+ } \
+ static inline void* egg_secure_strdup (const char *str) { \
+ return egg_secure_strdup_full (G_STRINGIFY (tag), str, EGG_SECURE_USE_FALLBACK); \
+ }
-void* egg_secure_alloc_full (size_t length, int flags);
+void* egg_secure_alloc_full (const char *tag, size_t length, int options);
-void* egg_secure_realloc (void *p, size_t length);
-
-void* egg_secure_realloc_full (void *p, size_t length, int fallback);
+void* egg_secure_realloc_full (const char *tag, void *p, size_t length, int options);
void egg_secure_free (void* p);
void egg_secure_validate (void);
-void egg_secure_dump_blocks (void);
-
-char* egg_secure_strdup (const char *str);
+char* egg_secure_strdup_full (const char *tag, const char *str, int options);
void egg_secure_strclear (char *str);
void egg_secure_strfree (char *str);
+typedef struct {
+ const char *tag;
+ size_t request_length;
+ size_t block_length;
+} egg_secure_rec;
+
+egg_secure_rec * egg_secure_records (unsigned int *count);
+
#endif /* EGG_SECURE_MEMORY_H */
include $(top_srcdir)/Makefile.decl
-NULL =
+SUBDIRS = . tests
module_flags = \
-export_dynamic \
lib_LTLIBRARIES = libgsecret.la
libgsecret_la_SOURCES = \
- gsecret-data.h gsecret-data.c
+ gsecret-value.h gsecret-value.c \
+ gsecret-item.h gsecret-item.c \
+ gsecret-service.h gsecret-service.c \
+ gsecret-util.c \
+ $(NULL)
libgsecret_la_LIBADD = \
$(top_builddir)/egg/libegg.la \
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __GSECRET_SERVICE_H__
+#define __GSECRET_SERVICE_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GSECRET_TYPE_SERVICE (gsecret_service_get_type ())
+#define GSECRET_SERVICE(inst) (GSECRET_TYPE_CHECK_INSTANCE_CAST ((inst), GSECRET_TYPE_SERVICE, GSecretService))
+#define GSECRET_SERVICE_CLASS(class) (GSECRET_TYPE_CHECK_CLASS_CAST ((class), GSECRET_TYPE_SERVICE, GSecretServiceClass))
+#define GSECRET_IS_SERVICE(inst) (GSECRET_TYPE_CHECK_INSTANCE_TYPE ((inst), GSECRET_TYPE_SERVICE))
+#define GSECRET_IS_SERVICE_CLASS(class) (GSECRET_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_SERVICE))
+#define GSECRET_SERVICE_GET_CLASS(inst) (GSECRET_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_SERVICE, GSecretServiceClass))
+
+typedef struct _GSecretService GSecretService;
+typedef struct _GSecretServiceClass GSecretServiceClass;
+typedef struct _GSecretServicePrivate GSecretServicePrivate;
+
+struct _GSecretServiceClass {
+ GDBusProxyClass parent_class;
+
+ GType collection_type;
+ GType item_type;
+
+ padding;
+};
+
+struct _GSecretService {
+ GDBusProxy parent_instance;
+ GSecretServicePrivate *pv;
+};
+
+GType gsecret_service_get_type (void) G_GNUC_CONST;
+
+GSecretService* gsecret_collection_xxx_new (void);
+
+GSecretCollection* gsecret_collection_instance (GDBusConnection *connection,
+ const gchar *object_path);
+
+ gsecret_collection_delete
+ gsecret_collection_search
+
+ GSecretItem* gsecret_collection_create_item (xxxx);
+
+
+ gsecret_collection_get_items
+ gsecret_collection_get_label
+ gsecret_collection_set_label
+ gsecret_collection_get_locked
+ gsecret_collection_get_created
+ gsecret_collection_get_modified
+
+G_END_DECLS
+
+#endif /* __G_SERVICE_H___ */
+++ /dev/null
-/* GSecret - GLib wrapper for Secret Service
- *
- * Copyright 2011 Collabora Ltd.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the licence or (at
- * your option) any later version.
- *
- * See the included COPYING file for more information.
- */
-
-#include "config.h"
-
-#include "gsecret-data.h"
-
-#include "egg/egg-secure-memory.h"
-
-#include <string.h>
-
-struct _GSecretData {
- gint refs;
- gpointer secret;
- gsize length;
- GDestroyNotify destroy;
- gchar *content_type;
-};
-
-GType
-gsecret_data_get_type (void)
-{
- static gsize initialized = 0;
- static GType type = 0;
-
- if (g_once_init_enter (&initialized)) {
- type = g_boxed_type_register_static ("GSecretData",
- (GBoxedCopyFunc)gsecret_data_ref,
- (GBoxedFreeFunc)gsecret_data_unref);
- g_once_init_leave (&initialized, 1);
- }
-
- return type;
-}
-
-GSecretData*
-gsecret_data_new (const gchar *secret, gssize length, const gchar *content_type)
-{
- gchar *copy;
-
- g_return_val_if_fail (!secret && length, NULL);
- g_return_val_if_fail (content_type, NULL);
-
- if (length < 0)
- length = strlen (secret);
-
- copy = egg_secure_alloc (length + 1);
- memcpy (copy, secret, length);
- copy[length] = 0;
- return gsecret_data_new_full (copy, length, content_type, egg_secure_free);
-}
-
-GSecretData*
-gsecret_data_new_full (gchar *secret, gssize length,
- const gchar *content_type, GDestroyNotify destroy)
-{
- GSecretData *data;
-
- g_return_val_if_fail (!secret && length, NULL);
- g_return_val_if_fail (content_type, NULL);
-
- if (length < 0)
- length = strlen (secret);
-
- data = g_slice_new0 (GSecretData);
- data->content_type = strdup (content_type);
- data->destroy = destroy;
- data->length = length;
- data->secret = secret;
-
- return data;
-}
-
-const gchar*
-gsecret_data_get (GSecretData *data, gsize *length)
-{
- g_return_val_if_fail (data, NULL);
- if (length)
- *length = data->length;
- return data->secret;
-}
-
-const gchar*
-gsecret_data_get_content_type (GSecretData *data)
-{
- g_return_val_if_fail (data, NULL);
- return data->content_type;
-}
-
-GSecretData*
-gsecret_data_ref (GSecretData *data)
-{
- g_return_val_if_fail (data, NULL);
- g_atomic_int_inc (&data->refs);
- return data;
-}
-
-void
-gsecret_data_unref (GSecretData *data)
-{
- g_return_if_fail (data);
-
- if (g_atomic_int_dec_and_test (&data->refs)) {
- g_free (data->content_type);
- if (data->destroy)
- (data->destroy) (data->secret);
- g_slice_free (GSecretData, data);
- }
-}
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include "config.h"
+
+#include "gsecret-item.h"
+#include "gsecret-private.h"
+#include "gsecret-service.h"
+#include "gsecret-types.h"
+#include "gsecret-value.h"
+
+#include <glib/gi18n-lib.h>
+
+struct _GSecretItemPrivate {
+ GSecretService *service;
+};
+
+G_DEFINE_TYPE (GSecretItem, gsecret_item, G_TYPE_DBUS_PROXY);
+
+static void
+gsecret_item_init (GSecretItem *self)
+{
+ self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GSECRET_TYPE_ITEM, GSecretItemPrivate);
+}
+
+static void
+gsecret_item_class_init (GSecretItemClass *klass)
+{
+
+}
+
+static void
+on_item_delete_ready (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GError *error = NULL;
+ GVariant *ret;
+
+ ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
+ result, &error);
+ if (ret == NULL)
+ g_simple_async_result_take_error (res, error);
+ else
+ g_variant_unref (ret);
+
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
+
+void
+gsecret_item_delete (GSecretItem *self, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ const gchar *object_path;
+ gchar *collection_path;
+ GSimpleAsyncResult *res;
+
+ g_return_if_fail (GSECRET_IS_ITEM (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ res = g_simple_async_result_new (G_OBJECT (self), callback,
+ user_data, gsecret_item_delete);
+
+ object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
+ collection_path = _gsecret_util_parent_path (object_path);
+
+ g_dbus_connection_call (g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
+ g_dbus_proxy_get_name (G_DBUS_PROXY (self)),
+ collection_path, GSECRET_COLLECTION_INTERFACE,
+ "Delete", NULL, NULL,
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+ cancellable, on_item_delete_ready, res);
+
+ g_free (collection_path);
+}
+
+gboolean
+gsecret_item_delete_finish (GSecretItem *self, GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result,
+ G_OBJECT (self), gsecret_item_delete), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gsecret_item_delete_sync (GSecretItem *self, GCancellable *cancellable,
+ GError **error)
+{
+ const gchar *object_path;
+ gchar *collection_path;
+ GVariant *ret;
+
+ g_return_val_if_fail (GSECRET_IS_ITEM (self), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
+ collection_path = _gsecret_util_parent_path (object_path);
+
+ ret = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (self)),
+ g_dbus_proxy_get_name (G_DBUS_PROXY (self)),
+ collection_path, GSECRET_COLLECTION_INTERFACE,
+ "Delete", NULL, NULL,
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+ cancellable, error);
+
+ g_free (collection_path);
+
+ if (ret != NULL) {
+ g_variant_unref (ret);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+on_item_get_secret_ready (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GSecretItem *self = GSECRET_ITEM (g_async_result_get_source_object (user_data));
+ GError *error = NULL;
+ GSecretValue *value;
+ GVariant *ret;
+
+ ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
+ if (error == NULL) {
+ value = _gsecret_service_decode_secret (self->pv->service, ret);
+ if (value == NULL) {
+ g_set_error (&error, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
+ _("Received invalid secret from the secret storage"));
+ }
+ g_object_unref (ret);
+ }
+
+ if (error != NULL)
+ g_simple_async_result_take_error (res, error);
+ else
+ g_simple_async_result_set_op_res_gpointer (res, value,
+ gsecret_value_unref);
+
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
+
+static void
+on_service_ensure_session (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GSecretItem *self = GSECRET_ITEM (g_async_result_get_source_object (user_data));
+ GError *error = NULL;
+ const gchar *session_path;
+
+ session_path = gsecret_service_ensure_session_finish (self->pv->service,
+ result, &error);
+ if (error != NULL) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+
+ } else {
+ g_assert (session_path != NULL && session_path[0] != '\0');
+ g_dbus_proxy_call (G_DBUS_PROXY (self), "GetSecret",
+ g_variant_new ("o", session_path),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ _gsecret_async_result_get_cancellable (res),
+ on_item_get_secret_ready, g_object_ref (res));
+ }
+
+ g_object_unref (res);
+}
+
+void
+gsecret_item_get_secret (GSecretItem *self, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+
+ g_return_if_fail (GSECRET_IS_ITEM (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback,
+ user_data, gsecret_item_get_secret);
+
+ gsecret_service_ensure_session (self->pv->service, cancellable,
+ on_service_ensure_session,
+ g_object_ref (res));
+
+ g_object_unref (res);
+}
+
+GSecretValue*
+gsecret_item_get_secret_finish (GSecretItem *self, GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *res;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ gsecret_item_get_secret), NULL);
+
+ res = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (res, error))
+ return NULL;
+
+ return gsecret_value_ref (g_simple_async_result_get_op_res_gpointer (res));
+}
+
+GSecretValue*
+gsecret_item_get_secret_sync (GSecretItem *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ const gchar *session_path;
+ GSecretValue *value;
+ GVariant *ret;
+
+ session_path = gsecret_service_ensure_session_sync (self->pv->service,
+ cancellable, error);
+ if (session_path != NULL)
+ return NULL;
+
+ g_assert (session_path != NULL && session_path[0] != '\0');
+ ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "GetSecret",
+ g_variant_new ("o", session_path),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable, error);
+
+ if (ret != NULL) {
+ value = _gsecret_service_decode_secret (self->pv->service, ret);
+ if (value == NULL) {
+ g_set_error (error, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
+ _("Received invalid secret from the secret storage"));
+ }
+ }
+
+ g_object_unref (ret);
+ return value;
+}
+
+#ifdef UNIMPLEMENTED
+
+GHashTable* gsecret_item_get_attributes (GSecretItem *self);
+
+void gsecret_item_set_attributes (GSecretItem *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_item_set_attributes_finish (GSecretItem *self,
+ GAsyncResult *result,
+ GError **error);
+
+void gsecret_item_set_attributes_sync (GSecretItem *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error);
+
+const gchar* gsecret_item_get_label (GSecretItem *self);
+
+void gsecret_item_set_label (GSecretItem *self,
+ const gchar *label,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_item_set_label_finish (GSecretItem *self,
+ GAsyncResult *result,
+ GError **error);
+
+void gsecret_item_set_label_sync (GSecretItem *self,
+ const gchar *label,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean gsecret_item_get_locked (GSecretItem *self);
+
+guint64 gsecret_item_get_created (GSecretItem *self);
+
+guint64 gsecret_item_get_modified (GSecretItem *self);
+
+#endif /* UNIMPLEMENTED */
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __GSECRET_ITEM_H__
+#define __GSECRET_ITEM_H__
+
+#include <gio/gio.h>
+
+#include "gsecret-item.h"
+#include "gsecret-value.h"
+
+G_BEGIN_DECLS
+
+#define GSECRET_TYPE_ITEM (gsecret_item_get_type ())
+#define GSECRET_ITEM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GSECRET_TYPE_ITEM, GSecretItem))
+#define GSECRET_ITEM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GSECRET_TYPE_ITEM, GSecretItemClass))
+#define GSECRET_IS_ITEM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GSECRET_TYPE_ITEM))
+#define GSECRET_IS_ITEM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_ITEM))
+#define GSECRET_ITEM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_ITEM, GSecretItemClass))
+
+typedef struct _GSecretItem GSecretItem;
+typedef struct _GSecretItemClass GSecretItemClass;
+typedef struct _GSecretItemPrivate GSecretItemPrivate;
+
+struct _GSecretItemClass {
+ GDBusProxyClass parent_class;
+};
+
+struct _GSecretItem {
+ GDBusProxy parent_instance;
+ GSecretItemPrivate *pv;
+};
+
+GType gsecret_item_get_type (void) G_GNUC_CONST;
+
+GSecretItem* gsecret_item_instance (GDBusConnection *connection,
+ const gchar *object_path);
+
+void gsecret_item_delete (GSecretItem *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_item_delete_finish (GSecretItem *self,
+ GAsyncResult *result,
+ GError **error);
+
+gboolean gsecret_item_delete_sync (GSecretItem *self,
+ GCancellable *cancellable,
+ GError **error);
+
+void gsecret_item_get_secret (GSecretItem *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GSecretValue * gsecret_item_get_secret_finish (GSecretItem *self,
+ GAsyncResult *result,
+ GError **error);
+
+GSecretValue * gsecret_item_get_secret_sync (GSecretItem *self,
+ GCancellable *cancellable,
+ GError **error);
+
+#if 0
+
+GHashTable* gsecret_item_get_attributes (GSecretItem *self);
+
+void gsecret_item_set_attributes (GSecretItem *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_item_set_attributes_finish (GSecretItem *self,
+ GAsyncResult *result,
+ GError **error);
+
+void gsecret_item_set_attributes_sync (GSecretItem *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error);
+
+const gchar* gsecret_item_get_label (GSecretItem *self);
+
+void gsecret_item_set_label (GSecretItem *self,
+ const gchar *label,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_item_set_label_finish (GSecretItem *self,
+ GAsyncResult *result,
+ GError **error);
+
+void gsecret_item_set_label_sync (GSecretItem *self,
+ const gchar *label,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean gsecret_item_get_locked (GSecretItem *self);
+
+guint64 gsecret_item_get_created (GSecretItem *self);
+
+guint64 gsecret_item_get_modified (GSecretItem *self);
+
+#endif
+
+G_END_DECLS
+
+#endif /* __G_ITEM_H___ */
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+
+ */
+#ifndef __GSECRET_PRIVATE_H__
+#define __GSECRET_PRIVATE_H__
+
+#include <gio/gio.h>
+
+#include "gsecret-service.h"
+#include "gsecret-value.h"
+
+G_BEGIN_DECLS
+
+#define GSECRET_COLLECTION_INTERFACE "org.freedesktop.Secret.Collection"
+
+gchar * _gsecret_util_parent_path (const gchar *path);
+
+GVariant * _gsecret_service_encode_secret (GSecretService *self,
+ GSecretValue *value);
+
+GSecretValue * _gsecret_service_decode_secret (GSecretService *service,
+ GVariant *encoded);
+
+GCancellable * _gsecret_async_result_get_cancellable (GSimpleAsyncResult *result);
+
+void _gsecret_async_result_set_cancellable (GSimpleAsyncResult *result,
+ GCancellable *cancellable);
+
+gboolean _gsecret_async_result_propagate_cancelled (GSimpleAsyncResult *result);
+
+G_END_DECLS
+
+#endif /* __G_SERVICE_H___ */
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __GSECRET_PROMPT_H__
+#define __GSECRET_PROMPT_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GSECRET_TYPE_PROMPT (gsecret_prompt_get_type ())
+#define GSECRET_PROMPT(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GSECRET_TYPE_PROMPT, GSecretPrompt))
+#define GSECRET_PROMPT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GSECRET_TYPE_PROMPT, GSecretPromptClass))
+#define GSECRET_IS_PROMPT(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GSECRET_TYPE_PROMPT))
+#define GSECRET_IS_PROMPT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_PROMPT))
+#define GSECRET_PROMPT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_PROMPT, GSecretPromptClass))
+
+typedef struct _GSecretPrompt GSecretPrompt;
+typedef struct _GSecretPromptClass GSecretPromptClass;
+typedef struct _GSecretPromptPrivate GSecretPromptPrivate;
+
+struct _GSecretPromptClass {
+ GDBusProxyClass parent_class;
+ padding;
+};
+
+struct _GSecretPrompt {
+ GDBusProxy parent_instance;
+ GSecretPromptPrivate *pv;
+};
+
+GType gsecret_service_get_type (void) G_GNUC_CONST;
+
+GSecretService* gsecret_collection_xxx_new (void);
+
+GSecretPrompt* gsecret_prompt_instance (GDBusConnection *connection,
+ const gchar *object_path,
+ GError **error);
+
+GSecretPrompt* gsecret_prompt_instance_sync (GDBusConnection *connection,
+ const gchar *object_path);
+
+ gsecret_prompt_perform
+ gsecret_prompt_dismiss
+
+G_END_DECLS
+
+#endif /* __G_SERVICE_H___ */
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include "config.h"
+
+#include "gsecret-private.h"
+#include "gsecret-service.h"
+#include "gsecret-types.h"
+#include "gsecret-value.h"
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <gcrypt.h>
+
+#include "egg/egg-dh.h"
+#include "egg/egg-hkdf.h"
+#include "egg/egg-secure-memory.h"
+
+EGG_SECURE_GLIB_DEFINITIONS ();
+
+EGG_SECURE_DECLARE (secret_service);
+
+typedef struct {
+ gchar *path;
+ gcry_mpi_t prime;
+ gcry_mpi_t privat;
+ gcry_mpi_t publi;
+ gpointer key;
+ gsize n_key;
+} GSecretSession;
+
+struct _GSecretServicePrivate {
+ gpointer session;
+};
+
+static void
+gsecret_session_free (gpointer data)
+{
+ GSecretSession *session = data;
+
+ if (session == NULL)
+ return;
+
+ g_free (session->path);
+ gcry_mpi_release (session->publi);
+ gcry_mpi_release (session->privat);
+ gcry_mpi_release (session->prime);
+ egg_secure_free (session->key);
+ g_free (session);
+}
+
+static GVariant *
+request_open_session_aes (GSecretSession *session)
+{
+ gcry_error_t gcry;
+ gcry_mpi_t base;
+ unsigned char *buffer;
+ size_t n_buffer;
+ GVariant *argument;
+
+ g_assert (session->prime == NULL);
+ g_assert (session->privat == NULL);
+ g_assert (session->publi == NULL);
+
+ /* Initialize our local parameters and values */
+ if (!egg_dh_default_params ("ietf-ike-grp-modp-1024",
+ &session->prime, &base))
+ g_return_val_if_reached (NULL);
+ if (!egg_dh_gen_pair (session->prime, base, 0,
+ &session->publi, &session->privat))
+ g_return_val_if_reached (NULL);
+ gcry_mpi_release (base);
+
+ gcry = gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer, &n_buffer, session->publi);
+ g_return_val_if_fail (gcry == 0, NULL);
+ argument = g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
+ buffer, n_buffer, TRUE,
+ gcry_free, buffer);
+
+ return g_variant_new ("sv", "dh-ietf1024-sha256-aes128-cbc-pkcs7", argument);
+}
+
+static gboolean
+response_open_session_aes (GSecretSession *session,
+ GVariant *response)
+{
+ gconstpointer buffer;
+ GVariant *argument;
+ gsize n_buffer;
+ gcry_mpi_t peer;
+ gcry_error_t gcry;
+ gpointer ikm;
+ gsize n_ikm;
+
+ if (G_VARIANT_TYPE ("vo") != g_variant_get_type (response)) {
+ g_warning ("invalid OpenSession() response from daemon with signature: %s",
+ g_variant_get_type_string (response));
+ return FALSE;
+ }
+
+ g_assert (session->path == NULL);
+ g_variant_get (response, "vo", &argument, &session->path);
+
+ buffer = g_variant_get_fixed_array (argument, &n_buffer, sizeof (guchar));
+ gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, buffer, n_buffer, NULL);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ g_variant_unref (argument);
+
+ ikm = egg_dh_gen_secret (peer, session->privat, session->prime, &n_ikm);
+ gcry_mpi_release (peer);
+
+ if (ikm == NULL) {
+ g_warning ("couldn't negotiate a valid AES session key");
+ g_free (session->path);
+ session->path = NULL;
+ return FALSE;
+ }
+
+ session->n_key = 16;
+ session->key = egg_secure_alloc (session->n_key);
+ if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0,
+ session->key, session->n_key))
+ g_return_val_if_reached (FALSE);
+ egg_secure_free (ikm);
+
+ return TRUE;
+}
+
+static GVariant *
+request_open_session_plain (GSecretSession *session)
+{
+ GVariant *argument = g_variant_new_string ("");
+ return g_variant_new ("sv", "plain", argument);
+}
+
+static gboolean
+response_open_session_plain (GSecretSession *session,
+ GVariant *response)
+{
+ GVariant *argument;
+
+ if (G_VARIANT_TYPE ("vo") != g_variant_get_type (response)) {
+ g_warning ("invalid OpenSession() response from daemon with signature: %s",
+ g_variant_get_type_string (response));
+ return FALSE;
+ }
+
+ g_assert (session->path == NULL);
+ g_variant_get (response, "vo", &argument, &session->path);
+ g_variant_unref (argument);
+
+ g_assert (session->key == NULL);
+ g_assert (session->n_key == 0);
+
+ return TRUE;
+}
+
+typedef struct {
+ GCancellable *cancellable;
+ GSecretSession *session;
+} OpenSessionClosure;
+
+static void
+open_session_closure_free (gpointer data)
+{
+ OpenSessionClosure *closure = data;
+ g_assert (closure);
+ g_clear_object (&closure->cancellable);
+ gsecret_session_free (closure->session);
+ g_free (closure);
+}
+
+static void
+on_service_open_session_plain (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ OpenSessionClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *self = GSECRET_SERVICE (source);
+ GError *error = NULL;
+ GVariant *response;
+
+ response = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, &error);
+
+ /* A successful response, decode it */
+ if (response != NULL) {
+ if (response_open_session_plain (closure->session, response)) {
+
+ /* Set value atomically, in case of race condition */
+ if (g_atomic_pointer_compare_and_exchange (&(self->pv->session),
+ NULL, closure->session))
+ closure->session = NULL; /* Service takes ownership */
+
+ } else {
+ g_simple_async_result_set_error (res, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
+ _("Couldn't communicate with the secret storage"));
+ }
+
+ g_simple_async_result_complete (res);
+ g_variant_unref (response);
+
+ } else {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ }
+
+ g_object_unref (res);
+}
+
+static void
+on_service_open_session_aes (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ OpenSessionClosure * closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *self = GSECRET_SERVICE (source);
+ GError *error = NULL;
+ GVariant *response;
+
+ response = g_dbus_proxy_call_finish (G_DBUS_PROXY (self), result, &error);
+
+ /* A successful response, decode it */
+ if (response != NULL) {
+ if (response_open_session_aes (closure->session, response)) {
+
+ /* Set value atomically, in case of race condition */
+ if (!g_atomic_pointer_compare_and_exchange (&(self->pv->session),
+ NULL, closure->session))
+ closure->session = NULL; /* Service takes ownership */
+
+ } else {
+ g_simple_async_result_set_error (res, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
+ _("Couldn't communicate with the secret storage"));
+ }
+
+ g_simple_async_result_complete (res);
+ g_variant_unref (response);
+
+ } else {
+ /* AES session not supported, request a plain session */
+ if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED)) {
+ g_dbus_proxy_call (G_DBUS_PROXY (source), "OpenSession",
+ request_open_session_plain (closure->session),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ closure->cancellable, on_service_open_session_plain,
+ g_object_ref (res));
+ g_error_free (error);
+
+ /* Other errors result in a failure */
+ } else {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ }
+ }
+
+ g_object_unref (res);
+}
+
+void
+gsecret_service_ensure_session (GSecretService *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ OpenSessionClosure *closure;
+
+ g_return_if_fail (GSECRET_IS_SERVICE (self));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ gsecret_service_ensure_session);
+
+ /* If we have no session, then request an AES session */
+ if (g_atomic_pointer_get (&self->pv->session) == NULL) {
+
+ closure = g_new (OpenSessionClosure, 1);
+ closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
+ closure->session = g_new (GSecretSession, 1);
+ g_simple_async_result_set_op_res_gpointer (res, closure, open_session_closure_free);
+
+ g_dbus_proxy_call (G_DBUS_PROXY (self), "OpenSession",
+ request_open_session_aes (closure->session),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable, on_service_open_session_aes,
+ g_object_ref (res));
+
+ /* Already have a session */
+ } else {
+ g_simple_async_result_complete_in_idle (res);
+ }
+
+ g_object_unref (res);
+}
+
+const gchar *
+gsecret_service_ensure_session_finish (GSecretService *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSecretSession *session;
+
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ gsecret_service_ensure_session), NULL);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return NULL;
+
+ /* The session we have should never change once created */
+ session = g_atomic_pointer_get (&self->pv->session);
+ g_assert (session != NULL);
+ return session->path;
+}
+
+const gchar *
+gsecret_service_ensure_session_sync (GSecretService *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *response;
+ GSecretSession *session;
+ GError *lerror = NULL;
+ gboolean complete = FALSE;
+
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* The session we have should never change once created */
+ session = g_atomic_pointer_get (&self->pv->session);
+ if (session != NULL)
+ return session->path;
+
+ session = g_new0 (GSecretSession, 1);
+ response = g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "OpenSession",
+ request_open_session_aes (session),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable, &lerror);
+
+ if (response != NULL) {
+ complete = response_open_session_aes (session, response);
+ g_variant_unref (response);
+
+ /* AES session not supported, request a plain session */
+ } else if (g_error_matches (lerror, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED)) {
+ g_clear_error (&lerror);
+
+ response = g_dbus_proxy_call_sync (G_DBUS_PROXY (self), "OpenSession",
+ request_open_session_plain (session),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ cancellable, &lerror);
+
+ if (response != NULL) {
+ complete = response_open_session_plain (session, response);
+ g_variant_unref (response);
+ }
+ }
+
+ if (lerror == NULL && !complete) {
+ g_set_error (&lerror, GSECRET_ERROR, GSECRET_ERROR_PROTOCOL,
+ _("Couldn't communicate with the secret storage"));
+ }
+
+ if (lerror != NULL) {
+ gsecret_session_free (session);
+ g_propagate_error (error, lerror);
+ return NULL;
+ }
+
+ /* Set value atomically, in case of race condition */
+ if (!g_atomic_pointer_compare_and_exchange (&(self->pv->session),
+ NULL, session))
+ gsecret_session_free (session);
+
+ /* The session we have should never change once created */
+ session = g_atomic_pointer_get (&self->pv->session);
+ g_assert (session != NULL);
+ return session->path;
+}
+
+static gboolean
+pkcs7_unpad_bytes_in_place (guchar *padded,
+ gsize *n_padded)
+{
+ gsize n_pad, i;
+
+ if (*n_padded == 0)
+ return FALSE;
+
+ n_pad = padded[*n_padded - 1];
+
+ /* Validate the padding */
+ if (n_pad == 0 || n_pad > 16)
+ return FALSE;
+ if (n_pad > *n_padded)
+ return FALSE;
+ for (i = *n_padded - n_pad; i < *n_padded; ++i) {
+ if (padded[i] != n_pad)
+ return FALSE;
+ }
+
+ /* The last bit of data */
+ *n_padded -= n_pad;
+
+ /* Null teriminate as a courtesy */
+ padded[*n_padded] = 0;
+
+ return TRUE;
+}
+
+static GSecretValue *
+service_decode_aes_secret (GSecretSession *session,
+ gconstpointer param,
+ gsize n_param,
+ gconstpointer value,
+ gsize n_value,
+ const gchar *content_type)
+{
+ gcry_cipher_hd_t cih;
+ gsize n_padded;
+ gcry_error_t gcry;
+ guchar *padded;
+ gsize pos;
+
+ if (n_param != 16) {
+ g_message ("received an encrypted secret structure with invalid parameter");
+ return NULL;
+ }
+
+ if (n_value == 0 || n_value % 16 != 0) {
+ g_message ("received an encrypted secret structure with bad secret length");
+ return NULL;
+ }
+
+ gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
+ if (gcry != 0) {
+ g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry));
+ return NULL;
+ }
+
+ gcry = gcry_cipher_setiv (cih, param, n_param);
+ g_return_val_if_fail (gcry == 0, NULL);
+
+ gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
+ g_return_val_if_fail (gcry == 0, NULL);
+
+ /* Copy the memory buffer */
+ n_padded = n_value;
+ padded = egg_secure_alloc (n_padded);
+ memcpy (padded, value, n_padded);
+
+ /* Perform the decryption */
+ for (pos = 0; pos < n_padded; pos += 16) {
+ gcry = gcry_cipher_decrypt (cih, (guchar*)padded + pos, 16, NULL, 0);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ }
+
+ gcry_cipher_close (cih);
+
+ /* Unpad the resulting value */
+ if (!pkcs7_unpad_bytes_in_place (padded, &n_padded)) {
+ egg_secure_clear (padded, n_padded);
+ egg_secure_free (padded);
+ g_message ("received an invalid, unencryptable, or non-utf8 secret");
+ return FALSE;
+ }
+
+ return gsecret_value_new_full ((gchar *)padded, n_padded, content_type, egg_secure_free);
+}
+
+static GSecretValue *
+service_decode_plain_secret (GSecretSession *session,
+ gconstpointer param,
+ gsize n_param,
+ gconstpointer value,
+ gsize n_value,
+ const gchar *content_type)
+{
+ if (n_param != 0) {
+ g_message ("received a plain secret structure with invalid parameter");
+ return NULL;
+ }
+
+ return gsecret_value_new (value, n_value, content_type);
+}
+
+GSecretValue *
+_gsecret_service_decode_secret (GSecretService *self,
+ GVariant *encoded)
+{
+ GSecretSession *session;
+ GSecretValue *result;
+ gconstpointer param;
+ gconstpointer value;
+ gchar *session_path;
+ gchar *content_type;
+ gsize n_param;
+ gsize n_value;
+ GVariant *vparam;
+ GVariant *vvalue;
+
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
+ g_return_val_if_fail (encoded, NULL);
+
+ session = g_atomic_pointer_get (&self->pv->session);
+ g_return_val_if_fail (session != NULL, NULL);
+ g_assert (session->path != NULL);
+
+ /* Parsing (oayays) */
+ g_variant_get_child (encoded, 0, "o", &session_path);
+
+ if (session_path == NULL || !g_str_equal (session_path, session->path)) {
+ g_message ("received a secret encoded with wrong session: %s != %s",
+ session_path, session->path);
+ g_free (session_path);
+ return NULL;
+ }
+
+ vparam = g_variant_get_child_value (encoded, 1);
+ param = g_variant_get_fixed_array (vparam, &n_param, sizeof (guchar));
+ vvalue = g_variant_get_child_value (encoded, 2);
+ value = g_variant_get_fixed_array (vvalue, &n_value, sizeof (guchar));
+ g_variant_get_child (encoded, 3, "s", &content_type);
+
+ if (session->key != NULL) {
+ result = service_decode_aes_secret (session, param, n_param,
+ value, n_value, content_type);
+ } else {
+ result = service_decode_plain_secret (session, param, n_param,
+ value, n_value, content_type);
+ }
+
+ g_variant_unref (vparam);
+ g_variant_unref (vvalue);
+ g_free (content_type);
+ g_free (session_path);
+
+ return result;
+}
+
+static guchar*
+pkcs7_pad_bytes_in_secure_memory (gconstpointer secret,
+ gsize length,
+ gsize *n_padded)
+{
+ gsize n_pad;
+ guchar *padded;
+
+ /* Pad the secret */
+ *n_padded = ((length + 16) / 16) * 16;
+ g_assert (length < *n_padded);
+ g_assert (*n_padded > 0);
+ n_pad = *n_padded - length;
+ g_assert (n_pad > 0 && n_pad <= 16);
+ padded = egg_secure_alloc (*n_padded);
+ memcpy (padded, secret, length);
+ memset (padded + length, n_pad, n_pad);
+ return padded;
+}
+
+static gboolean
+service_encode_aes_secret (GSecretSession *session,
+ GSecretValue *value,
+ GVariantBuilder *builder)
+{
+ gcry_cipher_hd_t cih;
+ guchar *padded;
+ gsize n_padded, pos;
+ gcry_error_t gcry;
+ gpointer iv;
+ gconstpointer secret;
+ gsize n_secret;
+ GVariant *child;
+
+ g_variant_builder_add (builder, "o", session->path);
+
+ /* Create the cipher */
+ gcry = gcry_cipher_open (&cih, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
+ if (gcry != 0) {
+ g_warning ("couldn't create AES cipher: %s", gcry_strerror (gcry));
+ return FALSE;
+ }
+
+ secret = gsecret_value_get (value, &n_secret);
+
+ /* Perform the encoding here */
+ padded = pkcs7_pad_bytes_in_secure_memory (secret, n_secret, &n_padded);
+ g_assert (padded != NULL);
+
+ /* Setup the IV */
+ iv = g_malloc0 (16);
+ gcry_create_nonce (iv, 16);
+ gcry = gcry_cipher_setiv (cih, iv, 16);
+ g_return_val_if_fail (gcry == 0, FALSE);
+
+ /* Setup the key */
+ gcry = gcry_cipher_setkey (cih, session->key, session->n_key);
+ g_return_val_if_fail (gcry == 0, FALSE);
+
+ /* Perform the encryption */
+ for (pos = 0; pos < n_padded; pos += 16) {
+ gcry = gcry_cipher_encrypt (cih, (guchar*)padded + pos, 16, NULL, 0);
+ g_return_val_if_fail (gcry == 0, FALSE);
+ }
+
+ gcry_cipher_close (cih);
+
+ child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), iv, 16, TRUE, g_free, iv);
+ g_variant_builder_add_value (builder, child);
+ g_variant_unref (child);
+
+ child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), padded, n_padded, TRUE, egg_secure_free, padded);
+ g_variant_builder_add_value (builder, child);
+ g_variant_unref (child);
+
+ g_variant_builder_add (builder, "s", gsecret_value_get_content_type (value));
+ return TRUE;
+}
+
+static gboolean
+service_encode_plain_secret (GSecretSession *session,
+ GSecretValue *value,
+ GVariantBuilder *builder)
+{
+ gconstpointer secret;
+ gsize n_secret;
+ GVariant *child;
+
+ g_variant_builder_add (builder, "o", session->path);
+
+ secret = gsecret_value_get (value, &n_secret);
+
+ child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), "", 0, TRUE, NULL, NULL);
+ g_variant_builder_add_value (builder, child);
+ g_variant_unref (child);
+
+ child = g_variant_new_from_data (G_VARIANT_TYPE ("ay"), secret, n_secret, TRUE,
+ gsecret_value_unref, gsecret_value_ref (value));
+ g_variant_builder_add_value (builder, child);
+ g_variant_unref (child);
+
+ g_variant_builder_add (builder, "s", gsecret_value_get_content_type (value));
+ return TRUE;
+}
+
+GVariant *
+_gsecret_service_encode_secret (GSecretService *self,
+ GSecretValue *value)
+{
+ GVariantBuilder *builder;
+ GSecretSession *session;
+ GVariant *result = NULL;
+ GVariantType *type;
+ gboolean ret;
+
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
+ g_return_val_if_fail (value, NULL);
+
+ session = g_atomic_pointer_get (&self->pv->session);
+ g_return_val_if_fail (session != NULL, NULL);
+ g_assert (session->path != NULL);
+
+ type = g_variant_type_new ("(oayays)");
+ builder = g_variant_builder_new (type);
+
+ if (session->key)
+ ret = service_encode_aes_secret (session, value, builder);
+ else
+ ret = service_encode_plain_secret (session, value, builder);
+ if (ret)
+ result = g_variant_builder_end (builder);
+
+ g_variant_builder_unref (builder);
+ g_variant_type_free (type);
+ return result;
+}
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __GSECRET_SERVICE_H__
+#define __GSECRET_SERVICE_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GSECRET_TYPE_SERVICE (gsecret_service_get_type ())
+#define GSECRET_SERVICE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), GSECRET_TYPE_SERVICE, GSecretService))
+#define GSECRET_SERVICE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GSECRET_TYPE_SERVICE, GSecretServiceClass))
+#define GSECRET_IS_SERVICE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), GSECRET_TYPE_SERVICE))
+#define GSECRET_IS_SERVICE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GSECRET_TYPE_SERVICE))
+#define GSECRET_SERVICE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GSECRET_TYPE_SERVICE, GSecretServiceClass))
+
+typedef struct _GSecretService GSecretService;
+typedef struct _GSecretServiceClass GSecretServiceClass;
+typedef struct _GSecretServicePrivate GSecretServicePrivate;
+
+struct _GSecretServiceClass {
+ GDBusProxyClass parent_class;
+
+ GType collection_type;
+ GType item_type;
+
+#if 0
+ padding;
+#endif
+};
+
+struct _GSecretService {
+ GDBusProxy parent_instance;
+ GSecretServicePrivate *pv;
+};
+
+GType gsecret_service_get_type (void) G_GNUC_CONST;
+
+#if 0
+void gsecret_service_get (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GSecretService* gsecret_service_get_finish (GAsyncResult *result,
+ GError **error);
+
+GSecretService* gsecret_service_get_sync (GAsyncResult *result,
+ GError **error);
+
+void gsecret_service_instance (GDBusConnection *connection,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GSecretService * gsecret_service_instance_finish (GAsyncResult *result,
+ GError **error);
+
+GSecretService * gsecret_service_instance_sync (GDBusConnection *connection,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+#endif
+
+void gsecret_service_ensure_session (GSecretService *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+const gchar * gsecret_service_ensure_session_finish (GSecretService *self,
+ GAsyncResult *result,
+ GError **error);
+
+const gchar * gsecret_service_ensure_session_sync (GSecretService *self,
+ GCancellable *cancellable,
+ GError **error);
+
+#if 0
+void gsecret_service_search (GSecretService *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_service_search_finish (GSecretService *self,
+ GAsyncResult *result,
+ GList **unlocked,
+ GList **locked,
+ GError **error);
+
+gboolean gsecret_service_search_sync (GSecretService *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GList **unlocked,
+ GList **locked,
+ GError **error);
+
+void gsecret_service_search_for_paths (GSecretService *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_service_search_for_paths_finish (GSecretService *self,
+ GAsyncResult *result,
+ gchar ***unlocked,
+ gchar ***locked,
+ GError **error);
+
+gboolean gsecret_service_search_for_paths_sync (GSecretService *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ gchar ***unlocked,
+ gchar ***locked,
+ GError **error);
+
+void gsecret_service_lock (GSecretService *self,
+ GList *objects,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_service_lock_finish (GSecretService *self,
+ GAsyncResult *result,
+ GList **locked,
+ GSecretPrompt *prompt,
+ GError **error);
+
+void gsecret_service_lock_sync (GSecretService *self,
+ GList *objects,
+ GCancellable *cancellable,
+ GList **locked,
+ GSecretPrompt *prompt,
+ GError **error);
+
+void gsecret_service_unlock (GSecretService *self,
+ GList *objects,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gsecret_service_
+ GList **unlocked,
+ GSecretPrompt *prompt,
+ GError **error);
+
+gboolean gsecret_service_unlock (GSecretService *self,
+ GList *objects,
+ GList **unlocked,
+ GSecretPrompt *prompt,
+ GError **error);
+
+gboolean gsecret_service_unlock_for_paths (GSecretService *self,
+ GList *objects,
+ GList **unlocked,
+ GSecretPrompt *prompt,
+ GError **error);
+
+GHashTable* gsecret_service_get_secrets (GList *items,
+ GError **error);
+
+GHashTable* gsecret_service_get_secrets_for_paths (GList *items,
+ GError **error);
+
+gsecret_collection_create_collection
+
+GList* gsecret_service_get_collections
+
+GSecretCollection* gsecret_service_read_alias (GSecretService *self,
+ const gchar *alias,
+ GError **error);
+
+GSecretCollection* gsecret_service_set_alias (GSecretService *self,
+ const gchar *alias,
+ GSecretCollection *collection,
+ GError **error);
+
+#endif
+
+G_END_DECLS
+
+#endif /* __G_SERVICE_H___ */
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __GSECRET_TYPES_H__
+#define __GSECRET_TYPES_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define GSECRET_ERROR (gsecret_error_get_quark ())
+
+GQuark gsecret_error_get_quark (void) G_GNUC_CONST;
+
+typedef enum {
+ GSECRET_ERROR_PROTOCOL = 1,
+} GSecretError;
+
+G_END_DECLS
+
+#endif /* __G_SERVICE_H___ */
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include "config.h"
+
+#include "gsecret-private.h"
+
+#include <string.h>
+
+gchar *
+_gsecret_util_parent_path (const gchar *path)
+{
+ const gchar *pos;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ pos = strrchr (path, '/');
+ g_return_val_if_fail (pos != NULL, NULL);
+ g_return_val_if_fail (pos != path, NULL);
+
+ pos--;
+ return g_strndup (path, pos - path);
+}
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include "config.h"
+
+#include "gsecret-value.h"
+
+#include "egg/egg-secure-memory.h"
+
+#include <string.h>
+
+EGG_SECURE_DECLARE (gsecret_value);
+
+struct _GSecretValue {
+ gint refs;
+ gpointer secret;
+ gsize length;
+ GDestroyNotify destroy;
+ gchar *content_type;
+};
+
+GType
+gsecret_value_get_type (void)
+{
+ static gsize initialized = 0;
+ static GType type = 0;
+
+ if (g_once_init_enter (&initialized)) {
+ type = g_boxed_type_register_static ("GSecretValue",
+ (GBoxedCopyFunc)gsecret_value_ref,
+ (GBoxedFreeFunc)gsecret_value_unref);
+ g_once_init_leave (&initialized, 1);
+ }
+
+ return type;
+}
+
+GSecretValue*
+gsecret_value_new (const gchar *secret, gssize length, const gchar *content_type)
+{
+ gchar *copy;
+
+ g_return_val_if_fail (!secret && length, NULL);
+ g_return_val_if_fail (content_type, NULL);
+
+ if (length < 0)
+ length = strlen (secret);
+
+ copy = egg_secure_alloc (length + 1);
+ memcpy (copy, secret, length);
+ copy[length] = 0;
+ return gsecret_value_new_full (copy, length, content_type, egg_secure_free);
+}
+
+GSecretValue*
+gsecret_value_new_full (gchar *secret, gssize length,
+ const gchar *content_type, GDestroyNotify destroy)
+{
+ GSecretValue *value;
+
+ g_return_val_if_fail (!secret && length, NULL);
+ g_return_val_if_fail (content_type, NULL);
+
+ if (length < 0)
+ length = strlen (secret);
+
+ value = g_slice_new0 (GSecretValue);
+ value->content_type = strdup (content_type);
+ value->destroy = destroy;
+ value->length = length;
+ value->secret = secret;
+
+ return value;
+}
+
+const gchar*
+gsecret_value_get (GSecretValue *value, gsize *length)
+{
+ g_return_val_if_fail (value, NULL);
+ if (length)
+ *length = value->length;
+ return value->secret;
+}
+
+const gchar*
+gsecret_value_get_content_type (GSecretValue *value)
+{
+ g_return_val_if_fail (value, NULL);
+ return value->content_type;
+}
+
+GSecretValue*
+gsecret_value_ref (GSecretValue *value)
+{
+ g_return_val_if_fail (value, NULL);
+ g_atomic_int_inc (&value->refs);
+ return value;
+}
+
+void
+gsecret_value_unref (gpointer value)
+{
+ GSecretValue *val = value;
+
+ g_return_if_fail (value);
+
+ if (g_atomic_int_dec_and_test (&val->refs)) {
+ g_free (val->content_type);
+ if (val->destroy)
+ (val->destroy) (val->secret);
+ g_slice_free (GSecretValue, val);
+ }
+}
* See the included COPYING file for more information.
*/
-#ifndef __GSECRET_DATA_H__
-#define __GSECRET_DATA_H__
+#ifndef __GSECRET_VALUE_H__
+#define __GSECRET_VALUE_H__
#include <gio/gio.h>
G_BEGIN_DECLS
-#define GSECRET_TYPE_DATA (gsecret_service_get_type ())
+#define GSECRET_TYPE_VALUE (gsecret_service_get_type ())
-typedef struct _GSecretData GSecretData;
+typedef struct _GSecretValue GSecretValue;
-GType gsecret_data_get_type (void) G_GNUC_CONST;
+GType gsecret_value_get_type (void) G_GNUC_CONST;
-GSecretData* gsecret_data_new (const gchar *secret,
+GSecretValue* gsecret_value_new (const gchar *secret,
gssize length,
const gchar *content_type);
-GSecretData* gsecret_data_new_full (gchar *secret,
+GSecretValue* gsecret_value_new_full (gchar *secret,
gssize length,
const gchar *content_type,
GDestroyNotify destroy);
-const gchar* gsecret_data_get (GSecretData *data,
+const gchar* gsecret_value_get (GSecretValue *value,
gsize *length);
-const gchar* gsecret_data_get_content_type (GSecretData *data);
+const gchar* gsecret_value_get_content_type (GSecretValue *value);
-GSecretData* gsecret_data_ref (GSecretData *data);
+GSecretValue* gsecret_value_ref (GSecretValue *value);
-void gsecret_data_unref (GSecretData *data);
+void gsecret_value_unref (gpointer value);
G_END_DECLS
--- /dev/null
+include $(top_srcdir)/Makefile.decl
+
+INCLUDES = \
+ -I$(top_srcdir)/library \
+ $(NULL)
+
+LDADD = \
+ $(top_builddir)/egg/libegg.la \
+ $(top_builddir)/library/libgsecret.la \
+ $(NULL)
+
+TEST_PROGS = \
+ test-initial \
+ $(NULL)
+
+check_PROGRAMS = \
+ $(TEST_PROGS)
+
+noinst_PROGRAMS = \
+ $(NULL)
+
+test: $(TEST_PROGS)
+ gtester -k --verbose $(TEST_PROGS)
+
+all-local: $(check_PROGRAMS)
+
+check-local: test
\ No newline at end of file
--- /dev/null
+/* GSecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2011 Collabora Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+
+#include "config.h"
+
+#include "gsecret-item.h"
+#include "gsecret-service.h"
+
+#include <glib.h>
+
+static void
+test_initial (void)
+{
+ GType type;
+
+ type = gsecret_service_get_type ();
+ type += gsecret_item_get_type ();
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+ g_set_prgname ("test-other");
+
+ g_test_add_func ("/initial", test_initial);
+
+ return g_test_run ();
+}