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

@ -60,6 +60,201 @@ struct TALER_EXCHANGE_ManagementGetKeysHandle
};
/**
* Handle the case that the response was of type #MHD_HTTP_OK.
*
* @param[in,out] gh request handle
* @param response the response
* @return #MHD_OK if the response was well-formed
*/
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 (response,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
fk.num_sign_keys = json_array_size (sk);
fk.num_denom_keys = json_array_size (dk);
fk.sign_keys = GNUNET_new_array (
fk.num_sign_keys,
struct TALER_EXCHANGE_FutureSigningPublicKey);
fk.denom_keys = GNUNET_new_array (
fk.num_denom_keys,
struct TALER_EXCHANGE_FutureDenomPublicKey);
ok = true;
for (unsigned int i = 0; i<fk.num_sign_keys; i++)
{
json_t *j = json_array_get (sk,
i);
struct TALER_EXCHANGE_FutureSigningPublicKey *sign_key
= &fk.sign_keys[i];
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",
&sign_key->valid_until),
TALER_JSON_spec_absolute_time ("stamp_end",
&sign_key->valid_legal),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
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++)
{
json_t *j = json_array_get (dk,
i);
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",
&denom_key->withdraw_valid_until),
TALER_JSON_spec_absolute_time ("stamp_start",
&denom_key->valid_from),
TALER_JSON_spec_absolute_time ("stamp_expire_legal",
&denom_key->expire_legal),
TALER_JSON_spec_amount ("value",
&denom_key->value),
TALER_JSON_spec_amount ("fee_withdraw",
&denom_key->fee_withdraw),
TALER_JSON_spec_amount ("fee_deposit",
&denom_key->fee_deposit),
TALER_JSON_spec_amount ("fee_refresh",
&denom_key->fee_refresh),
TALER_JSON_spec_amount ("fee_refund",
&denom_key->fee_refund),
GNUNET_JSON_spec_rsa_public_key ("denom_pub",
&denom_key->key.rsa_public_key),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
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);
}
for (unsigned int i = 0; i<fk.num_denom_keys; i++)
{
if (NULL != fk.denom_keys[i].key.rsa_public_key)
{
GNUNET_CRYPTO_rsa_public_key_free (
fk.denom_keys[i].key.rsa_public_key);
fk.denom_keys[i].key.rsa_public_key = NULL;
}
}
GNUNET_free (fk.sign_keys);
GNUNET_free (fk.denom_keys);
GNUNET_JSON_parse_free (spec);
return (ok) ? GNUNET_OK : GNUNET_SYSERR;
}
/**
* Function called when we're done processing the
* HTTP GET /management/keys request.
@ -84,129 +279,15 @@ handle_get_keys_finished (void *cls,
switch (response_code)
{
case MHD_HTTP_OK:
if (GNUNET_OK ==
handle_ok (gh,
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_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
response_code = 0;
break;
}
fk.num_sign_keys = json_array_size (sk);
fk.num_denom_keys = json_array_size (dk);
fk.sign_keys = GNUNET_new_array (
fk.num_sign_keys,
struct TALER_EXCHANGE_FutureSigningPublicKey);
fk.denom_keys = GNUNET_new_array (
fk.num_denom_keys,
struct TALER_EXCHANGE_FutureDenomPublicKey);
ok = true;
for (unsigned int i = 0; i<fk.num_sign_keys; i++)
{
json_t *j = json_array_get (sk,
i);
struct TALER_EXCHANGE_FutureSigningPublicKey *sign_key
= &fk.sign_keys[i];
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("key",
&sign_key->key),
TALER_JSON_spec_absolute_time ("stamp_start",
&sign_key->valid_from),
TALER_JSON_spec_absolute_time ("stamp_expire",
&sign_key->valid_until),
TALER_JSON_spec_absolute_time ("stamp_end",
&sign_key->valid_legal),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
ok = false;
break;
}
}
for (unsigned int i = 0; i<fk.num_denom_keys; i++)
{
json_t *j = json_array_get (dk,
i);
struct TALER_EXCHANGE_FutureDenomPublicKey *denom_key
= &fk.denom_keys[i];
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_absolute_time ("stamp_expire_deposit",
&denom_key->expire_deposit),
TALER_JSON_spec_absolute_time ("stamp_expire_withdraw",
&denom_key->withdraw_valid_until),
TALER_JSON_spec_absolute_time ("stamp_start",
&denom_key->valid_from),
TALER_JSON_spec_absolute_time ("stamp_expire_legal",
&denom_key->expire_legal),
TALER_JSON_spec_amount ("value",
&denom_key->value),
TALER_JSON_spec_amount ("fee_withdraw",
&denom_key->fee_withdraw),
TALER_JSON_spec_amount ("fee_deposit",
&denom_key->fee_deposit),
TALER_JSON_spec_amount ("fee_refresh",
&denom_key->fee_refresh),
TALER_JSON_spec_amount ("fee_refund",
&denom_key->fee_refund),
GNUNET_JSON_spec_rsa_public_key ("denom_pub",
&denom_key->key.rsa_public_key),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
ok = false;
break;
}
}
if (ok)
{
gh->cb (gh->cb_cls,
&hr,
&fk);
gh->cb = NULL;
}
for (unsigned int i = 0; i<fk.num_denom_keys; i++)
{
if (NULL != fk.denom_keys[i].key.rsa_public_key)
{
GNUNET_CRYPTO_rsa_public_key_free (
fk.denom_keys[i].key.rsa_public_key);
fk.denom_keys[i].key.rsa_public_key = NULL;
}
}
GNUNET_free (fk.sign_keys);
GNUNET_free (fk.denom_keys);
if (! ok)
{
response_code = 0;
break;
}
gh->cb = NULL;
}
else
{
response_code = 0;
}
break;
default: