add logic to parse and check secmod signatures

This commit is contained in:
Christian Grothoff 2020-11-26 15:00:34 +01:00
parent 440d0e6ea4
commit 2c88cff283
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
2 changed files with 228 additions and 122 deletions

View File

@ -1930,6 +1930,11 @@ struct TALER_EXCHANGE_FutureSigningPublicKey
*/
struct TALER_ExchangePublicKeyP key;
/**
* Signature by the security module affirming it owns this key.
*/
struct TALER_SecurityModuleSignatureP signkey_secmod_sig;
/**
* Validity start time
*/
@ -1957,6 +1962,11 @@ struct TALER_EXCHANGE_FutureDenomPublicKey
*/
struct TALER_DenominationPublicKey key;
/**
* Signature by the security module affirming it owns this key.
*/
struct TALER_SecurityModuleSignatureP denom_secmod_sig;
/**
* Timestamp indicating when the denomination key becomes valid
*/
@ -2026,6 +2036,21 @@ struct TALER_EXCHANGE_FutureKeys
*/
struct TALER_EXCHANGE_FutureDenomPublicKey *denom_keys;
/**
* Public key of the signkey security module.
*/
struct TALER_SecurityModulePublicKeyP signkey_secmod_public_key;
/**
* Public key of the denomination security module.
*/
struct TALER_SecurityModulePublicKeyP denom_secmod_public_key;
/**
* Offline master public key used by this exchange.
*/
struct TALER_MasterPublicKeyP master_pub;
/**
* Length of the @e sign_keys array (number of valid entries).
*/

View File

@ -61,51 +61,41 @@ struct TALER_EXCHANGE_ManagementGetKeysHandle
/**
* Function called when we're done processing the
* HTTP GET /management/keys request.
* Handle the case that the response was of type #MHD_HTTP_OK.
*
* @param cls the `struct TALER_EXCHANGE_ManagementGetKeysHandle *`
* @param response_code HTTP response code, 0 on error
* @param response response body, NULL if not in JSON
* @param[in,out] gh request handle
* @param response the response
* @return #MHD_OK if the response was well-formed
*/
static void
handle_get_keys_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_ManagementGetKeysHandle *gh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
};
gh->job = NULL;
switch (response_code)
{
case MHD_HTTP_OK:
static int
handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
const json_t *response)
{
struct TALER_EXCHANGE_FutureKeys fk;
json_t *sk;
json_t *dk;
bool ok;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("future_denoms",
&dk),
GNUNET_JSON_spec_json ("future_signkeys",
&sk),
GNUNET_JSON_spec_fixed_auto ("master_pub",
&fk.master_pub),
GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key",
&fk.denom_secmod_public_key),
GNUNET_JSON_spec_fixed_auto ("signkey_secmod_public_key",
&fk.signkey_secmod_public_key),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
GNUNET_JSON_parse (response,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
response_code = 0;
break;
return GNUNET_SYSERR;
}
fk.num_sign_keys = json_array_size (sk);
fk.num_denom_keys = json_array_size (dk);
@ -125,6 +115,8 @@ handle_get_keys_finished (void *cls,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("key",
&sign_key->key),
GNUNET_JSON_spec_fixed_auto ("signkey_secmod_sig",
&sign_key->signkey_secmod_sig),
TALER_JSON_spec_absolute_time ("stamp_start",
&sign_key->valid_from),
TALER_JSON_spec_absolute_time ("stamp_expire",
@ -143,6 +135,30 @@ handle_get_keys_finished (void *cls,
ok = false;
break;
}
{
struct GNUNET_TIME_Relative duration
= GNUNET_TIME_absolute_get_difference (sign_key->valid_from,
sign_key->valid_until);
struct TALER_SigningKeyAnnouncementPS ska = {
.purpose.purpose = htonl (TALER_SIGNATURE_SM_SIGNING_KEY),
.purpose.size = htonl (sizeof (ska)),
.exchange_pub = sign_key->key,
.anchor_time = GNUNET_TIME_absolute_hton (sign_key->valid_from),
.duration = GNUNET_TIME_relative_hton (duration)
};
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_SM_SIGNING_KEY,
&ska,
&sign_key->signkey_secmod_sig.eddsa_signature,
&fk.signkey_secmod_public_key.eddsa_pub))
{
GNUNET_break_op (0);
ok = false;
break;
}
}
}
for (unsigned int i = 0; i<fk.num_denom_keys; i++)
{
@ -151,6 +167,8 @@ handle_get_keys_finished (void *cls,
struct TALER_EXCHANGE_FutureDenomPublicKey *denom_key
= &fk.denom_keys[i];
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("denom_secmod_sig",
&denom_key->denom_secmod_sig),
TALER_JSON_spec_absolute_time ("stamp_expire_deposit",
&denom_key->expire_deposit),
TALER_JSON_spec_absolute_time ("stamp_expire_withdraw",
@ -183,13 +201,43 @@ handle_get_keys_finished (void *cls,
ok = false;
break;
}
{
struct GNUNET_TIME_Relative duration
= GNUNET_TIME_absolute_get_difference (denom_key->valid_from,
denom_key->withdraw_valid_until);
struct TALER_DenominationKeyAnnouncementPS dka = {
.purpose.purpose = htonl (TALER_SIGNATURE_SM_DENOMINATION_KEY),
.purpose.size = htonl (sizeof (dka)),
.anchor_time = GNUNET_TIME_absolute_hton (denom_key->valid_from),
.duration_withdraw = GNUNET_TIME_relative_hton (duration)
};
GNUNET_CRYPTO_rsa_public_key_hash (denom_key->key.rsa_public_key,
&dka.h_denom_pub);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_SM_DENOMINATION_KEY,
&dka,
&denom_key->denom_secmod_sig.eddsa_signature,
&fk.denom_secmod_public_key.eddsa_pub))
{
GNUNET_break_op (0);
ok = false;
break;
}
}
}
if (ok)
{
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = MHD_HTTP_OK,
.reply = response
};
gh->cb (gh->cb_cls,
&hr,
&fk);
gh->cb = NULL;
}
for (unsigned int i = 0; i<fk.num_denom_keys; i++)
{
@ -202,11 +250,44 @@ handle_get_keys_finished (void *cls,
}
GNUNET_free (fk.sign_keys);
GNUNET_free (fk.denom_keys);
if (! ok)
GNUNET_JSON_parse_free (spec);
return (ok) ? GNUNET_OK : GNUNET_SYSERR;
}
/**
* Function called when we're done processing the
* HTTP GET /management/keys request.
*
* @param cls the `struct TALER_EXCHANGE_ManagementGetKeysHandle *`
* @param response_code HTTP response code, 0 on error
* @param response response body, NULL if not in JSON
*/
static void
handle_get_keys_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_ManagementGetKeysHandle *gh = cls;
const json_t *json = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.http_status = (unsigned int) response_code,
.reply = json
};
gh->job = NULL;
switch (response_code)
{
case MHD_HTTP_OK:
if (GNUNET_OK ==
handle_ok (gh,
response))
{
gh->cb = NULL;
}
else
{
response_code = 0;
break;
}
}
break;
default: