Browse Source

Merge branch 'develop'

master v0.2.0
Damien Goutte-Gattat 5 years ago
parent
commit
5dd3cd2384
  1. 2
      Makefile.am
  2. 3
      NEWS
  3. 42
      README.md
  4. 8
      configure.ac
  5. 8
      man/gfsec-use.1.in
  6. 57
      src/gfsec-use.c
  7. 58
      src/secretcfg.c
  8. 2
      src/share.c
  9. 1
      src/share.h

2
Makefile.am

@ -2,4 +2,4 @@ SUBDIRS = lib src man
ACLOCAL_AMFLAGS = -I m4 --install
dist_doc_DATA = AUTHORS COPYING README
dist_doc_DATA = AUTHORS COPYING README.md NEWS

3
NEWS

@ -0,0 +1,3 @@
Changes in gfsecret 0.2.0
* Check share data against SHA-256 hash.

42
README → README.md

@ -13,20 +13,20 @@ sticks and/or MTP-compliant devices like some smartphones or audio
players).
The program needs a configuration file (by default,
$XDG_CONFIG_HOME/gfsecret/default.conf) which describes the shared
`$XDG_CONFIG_HOME/gfsecret/default.conf`) which describes the shared
secret. Here is a sample configuration:
OUTFILE=/home/alice/mysecret
MINSHARES=2
URI=file:///home/alice/.local/share/gfsecret/mysecret.024
URI=label://MYSTICK/mysecretfile.070
URI=mtp://RF2GB6X704P/Documents/mysecret.139
OUTFILE=/home/alice/mysecret
MINSHARES=2
URI=file:///home/alice/.local/share/gfsecret/mysecret.024
URI=label://MYSTICK/mysecretfile.070
URI=mtp://RF2GB6X704P/Documents/mysecret.139
With such a configuration, gfse-use will attempt to reconstruct the file
‘/home/alice/mysecret’, using at least two of the three available
`/home/alice/mysecret`, using at least two of the three available
shares: one available on the local filesystem, one on a USB storage
device with the label ‘MYSTICK’, and one on a MTP-compliant device with
the serial number ‘RF2GB6X704P’. Gfsec-use will automatically detect
device with the label `MYSTICK`, and one on a MTP-compliant device with
the serial number `RF2GB6X704P`. Gfsec-use will automatically detect
which devices are currently connected and will fetch from them the
corresponding shares.
@ -41,29 +41,29 @@ Install
-------
Gfsecret depends on the following libraries at compile-time:
– libgfshare <http://www.digital-scurf.org/software/libgfshare>, which
implements the secret sharing scheme proper (mandatory);
– GIO <http://developer.gnome.org/gio/>, to access shares stored on
external volumes (typically USB storage) (optional);
– libmtp <http://libmtp.sourceforge.net/>, to access shares stored on
MTP-compliant devices (optional).
- [libgfshare](http://www.digital-scurf.org/software/libgfshare), which
implements the secret sharing scheme proper (mandatory);
- [libgcrypt](http://www.gnupg.org/), for the SHA-256 implementation
(mandatory);
- [GIO](http://developer.gnome.org/gio/), to access shares stored on
external volumes (typically USB storage) (optional);
- [libmtp](http://libmtp.sourceforge.net/), to access shares stored on
MTP-compliant devices (optional).
Copying
-------
Gfsecret is distributed under the terms of the GNU General Public
License, version 3 or higher. The full license is included in the
COPYING file of the source distribution.
[COPYING file](COPYING) of the source distribution.
Homepage and contact
--------------------
The project is located at <http://www.incenp.org/dvlpt/gfsecret.html>.
The project is located at http://www.incenp.org/dvlpt/gfsecret.html.
The latest source code is available in a Git repository at
<git://git.incenp.org/gfsecret.git> and may also be browsed at
<http://www.incenp.org/gitweb/?p=gfsecret.git;a=summary>.
git://git.incenp.org/gfsecret.git and may also be browsed at
http://www.incenp.org/gitweb/?p=gfsecret.git;a=summary.
The author may be contacted at the following address:
Damien Goutte-Gattat <dgouttegattat@incenp.org>

8
configure.ac

@ -1,6 +1,6 @@
dnl Configure template for the gfsecret package
AC_INIT([gfsecret], [0.1.0],
AC_INIT([gfsecret], [0.2.0],
[dgouttegattat@incenp.org])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])
@ -18,6 +18,12 @@ AC_PROG_INSTALL
dnl Check for some non-ubiquitous functions
ICP_CHECK_NOTCH_FUNCS
dnl Check for Libgcrypt
AM_PATH_LIBGCRYPT([1.6.0],
[CFLAGS="$CFLAGS $LIBGCRYPT_FLAGS"
LIBS="$LIBS $LIBGCRYPT_LIBS"],
[AC_MSG_ERROR([libgcrypt not found])])
dnl Check for Libgfshare
PKG_CHECK_MODULES([LIBGFSHARE], [libgfshare])

8
man/gfsec-use.1.in

@ -94,13 +94,19 @@ whole secret and not only a share (in that case, the
previous remark about the share number in the extension
does not apply).
.PP
Another parameter is \fIsha256\fR, which specifies the
expected SHA-256 hash value of the share data. If such a
parameter is specified, a share will only be used if the
data matches the expected hash value.
.SH EXAMPLE CONFIGURATION FILE
.PP
.nf
OUTFILE=/home/alice/mysecret
MINSHARES=2
URI=file:///home/alice/.local/share/gfsecret/mysecret.024
URI=label://USBSTICK/mysecret.070
URI=label://USBSTICK/mysecret.070?sha256=\fIhex_hash\fR
URI=mtp://RF2GB6X704P/Documents/mysecret.139
.fi

57
src/gfsec-use.c

@ -33,6 +33,7 @@
#include <err.h>
#include <libgfshare.h>
#include <gcrypt.h>
#include "util.h"
#include "share.h"
@ -123,8 +124,22 @@ get_config_file(const char *filename, char *buffer, size_t len)
return rc;
}
static char *
get_share_display_name(gfsec_share_t *share)
{
static char buffer[256];
char *schemes[] = { "file://", "uuid://", "label://", "mtp://" };
snprintf(buffer, sizeof(buffer), "%s%s%s",
schemes[share->scheme],
share->authority ? share->authority : "",
share->path);
return buffer;
}
static int
get_share_data(gfsec_share_t *share)
get_share_data(gfsec_share_t *share, gcry_md_hd_t md)
{
int rc = -1;
@ -153,21 +168,23 @@ get_share_data(gfsec_share_t *share)
break;
}
return rc;
}
if ( rc == 0 && share->sha256 ) {
unsigned char *md_val;
static char *
get_share_display_name(gfsec_share_t *share)
{
static char buffer[256];
char *schemes[] = { "file://", "uuid://", "label://", "mtp://" };
gcry_md_write(md, share->data, share->length);
md_val = gcry_md_read(md, 0);
snprintf(buffer, sizeof(buffer), "%s%s%s",
schemes[share->scheme],
share->authority ? share->authority : "",
share->path);
if ( memcmp(share->sha256, md_val, 32) != 0 ) {
warnx("Incorrect hash value for share %s\n", get_share_display_name(share));
free(share->data);
share->data = NULL;
rc = -1;
}
return buffer;
gcry_md_reset(md);
}
return rc;
}
int
@ -180,6 +197,7 @@ main(int argc, char **argv)
gfsec_share_t *share;
unsigned have_shares, have_full;
pid_t pid;
gcry_md_hd_t md;
struct option options[] = {
{ "help", 0, NULL, 'h' },
@ -219,6 +237,12 @@ main(int argc, char **argv)
gfsec_mtp_init();
if ( ! gcry_check_version(GCRYPT_VERSION) )
errx(EXIT_FAILURE, "libgcrypt version mismatch");
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
if ( get_config_file(cfg_file, cfg_path, sizeof(cfg_path)) == -1 )
err(EXIT_FAILURE, "Cannot find configuration file");
@ -228,10 +252,13 @@ main(int argc, char **argv)
if ( ! output_file && ! (output_file = cfg->output_file) )
errx(EXIT_FAILURE, "No output file specified");
if ( gcry_md_open(&md, GCRY_MD_SHA256, 0) )
errx(EXIT_FAILURE, "Cannot create hashing context");
share = cfg->shares;
while ( share ) {
if ( get_share_data(share) == 0 ) {
if ( get_share_data(share, md) == 0 ) {
if ( (share->flags & GFSEC_SHARE_FLAGS_FULL) > 0 )
have_full = 1;
else
@ -243,6 +270,8 @@ main(int argc, char **argv)
share = share->next;
}
gcry_md_close(md);
if ( have_full ) {
share = cfg->shares;
while ( share ) {

58
src/secretcfg.c

@ -125,6 +125,57 @@ parse_path(const char **uri)
return path;
}
/**
* Parses a hexadecimal-encoded SHA-256 hash value.
*
* @param hex The encoded hash to parse.
* @param len The length of the \a hex buffer.
*
* @return A newly allocated buffer containing the
* hash value, or NULL if an error occured.
*/
static unsigned char *
parse_sha256(const char *hex, size_t len)
{
unsigned char *sha256 = NULL;
unsigned n;
if ( len != 64 ) {
errno = EBADMSG;
return NULL;
}
if ( ! (sha256 = malloc(32)) )
return NULL;
for ( n = 0; n < len; n++ ) {
unsigned char h, val;
h = hex[n];
if ( h >= '0' && h <= '9' )
val = h - '0';
else if ( h >= 'A' && h <= 'F' )
val = h - 'A' + 10;
else if ( h >= 'a' && h <= 'f' )
val = h - 'a' + 10;
else
n = 99;
if ( n % 2 == 0 )
sha256[n / 2] = val << 4;
else
sha256[n / 2] += val;
}
if ( n == 100 ) {
free(sha256);
sha256 = NULL;
}
return sha256;
}
/**
* Parses a name=value parameter in the provided string.
* Advances the pointer to the next character after the
@ -157,6 +208,12 @@ parse_parameter(const char **uri, gfsec_share_t *share)
share->flags |= GFSEC_SHARE_FLAGS_FULL;
*uri = amp;
}
else if ( strncmp(*uri, "sha256", eq - *uri) == 0 ) {
amp = strchrnul(++eq, '&');
if ( ! (share->sha256 = parse_sha256(eq, amp - eq)) )
rc = -1;
*uri = amp;
}
else { /* Skip unknown parameter. */
while ( **uri != '\0' && **uri != '&' )
(*uri) += 1;
@ -223,6 +280,7 @@ parse_uri(const char *uri, gfsec_secret_config_t *cfg)
share->flags = GFSEC_SHARE_FLAGS_NONE;
share->length = 0;
share->data = NULL;
share->sha256 = NULL;
if ( strncmp(p, "file://", 7) == 0 && (p += 7) )
share->scheme = SCHEME_FILE;

2
src/share.c

@ -44,6 +44,8 @@ gfsec_destroy_share(gfsec_share_t *share, int linked)
memset(share->data, 0, share->length);
free(share->data);
}
if ( share->sha256 )
free(share->sha256);
if ( linked ) {
gfsec_share_t *tmp = share->next;

1
src/share.h

@ -40,6 +40,7 @@ typedef struct gfsec_share {
unsigned flags;
size_t length;
unsigned char *data;
unsigned char *sha256;
} gfsec_share_t;
#ifdef __cpluscplus

Loading…
Cancel
Save