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 | |
| parent | 440d0e6ea4ddc677d6e3046bc64cdf0013f5b7ad (diff) | |
add logic to parse and check secmod signatures
| -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 92b220e1..8b1feb15 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 7148af51..dfee6776 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:  | 
