mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2024-12-22 04:38:55 +00:00
More Implementation of GSecretService session related code.
This commit is contained in:
parent
3dfd7aa70f
commit
b1b54f525d
3
.gitignore
vendored
3
.gitignore
vendored
@ -22,5 +22,8 @@ Makefile.in
|
||||
Makefile.in.in
|
||||
missing
|
||||
stamp*
|
||||
.settings
|
||||
.project
|
||||
.cproject
|
||||
|
||||
/po/POTFILES
|
||||
|
@ -0,0 +1 @@
|
||||
NULL =
|
@ -8,7 +8,7 @@ ORIGDIR=`pwd`
|
||||
cd $srcdir
|
||||
PROJECT=gsecret
|
||||
TEST_TYPE=-f
|
||||
FILE=library/gsecret-data.c
|
||||
FILE=library/gsecret-value.c
|
||||
|
||||
DIE=0
|
||||
|
||||
|
16
configure.ac
16
configure.ac
@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
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
|
||||
@ -70,10 +70,12 @@ fi
|
||||
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
|
||||
|
@ -6,5 +6,7 @@ INCLUDES = \
|
||||
-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)
|
||||
|
353
egg/egg-dh.c
Normal file
353
egg/egg-dh.c
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
50
egg/egg-dh.h
Normal file
50
egg/egg-dh.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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_ */
|
109
egg/egg-hkdf.c
Normal file
109
egg/egg-hkdf.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* gnome-keyring
|
||||
*
|
||||
* Copyright (C) 2011 Collabora Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Author: Stef Walter <stefw@collabora.co.uk>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "egg-hkdf.h"
|
||||
#include "egg-secure-memory.h"
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
gboolean
|
||||
egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
|
||||
gconstpointer salt, gsize n_salt, gconstpointer info,
|
||||
gsize n_info, gpointer output, gsize n_output)
|
||||
{
|
||||
gpointer alloc = NULL;
|
||||
gpointer buffer = NULL;
|
||||
gcry_md_hd_t md1, md2;
|
||||
guint hash_len;
|
||||
guchar i;
|
||||
gint flags, algo;
|
||||
gsize step, n_buffer;
|
||||
guchar *at;
|
||||
gcry_error_t gcry;
|
||||
|
||||
algo = gcry_md_map_name (hash_algo);
|
||||
g_return_val_if_fail (algo != 0, FALSE);
|
||||
|
||||
hash_len = gcry_md_get_algo_dlen (algo);
|
||||
g_return_val_if_fail (hash_len != 0, FALSE);
|
||||
g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);
|
||||
|
||||
/* Buffer we need to for intermediate stuff */
|
||||
if (gcry_is_secure (input)) {
|
||||
flags = GCRY_MD_FLAG_SECURE;
|
||||
buffer = gcry_malloc_secure (hash_len);
|
||||
} else {
|
||||
flags = 0;
|
||||
buffer = gcry_malloc (hash_len);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (buffer, FALSE);
|
||||
n_buffer = 0;
|
||||
|
||||
/* Salt defaults to hash_len zeros */
|
||||
if (!salt) {
|
||||
salt = alloc = g_malloc0 (hash_len);
|
||||
n_salt = hash_len;
|
||||
}
|
||||
|
||||
/* Step 1: Extract */
|
||||
gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC | 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;
|
||||
}
|
39
egg/egg-hkdf.h
Normal file
39
egg/egg-hkdf.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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_ */
|
@ -97,20 +97,22 @@ typedef void* word_t;
|
||||
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;
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@ -263,6 +265,8 @@ pool_free (void* item)
|
||||
unused_push (&pool->unused, item);
|
||||
}
|
||||
|
||||
#ifndef G_DISABLE_ASSERT
|
||||
|
||||
static int
|
||||
pool_valid (void* item)
|
||||
{
|
||||
@ -282,6 +286,8 @@ pool_valid (void* item)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* G_DISABLE_ASSERT */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SEC ALLOCATION
|
||||
*
|
||||
@ -459,7 +465,9 @@ sec_neighbor_after (Block *block, Cell *cell)
|
||||
}
|
||||
|
||||
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;
|
||||
@ -467,8 +475,9 @@ sec_alloc (Block *block, size_t length)
|
||||
|
||||
ASSERT (block);
|
||||
ASSERT (length);
|
||||
ASSERT (tag);
|
||||
|
||||
if (!block->unused)
|
||||
if (!block->unused_cells)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
@ -482,10 +491,10 @@ sec_alloc (Block *block, size_t length)
|
||||
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;
|
||||
}
|
||||
@ -493,8 +502,9 @@ sec_alloc (Block *block, size_t length)
|
||||
|
||||
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);
|
||||
@ -516,10 +526,12 @@ sec_alloc (Block *block, size_t length)
|
||||
}
|
||||
|
||||
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
|
||||
@ -555,16 +567,19 @@ sec_free (Block *block, void *memory)
|
||||
#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);
|
||||
@ -574,12 +589,13 @@ sec_free (Block *block, void *memory)
|
||||
|
||||
/* 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;
|
||||
@ -587,25 +603,30 @@ sec_free (Block *block, void *memory)
|
||||
|
||||
/* 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;
|
||||
@ -621,13 +642,12 @@ sec_realloc (Block *block, void *memory, size_t length)
|
||||
|
||||
/* 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;
|
||||
|
||||
@ -635,7 +655,7 @@ sec_realloc (Block *block, void *memory, size_t length)
|
||||
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
|
||||
@ -658,14 +678,14 @@ sec_realloc (Block *block, void *memory, size_t length)
|
||||
|
||||
/* 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 */
|
||||
@ -679,18 +699,19 @@ sec_realloc (Block *block, void *memory, size_t length)
|
||||
}
|
||||
|
||||
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);
|
||||
@ -722,15 +743,14 @@ sec_allocated (Block *block, void *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
|
||||
@ -753,15 +773,19 @@ sec_validate (Block *block)
|
||||
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);
|
||||
}
|
||||
@ -777,13 +801,15 @@ sec_validate (Block *block)
|
||||
*/
|
||||
|
||||
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 ();
|
||||
@ -793,16 +819,16 @@ sec_acquire_pages (size_t *sz)
|
||||
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);
|
||||
@ -850,11 +876,14 @@ sec_release_pages (void *pages, size_t 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;
|
||||
@ -874,7 +903,7 @@ sec_block_create (size_t size)
|
||||
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);
|
||||
@ -889,10 +918,10 @@ sec_block_create (size_t size)
|
||||
/* 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;
|
||||
|
||||
@ -907,7 +936,7 @@ sec_block_destroy (Block *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) {
|
||||
@ -919,11 +948,12 @@ sec_block_destroy (Block *block)
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@ -938,17 +968,16 @@ sec_block_destroy (Block *block)
|
||||
*/
|
||||
|
||||
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",
|
||||
@ -963,16 +992,16 @@ egg_secure_alloc_full (size_t length, int flags)
|
||||
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
|
||||
@ -981,8 +1010,8 @@ egg_secure_alloc_full (size_t length, int flags)
|
||||
#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);
|
||||
@ -995,19 +1024,19 @@ egg_secure_alloc_full (size_t length, int flags)
|
||||
}
|
||||
|
||||
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",
|
||||
@ -1016,7 +1045,7 @@ egg_secure_realloc_full (void *memory, size_t length, int flags)
|
||||
}
|
||||
|
||||
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;
|
||||
@ -1034,8 +1063,8 @@ egg_secure_realloc_full (void *memory, size_t length, int flags)
|
||||
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,
|
||||
@ -1050,13 +1079,13 @@ egg_secure_realloc_full (void *memory, size_t length, int flags)
|
||||
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.
|
||||
@ -1070,9 +1099,9 @@ egg_secure_realloc_full (void *memory, size_t length, int flags)
|
||||
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);
|
||||
@ -1088,7 +1117,7 @@ egg_secure_realloc_full (void *memory, size_t length, int 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
|
||||
@ -1115,14 +1144,14 @@ egg_secure_free_full (void *memory, int flags)
|
||||
|
||||
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)
|
||||
@ -1164,35 +1193,87 @@ egg_secure_validate (void)
|
||||
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;
|
||||
}
|
||||
@ -1231,5 +1312,5 @@ egg_secure_strfree (char *str)
|
||||
*/
|
||||
|
||||
egg_secure_strclear (str);
|
||||
egg_secure_free_full (str, GKR_SECURE_USE_FALLBACK);
|
||||
egg_secure_free_full (str, EGG_SECURE_USE_FALLBACK);
|
||||
}
|
||||
|
@ -70,15 +70,22 @@ extern void* egg_memory_fallback (void *p, size_t length);
|
||||
* 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);
|
||||
|
||||
@ -90,12 +97,18 @@ int egg_secure_check (const 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 */
|
||||
|
@ -1,6 +1,6 @@
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
NULL =
|
||||
SUBDIRS = . tests
|
||||
|
||||
module_flags = \
|
||||
-export_dynamic \
|
||||
@ -12,7 +12,11 @@ module_flags = \
|
||||
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 \
|
||||
|
67
library/gsecret-collection.h
Normal file
67
library/gsecret-collection.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* 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___ */
|
@ -1,118 +0,0 @@
|
||||
/* 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);
|
||||
}
|
||||
}
|
297
library/gsecret-item.c
Normal file
297
library/gsecret-item.c
Normal file
@ -0,0 +1,297 @@
|
||||
/* 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 */
|
120
library/gsecret-item.h
Normal file
120
library/gsecret-item.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* 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___ */
|
42
library/gsecret-private.h
Normal file
42
library/gsecret-private.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* 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___ */
|
57
library/gsecret-prompt.h
Normal file
57
library/gsecret-prompt.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* 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___ */
|
691
library/gsecret-service.c
Normal file
691
library/gsecret-service.c
Normal file
@ -0,0 +1,691 @@
|
||||
/* 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;
|
||||
}
|
192
library/gsecret-service.h
Normal file
192
library/gsecret-service.h
Normal file
@ -0,0 +1,192 @@
|
||||
/* 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___ */
|
30
library/gsecret-types.h
Normal file
30
library/gsecret-types.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* 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___ */
|
32
library/gsecret-util.c
Normal file
32
library/gsecret-util.c
Normal file
@ -0,0 +1,32 @@
|
||||
/* 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);
|
||||
}
|
122
library/gsecret-value.c
Normal file
122
library/gsecret-value.c
Normal file
@ -0,0 +1,122 @@
|
||||
/* 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);
|
||||
}
|
||||
}
|
@ -10,36 +10,36 @@
|
||||
* 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
|
||||
|
27
library/tests/Makefile.am
Normal file
27
library/tests/Makefile.am
Normal file
@ -0,0 +1,27 @@
|
||||
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
|
39
library/tests/test-initial.c
Normal file
39
library/tests/test-initial.c
Normal file
@ -0,0 +1,39 @@
|
||||
/* 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 ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user