diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-11-26 15:00:34 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-11-26 15:00:34 +0100 |
commit | 2c88cff2837cb6f8b1b95822dd53f1d338055474 (patch) | |
tree | d7dcb40051c669a4140c21e26660edcbf2e16323 /src | |
parent | 440d0e6ea4ddc677d6e3046bc64cdf0013f5b7ad (diff) | |
download | exchange-2c88cff2837cb6f8b1b95822dd53f1d338055474.tar.xz |
add logic to parse and check secmod signatures
Diffstat (limited to 'src')
-rw-r--r-- | src/include/taler_exchange_service.h | 25 | ||||
-rw-r--r-- | src/lib/exchange_api_management_get_keys.c | 325 |
2 files changed, 228 insertions, 122 deletions
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 92b220e1d..8b1feb157 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -1931,6 +1931,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 */ struct GNUNET_TIME_Absolute valid_from; @@ -1958,6 +1963,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 */ struct GNUNET_TIME_Absolute valid_from; @@ -2027,6 +2037,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). */ unsigned int num_sign_keys; diff --git a/src/lib/exchange_api_management_get_keys.c b/src/lib/exchange_api_management_get_keys.c index 7148af516..dfee6776e 100644 --- a/src/lib/exchange_api_management_get_keys.c +++ b/src/lib/exchange_api_management_get_keys.c @@ -61,6 +61,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: |