implementing #3987

This commit is contained in:
Christian Grothoff 2016-03-21 01:45:53 +01:00
parent 737e3f4bf6
commit 6f8fa678c1
8 changed files with 159 additions and 69 deletions

View File

@ -1,4 +1,4 @@
.TH TALER\-AUDITOR\-SIGN 1 "Sep 15, 2015" "GNU Taler" .TH TALER\-AUDITOR\-SIGN 1 "Mar 15, 2016" "GNU Taler"
.SH NAME .SH NAME
taler\-auditor\-sign \- Sign exchange denomination as auditor. taler\-auditor\-sign \- Sign exchange denomination as auditor.
@ -22,6 +22,9 @@ Print short help on options.
.IP "\-m KEY, \-\-exchange-key=KEY" .IP "\-m KEY, \-\-exchange-key=KEY"
Public key of the exchange in Crockford base32 encoding, for example as generated by gnunet\-ecc \-p. Public key of the exchange in Crockford base32 encoding, for example as generated by gnunet\-ecc \-p.
.B .B
.IP "\-u URL, \-\-auditor-url=URL"
URL of the auditor. Provides informative link for the user to learn more about the auditor.
.B
.IP "\-r FILE, \-\-exchange-request=FILE" .IP "\-r FILE, \-\-exchange-request=FILE"
File with the exchange's denomination key signing request as generated by taler\-exchange\-keyup \-o. File with the exchange's denomination key signing request as generated by taler\-exchange\-keyup \-o.
.B .B

View File

@ -360,16 +360,18 @@ parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
unsigned int len; unsigned int len;
unsigned int off; unsigned int off;
unsigned int i; unsigned int i;
const char *auditor_url;
struct TALER_ExchangeKeyValidityPS kv; struct TALER_ExchangeKeyValidityPS kv;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("auditor_pub", GNUNET_JSON_spec_fixed_auto ("auditor_pub",
&auditor->auditor_pub), &auditor->auditor_pub),
GNUNET_JSON_spec_string ("auditor_url",
&auditor_url),
GNUNET_JSON_spec_json ("denomination_keys", GNUNET_JSON_spec_json ("denomination_keys",
&keys), &keys),
GNUNET_JSON_spec_end() GNUNET_JSON_spec_end()
}; };
auditor->auditor_url = NULL; /* #3987 */
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_JSON_parse (auditor_obj, GNUNET_JSON_parse (auditor_obj,
spec, spec,
@ -378,8 +380,12 @@ parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
auditor->auditor_url = GNUNET_strdup (auditor_url);
kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS); kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS);
kv.purpose.size = htonl (sizeof (struct TALER_ExchangeKeyValidityPS)); kv.purpose.size = htonl (sizeof (struct TALER_ExchangeKeyValidityPS));
GNUNET_CRYPTO_hash (auditor_url,
strlen (auditor_url) + 1,
&kv.auditor_url_hash);
kv.master = key_data->master_pub; kv.master = key_data->master_pub;
len = json_array_size (keys); len = json_array_size (keys);
auditor->denom_keys = GNUNET_new_array (len, auditor->denom_keys = GNUNET_new_array (len,

View File

@ -49,6 +49,11 @@ static char *exchange_request_file;
*/ */
static char *output_file; static char *output_file;
/**
* URL of the auditor (informative for the user).
*/
static char *auditor_url;
/** /**
* Master public key of the exchange. * Master public key of the exchange.
*/ */
@ -134,6 +139,10 @@ main (int argc,
{'m', "exchange-key", "KEY", {'m', "exchange-key", "KEY",
"public key of the exchange (Crockford base32 encoded)", 1, "public key of the exchange (Crockford base32 encoded)", 1,
&GNUNET_GETOPT_set_filename, &exchange_public_key}, &GNUNET_GETOPT_set_filename, &exchange_public_key},
{'u', "auditor-url", "URL",
"URL of the auditor (informative link for the user)", 1,
&GNUNET_GETOPT_set_string, &auditor_url},
TALER_GETOPT_OPTION_HELP ("Private key of the auditor to use for signing"),
{'r', "exchange-request", "FILE", {'r', "exchange-request", "FILE",
"set of keys the exchange requested the auditor to sign", 1, "set of keys the exchange requested the auditor to sign", 1,
&GNUNET_GETOPT_set_string, &exchange_request_file}, &GNUNET_GETOPT_set_string, &exchange_request_file},
@ -168,6 +177,12 @@ main (int argc,
"Auditor key file not given\n"); "Auditor key file not given\n");
return 1; return 1;
} }
if (NULL == auditor_url)
{
fprintf (stderr,
"Auditor URL not given\n");
return 1;
}
eddsa_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (auditor_key_file); eddsa_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (auditor_key_file);
if (NULL == eddsa_priv) if (NULL == eddsa_priv)
{ {
@ -240,6 +255,9 @@ main (int argc,
dks_len = in_size / sizeof (struct TALER_DenominationKeyValidityPS); dks_len = in_size / sizeof (struct TALER_DenominationKeyValidityPS);
kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS); kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS);
kv.purpose.size = htonl (sizeof (struct TALER_ExchangeKeyValidityPS)); kv.purpose.size = htonl (sizeof (struct TALER_ExchangeKeyValidityPS));
GNUNET_CRYPTO_hash (auditor_url,
strlen (auditor_url) + 1,
&kv.auditor_url_hash);
kv.master = master_public_key; kv.master = master_public_key;
dks = GNUNET_new_array (dks_len, dks = GNUNET_new_array (dks_len,
struct TALER_DenominationKeyValidityPS); struct TALER_DenominationKeyValidityPS);
@ -281,8 +299,6 @@ main (int argc,
GNUNET_CRYPTO_eddsa_sign (eddsa_priv, GNUNET_CRYPTO_eddsa_sign (eddsa_priv,
&kv.purpose, &kv.purpose,
&sigs[i].eddsa_sig); &sigs[i].eddsa_sig);
} }
if (NULL == output_file) if (NULL == output_file)
@ -299,6 +315,7 @@ main (int argc,
if (GNUNET_OK != if (GNUNET_OK !=
TALER_EXCHANGEDB_auditor_write (output_file, TALER_EXCHANGEDB_auditor_write (output_file,
&apub, &apub,
auditor_url,
sigs, sigs,
&master_public_key, &master_public_key,
dks_len, dks_len,

View File

@ -419,6 +419,7 @@ reload_keys_sign_iter (void *cls,
* Convert information from an auditor to a JSON object. * Convert information from an auditor to a JSON object.
* *
* @param apub the auditor's public key * @param apub the auditor's public key
* @param auditor_url URL of the auditor
* @param dki_len length of @a dki and @a asigs arrays * @param dki_len length of @a dki and @a asigs arrays
* @param asigs the auditor's signatures * @param asigs the auditor's signatures
* @param dki array of denomination coin data signed by the auditor * @param dki array of denomination coin data signed by the auditor
@ -426,6 +427,7 @@ reload_keys_sign_iter (void *cls,
*/ */
static json_t * static json_t *
auditor_to_json (const struct TALER_AuditorPublicKeyP *apub, auditor_to_json (const struct TALER_AuditorPublicKeyP *apub,
const char *auditor_url,
unsigned int dki_len, unsigned int dki_len,
const struct TALER_AuditorSignatureP **asigs, const struct TALER_AuditorSignatureP **asigs,
const struct TALER_DenominationKeyValidityPS **dki) const struct TALER_DenominationKeyValidityPS **dki)
@ -444,8 +446,9 @@ auditor_to_json (const struct TALER_AuditorPublicKeyP *apub,
GNUNET_JSON_from_data (asigs[i], GNUNET_JSON_from_data (asigs[i],
sizeof (struct TALER_AuditorSignatureP)))); sizeof (struct TALER_AuditorSignatureP))));
return return
json_pack ("{s:o, s:o}", json_pack ("{s:o, s:s, s:o}",
"denomination_keys", ja, "denomination_keys", ja,
"auditor_url", auditor_url,
"auditor_pub", "auditor_pub",
GNUNET_JSON_from_data (apub, GNUNET_JSON_from_data (apub,
sizeof (struct TALER_AuditorPublicKeyP))); sizeof (struct TALER_AuditorPublicKeyP)));
@ -460,6 +463,7 @@ auditor_to_json (const struct TALER_AuditorPublicKeyP *apub,
* *
* @param cls closure with the `struct TMH_KS_StateHandle *` * @param cls closure with the `struct TMH_KS_StateHandle *`
* @param apub the auditor's public key * @param apub the auditor's public key
* @param auditor_url URL of the auditor
* @param mpub the exchange's public key (as expected by the auditor) * @param mpub the exchange's public key (as expected by the auditor)
* @param dki_len length of @a dki and @a asigs * @param dki_len length of @a dki and @a asigs
* @param asigs array with the auditor's signatures, of length @a dki_len * @param asigs array with the auditor's signatures, of length @a dki_len
@ -471,6 +475,7 @@ auditor_to_json (const struct TALER_AuditorPublicKeyP *apub,
static int static int
reload_auditor_iter (void *cls, reload_auditor_iter (void *cls,
const struct TALER_AuditorPublicKeyP *apub, const struct TALER_AuditorPublicKeyP *apub,
const char *auditor_url,
const struct TALER_MasterPublicKeyP *mpub, const struct TALER_MasterPublicKeyP *mpub,
unsigned int dki_len, unsigned int dki_len,
const struct TALER_AuditorSignatureP *asigs, const struct TALER_AuditorSignatureP *asigs,
@ -508,6 +513,7 @@ reload_auditor_iter (void *cls,
/* add auditor information to our /keys response */ /* add auditor information to our /keys response */
json_array_append_new (ctx->auditors_array, json_array_append_new (ctx->auditors_array,
auditor_to_json (apub, auditor_to_json (apub,
auditor_url,
keep, keep,
kept_asigs, kept_asigs,
kept_dkis)); kept_dkis));

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015 GNUnet e.V. Copyright (C) 2014, 2015, 2016 Inria & GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software terms of the GNU General Public License as published by the Free Software
@ -388,6 +388,11 @@ struct AuditorFileHeaderP
*/ */
struct TALER_MasterPublicKeyP mpub; struct TALER_MasterPublicKeyP mpub;
/**
* Number of signatures and DKI entries in this file.
*/
uint32_t dki_len;
}; };
GNUNET_NETWORK_STRUCT_END GNUNET_NETWORK_STRUCT_END
@ -412,7 +417,9 @@ auditor_iter (void *cls,
struct AuditorFileHeaderP *af; struct AuditorFileHeaderP *af;
const struct TALER_AuditorSignatureP *sigs; const struct TALER_AuditorSignatureP *sigs;
const struct TALER_DenominationKeyValidityPS *dki; const struct TALER_DenominationKeyValidityPS *dki;
unsigned int len; const char *auditor_url;
unsigned int dki_len;
size_t url_len;
int ret; int ret;
if (GNUNET_OK != GNUNET_DISK_file_size (filename, if (GNUNET_OK != GNUNET_DISK_file_size (filename,
@ -425,10 +432,7 @@ auditor_iter (void *cls,
filename); filename);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if ( (size < sizeof (struct AuditorFileHeaderP)) || if (size < sizeof (struct AuditorFileHeaderP))
(0 != (len = ((size - sizeof (struct AuditorFileHeaderP)) %
(sizeof (struct TALER_DenominationKeyValidityPS) +
sizeof (struct TALER_AuditorSignatureP))))) )
{ {
GNUNET_break (0); GNUNET_break (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
@ -445,12 +449,49 @@ auditor_iter (void *cls,
GNUNET_free (af); GNUNET_free (af);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
dki_len = ntohl (af->dki_len);
if (0 == dki_len)
{
GNUNET_break_op (0);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"No signed keys in %s\n",
filename);
GNUNET_free (af);
return GNUNET_SYSERR;
}
if ( (size - sizeof (struct AuditorFileHeaderP)) / dki_len <
(sizeof (struct TALER_DenominationKeyValidityPS) +
sizeof (struct TALER_AuditorSignatureP)) )
{
GNUNET_break_op (0);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Malformed key file %s\n",
filename);
GNUNET_free (af);
return GNUNET_SYSERR;
}
url_len = size
- sizeof (struct AuditorFileHeaderP)
- dki_len * (sizeof (struct TALER_DenominationKeyValidityPS) +
sizeof (struct TALER_AuditorSignatureP));
sigs = (const struct TALER_AuditorSignatureP *) &af[1]; sigs = (const struct TALER_AuditorSignatureP *) &af[1];
dki = (const struct TALER_DenominationKeyValidityPS *) &sigs[len]; dki = (const struct TALER_DenominationKeyValidityPS *) &sigs[dki_len];
auditor_url = (const char *) &dki[dki_len];
if ( (0 == url_len) ||
('\0' != auditor_url[url_len - 1]) )
{
GNUNET_break_op (0);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Malformed key file %s\n",
filename);
GNUNET_free (af);
return GNUNET_SYSERR;
}
ret = aic->it (aic->it_cls, ret = aic->it (aic->it_cls,
&af->apub, &af->apub,
auditor_url,
&af->mpub, &af->mpub,
len, dki_len,
sigs, sigs,
dki); dki);
GNUNET_free (af); GNUNET_free (af);
@ -498,6 +539,7 @@ TALER_EXCHANGEDB_auditor_iterate (const char *exchange_base_dir,
* *
* @param filename the file where to write the auditor information to * @param filename the file where to write the auditor information to
* @param apub the auditor's public key * @param apub the auditor's public key
* @param auditor_url the URL of the auditor
* @param asigs the auditor's signatures, array of length @a dki_len * @param asigs the auditor's signatures, array of length @a dki_len
* @param mpub the exchange's public key (as expected by the auditor) * @param mpub the exchange's public key (as expected by the auditor)
* @param dki_len length of @a dki * @param dki_len length of @a dki
@ -507,6 +549,7 @@ TALER_EXCHANGEDB_auditor_iterate (const char *exchange_base_dir,
int int
TALER_EXCHANGEDB_auditor_write (const char *filename, TALER_EXCHANGEDB_auditor_write (const char *filename,
const struct TALER_AuditorPublicKeyP *apub, const struct TALER_AuditorPublicKeyP *apub,
const char *auditor_url,
const struct TALER_AuditorSignatureP *asigs, const struct TALER_AuditorSignatureP *asigs,
const struct TALER_MasterPublicKeyP *mpub, const struct TALER_MasterPublicKeyP *mpub,
unsigned int dki_len, unsigned int dki_len,
@ -521,6 +564,7 @@ TALER_EXCHANGEDB_auditor_write (const char *filename,
af.apub = *apub; af.apub = *apub;
af.mpub = *mpub; af.mpub = *mpub;
af.dki_len = htonl ((uint32_t) dki_len);
ret = GNUNET_SYSERR; ret = GNUNET_SYSERR;
if (NULL == (fh = GNUNET_DISK_file_open if (NULL == (fh = GNUNET_DISK_file_open
(filename, (filename,
@ -546,6 +590,12 @@ TALER_EXCHANGEDB_auditor_write (const char *filename,
dki, dki,
wsize)) wsize))
ret = GNUNET_OK; ret = GNUNET_OK;
wsize = strlen (auditor_url) + 1;
if (wsize ==
GNUNET_DISK_file_write (fh,
auditor_url,
wsize))
ret = GNUNET_OK;
cleanup: cleanup:
eno = errno; eno = errno;
if (NULL != fh) if (NULL != fh)

View File

@ -208,19 +208,19 @@ struct TALER_EXCHANGE_DenomPublicKey
struct TALER_EXCHANGE_AuditorInformation struct TALER_EXCHANGE_AuditorInformation
{ {
/** /**
* Public key of the auditing institution. * Public key of the auditing institution. Wallets and merchants
* are expected to be configured with a set of public keys of
* auditors that they deem acceptable. These public keys are
* the roots of the Taler PKI.
*/ */
struct TALER_AuditorPublicKeyP auditor_pub; struct TALER_AuditorPublicKeyP auditor_pub;
/** /**
* URL of the auditing institution. The application must check that * URL of the auditing institution. Signed by the auditor's public
* this is an acceptable auditor for its purpose and also verify * key, this URL is a place where applications can direct users for
* that the @a auditor_pub matches the auditor's public key given at * additional information about the auditor. In the future, there
* that website. We expect that in practice software is going to * should also be an auditor API for automated submission about
* often ship with an initial list of accepted auditors, just like * claims of misbehaving exchange providers.
* browsers ship with a CA root store.
*
* This field may be NULL. (#3987).
*/ */
const char *auditor_url; const char *auditor_url;
@ -230,7 +230,7 @@ struct TALER_EXCHANGE_AuditorInformation
unsigned int num_denom_keys; unsigned int num_denom_keys;
/** /**
* Array of length @a denom_keys with the denomination * Array of length @a num_denom_keys with the denomination
* keys audited by this auditor. Note that the array * keys audited by this auditor. Note that the array
* elements point to the same locations as the entries * elements point to the same locations as the entries
* in the key's main `denom_keys` array. * in the key's main `denom_keys` array.

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015 GNUnet e.V. Copyright (C) 2014, 2015, 2016 Inria & GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software terms of the GNU General Public License as published by the Free Software
@ -212,6 +212,7 @@ TALER_EXCHANGEDB_denomination_key_read (const char *filename,
* *
* @param cls closure * @param cls closure
* @param apub the auditor's public key * @param apub the auditor's public key
* @param auditor_url URL of the auditor
* @param mpub the exchange's public key (as expected by the auditor) * @param mpub the exchange's public key (as expected by the auditor)
* @param dki_len length of @a asig and @a dki arrays * @param dki_len length of @a asig and @a dki arrays
* @param asigs array of the auditor's signatures over the @a dks, of length @a dki_len * @param asigs array of the auditor's signatures over the @a dks, of length @a dki_len
@ -223,6 +224,7 @@ TALER_EXCHANGEDB_denomination_key_read (const char *filename,
typedef int typedef int
(*TALER_EXCHANGEDB_AuditorIterator)(void *cls, (*TALER_EXCHANGEDB_AuditorIterator)(void *cls,
const struct TALER_AuditorPublicKeyP *apub, const struct TALER_AuditorPublicKeyP *apub,
const char *auditor_url,
const struct TALER_MasterPublicKeyP *mpub, const struct TALER_MasterPublicKeyP *mpub,
unsigned int dki_len, unsigned int dki_len,
const struct TALER_AuditorSignatureP *asigs, const struct TALER_AuditorSignatureP *asigs,
@ -253,6 +255,7 @@ TALER_EXCHANGEDB_auditor_iterate (const char *exchange_base_dir,
* *
* @param filename the file where to write the auditor information to * @param filename the file where to write the auditor information to
* @param apub the auditor's public key * @param apub the auditor's public key
* @param auditor_url the URL of the auditor
* @param asigs the auditor's signatures, array of length @a dki_len * @param asigs the auditor's signatures, array of length @a dki_len
* @param mpub the exchange's public key (as expected by the auditor) * @param mpub the exchange's public key (as expected by the auditor)
* @param dki_len length of @a dki and @a asigs arrays * @param dki_len length of @a dki and @a asigs arrays
@ -262,6 +265,7 @@ TALER_EXCHANGEDB_auditor_iterate (const char *exchange_base_dir,
int int
TALER_EXCHANGEDB_auditor_write (const char *filename, TALER_EXCHANGEDB_auditor_write (const char *filename,
const struct TALER_AuditorPublicKeyP *apub, const struct TALER_AuditorPublicKeyP *apub,
const char *auditor_url,
const struct TALER_AuditorSignatureP *asigs, const struct TALER_AuditorSignatureP *asigs,
const struct TALER_MasterPublicKeyP *mpub, const struct TALER_MasterPublicKeyP *mpub,
unsigned int dki_len, unsigned int dki_len,
@ -287,5 +291,4 @@ void
TALER_EXCHANGEDB_plugin_unload (struct TALER_EXCHANGEDB_Plugin *plugin); TALER_EXCHANGEDB_plugin_unload (struct TALER_EXCHANGEDB_Plugin *plugin);
#endif #endif

View File

@ -655,9 +655,14 @@ struct TALER_ExchangeKeyValidityPS
*/ */
struct GNUNET_CRYPTO_EccSignaturePurpose purpose; struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Hash of the auditor's URL.
*/
struct GNUNET_HashCode auditor_url_hash;
/** /**
* The long-term offline master key of the exchange, affirmed by the * The long-term offline master key of the exchange, affirmed by the
* auditor. * auditor. Hashed string, including 0-terminator.
*/ */
struct TALER_MasterPublicKeyP master; struct TALER_MasterPublicKeyP master;