diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/include/taler_crypto_lib.h | 28 | ||||
| -rw-r--r-- | src/util/crypto_helper_cs.c | 195 | ||||
| -rw-r--r-- | src/util/taler-exchange-secmod-cs.c | 3 | ||||
| -rw-r--r-- | src/util/test_helper_cs.c | 132 | 
4 files changed, 353 insertions, 5 deletions
| diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index bd889b35..a20e5120 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -1800,7 +1800,7 @@ TALER_CRYPTO_helper_cs_sign (  /** - * Ask the helper to revoke the public key associated with @param h_denom_pub . + * Ask the helper to revoke the public key associated with @param h_cs .   * Will cause the helper to tell all clients that the key is now unavailable,   * and to create a replacement key.   * @@ -1812,7 +1812,7 @@ TALER_CRYPTO_helper_cs_sign (   * callback.   *   * @param dh helper to process connection - * @param h_rsa hash of the RSA public key to revoke + * @param h_cs hash of the CS public key to revoke   */  void  TALER_CRYPTO_helper_cs_revoke ( @@ -1821,6 +1821,30 @@ TALER_CRYPTO_helper_cs_revoke (  /** + * Ask the helper to derive R using the @param nonce and denomination key + * associated with @param h_cs. + * + * This operation will block until the R has been obtained.  Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail.  Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters.  Retrying in this case may work. + * + * @param dh helper to process connection + * @param h_cs hash of the CS public key to revoke + * @param nonce witdhraw nonce + * @param[out] ec set to the error code (or #TALER_EC_NONE on success) + * @return R, the value inside the structure will be NULL on failure, + *         see @a ec for details about the failure + */ +struct TALER_DenominationCsPublicR +TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh, +                                 const struct TALER_CsPubHashP *h_cs, +                                 const struct TALER_WithdrawNonce *nonce, +                                 enum TALER_ErrorCode *ec); + + +/**   * Close connection to @a dh.   *   * @param[in] dh connection to close diff --git a/src/util/crypto_helper_cs.c b/src/util/crypto_helper_cs.c index 95050a1f..5b299934 100644 --- a/src/util/crypto_helper_cs.c +++ b/src/util/crypto_helper_cs.c @@ -633,6 +633,201 @@ TALER_CRYPTO_helper_cs_revoke (  } +struct TALER_DenominationCsPublicR +TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh, +                                 const struct TALER_CsPubHashP *h_cs, +                                 const struct TALER_WithdrawNonce *nonce, +                                 enum TALER_ErrorCode *ec) +{ +  struct TALER_DenominationCsPublicR r_pub; + +  memset (&r_pub, +          0, +          sizeof (r_pub)); + +  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +              "Starting R derivation process\n"); +  if (GNUNET_OK != +      try_connect (dh)) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +                "Failed to connect to helper\n"); +    *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; +    return r_pub; +  } + +  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +              "Requesting R\n"); +  { +    struct TALER_CRYPTO_CsRDeriveRequest rdr; + +    rdr.header.size = htons (sizeof (rdr)); +    rdr.header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE); +    rdr.reserved = htonl (0); +    rdr.h_cs = *h_cs; +    rdr.nonce = *nonce; +    if (GNUNET_OK != +        TALER_crypto_helper_send_all (dh->sock, +                                      &rdr, +                                      sizeof (rdr))) +    { +      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, +                           "send"); +      do_disconnect (dh); +      *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; +      return r_pub; +    } +  } + +  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +              "Awaiting reply\n"); +  { +    char buf[UINT16_MAX]; +    size_t off = 0; +    const struct GNUNET_MessageHeader *hdr +      = (const struct GNUNET_MessageHeader *) buf; +    bool finished = false; + +    *ec = TALER_EC_INVALID; +    while (1) +    { +      uint16_t msize; +      ssize_t ret; + +      ret = recv (dh->sock, +                  &buf[off], +                  sizeof (buf) - off, +                  (finished && (0 == off)) +                  ? MSG_DONTWAIT +                  : 0); +      if (ret < 0) +      { +        if (EINTR == errno) +          continue; +        if (EAGAIN == errno) +        { +          GNUNET_assert (finished); +          GNUNET_assert (0 == off); +          return r_pub; +        } +        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, +                             "recv"); +        do_disconnect (dh); +        *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; +        break; +      } +      if (0 == ret) +      { +        GNUNET_break (0 == off); +        if (! finished) +          *ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG; +        return r_pub; +      } +      off += ret; +more: +      if (off < sizeof (struct GNUNET_MessageHeader)) +        continue; +      msize = ntohs (hdr->size); +      if (off < msize) +        continue; +      switch (ntohs (hdr->type)) +      { +      case TALER_HELPER_CS_MT_RES_RDERIVE: +        if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse)) +        { +          GNUNET_break_op (0); +          do_disconnect (dh); +          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; +          goto end; +        } +        if (finished) +        { +          GNUNET_break_op (0); +          do_disconnect (dh); +          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; +          goto end; +        } +        { +          const struct TALER_CRYPTO_RDeriveResponse *rdr = +            (const struct TALER_CRYPTO_RDeriveResponse *) buf; + +          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                      "Received R\n"); +          *ec = TALER_EC_NONE; +          finished = true; +          r_pub = rdr->r_pub; +          break; +        } +      case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE: +        if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure)) +        { +          GNUNET_break_op (0); +          do_disconnect (dh); +          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; +          goto end; +        } +        { +          const struct TALER_CRYPTO_RDeriveFailure *rdf = +            (const struct TALER_CRYPTO_RDeriveFailure *) buf; + +          *ec = (enum TALER_ErrorCode) ntohl (rdf->ec); +          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                      "R derivation failed!\n"); +          finished = true; +          break; +        } +      case TALER_HELPER_CS_MT_AVAIL: +        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                    "Received new key!\n"); +        if (GNUNET_OK != +            handle_mt_avail (dh, +                             hdr)) +        { +          GNUNET_break_op (0); +          do_disconnect (dh); +          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; +          goto end; +        } +        break; /* while(1) loop ensures we recvfrom() again */ +      case TALER_HELPER_CS_MT_PURGE: +        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                    "Received revocation!\n"); +        if (GNUNET_OK != +            handle_mt_purge (dh, +                             hdr)) +        { +          GNUNET_break_op (0); +          do_disconnect (dh); +          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; +          goto end; +        } +        break; /* while(1) loop ensures we recvfrom() again */ +      case TALER_HELPER_CS_SYNCED: +        GNUNET_log (GNUNET_ERROR_TYPE_WARNING, +                    "Synchronized add odd time with CS helper!\n"); +        dh->synced = true; +        break; +      default: +        GNUNET_break_op (0); +        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                    "Received unexpected message of type %u\n", +                    ntohs (hdr->type)); +        do_disconnect (dh); +        *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; +        goto end; +      } +      memmove (buf, +               &buf[msize], +               off - msize); +      off -= msize; +      goto more; +    } /* while(1) */ +end: +    return r_pub; +  } +} + +  void  TALER_CRYPTO_helper_cs_disconnect (    struct TALER_CRYPTO_CsDenominationHelper *dh) diff --git a/src/util/taler-exchange-secmod-cs.c b/src/util/taler-exchange-secmod-cs.c index 14f0a5d1..0df7c3dd 100644 --- a/src/util/taler-exchange-secmod-cs.c +++ b/src/util/taler-exchange-secmod-cs.c @@ -618,7 +618,6 @@ handle_r_derive_request (struct TES_Client *client,                           &rdf.header);    } -  // TODO: print nonce too?    GNUNET_log (GNUNET_ERROR_TYPE_INFO,                "Received request to derive R with key %s\n",                GNUNET_h2s (&rdr->h_cs.hash)); @@ -692,7 +691,7 @@ cs_work_dispatch (struct TES_Client *client,      return handle_revoke_request (        client,        (const struct TALER_CRYPTO_CsRevokeRequest *) hdr); -  case TALER_HELPER_CS_MT_RES_RDERIVE: +  case TALER_HELPER_CS_MT_REQ_RDERIVE:      if (msize != sizeof (struct TALER_CRYPTO_CsRDeriveRequest))      {        GNUNET_break_op (0); diff --git a/src/util/test_helper_cs.c b/src/util/test_helper_cs.c index 41d363fd..d59c2163 100644 --- a/src/util/test_helper_cs.c +++ b/src/util/test_helper_cs.c @@ -256,6 +256,133 @@ test_revocation (struct TALER_CRYPTO_CsDenominationHelper *dh)  /** + * Test R derivation logic. + * + * @param dh handle to the helper + * @return 0 on success + */ +static int +test_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh) +{ +  struct TALER_DenominationCsPublicR r_pub; +  enum TALER_ErrorCode ec; +  bool success = false; +  struct TALER_PlanchetSecretsP ps; +  struct TALER_CoinPubHash c_hash; + +  TALER_planchet_setup_random (&ps, TALER_DENOMINATION_RSA); +  for (unsigned int i = 0; i<MAX_KEYS; i++) +  { +    if (! keys[i].valid) +      continue; +    // TODO: insert assertion into other checks +    GNUNET_assert (TALER_DENOMINATION_CS == keys[i].denom_pub.cipher); +    { +      struct TALER_PlanchetDetail pd; +      pd.blinded_planchet.cipher = TALER_DENOMINATION_CS; + +      TALER_cs_withdraw_nonce_derive (&ps.coin_priv, +                                      &pd.blinded_planchet.details. +                                      cs_blinded_planchet.nonce); +      GNUNET_log (GNUNET_ERROR_TYPE_INFO, +                  "Requesting R derivation with key %s\n", +                  GNUNET_h2s (&keys[i].h_cs.hash)); +      r_pub = TALER_CRYPTO_helper_cs_r_derive (dh, +                                               &keys[i].h_cs, +                                               &pd.blinded_planchet.details. +                                               cs_blinded_planchet.nonce, +                                               &ec); +    } +    switch (ec) +    { +    case TALER_EC_NONE: +      if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( +                                      keys[i].start_time.abs_time), +                                    >, +                                    GNUNET_TIME_UNIT_SECONDS)) +      { +        /* key worked too early */ +        GNUNET_break (0); +        return 4; +      } +      if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( +                                      keys[i].start_time.abs_time), +                                    >, +                                    keys[i].validity_duration)) +      { +        /* key worked too later */ +        GNUNET_break (0); +        return 5; +      } + +      // since R is part of the signature creation process, it can't be tested fully here +      // instead it will be further tested in the signature creation process +      GNUNET_log (GNUNET_ERROR_TYPE_INFO, +                  "Received valid R for key %s\n", +                  GNUNET_h2s (&keys[i].h_cs.hash)); +      success = true; +      break; +    case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY: +      /* This 'failure' is expected, we're testing also for the +         error handling! */ +      if ( (GNUNET_TIME_relative_is_zero ( +              GNUNET_TIME_absolute_get_remaining ( +                keys[i].start_time.abs_time))) && +           (GNUNET_TIME_relative_cmp ( +              GNUNET_TIME_absolute_get_duration ( +                keys[i].start_time.abs_time), +              <, +              keys[i].validity_duration)) ) +      { +        /* key should have worked! */ +        GNUNET_break (0); +        return 6; +      } +      break; +    default: +      /* unexpected error */ +      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                  "Unexpected error %d\n", +                  ec); +      return 7; +    } +  } +  if (! success) +  { +    /* no valid key for signing found, also bad */ +    GNUNET_break (0); +    return 16; +  } + +  /* check R derivation does not work if the key is unknown */ +  { +    struct TALER_CsPubHashP rnd; +    struct TALER_WithdrawNonce nonce; + +    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, +                                &rnd, +                                sizeof (rnd)); +    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, +                                &nonce, +                                sizeof (nonce)); +    r_pub = TALER_CRYPTO_helper_cs_r_derive (dh, +                                             &rnd, +                                             &nonce, +                                             &ec); +    if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec) +    { +      GNUNET_break (0); +      return 17; +    } +    GNUNET_log (GNUNET_ERROR_TYPE_INFO, +                "R derivation with invalid key %s failed as desired\n", +                GNUNET_h2s (&rnd.hash)); +  } +  return 0; +} + + +/**   * Test signing logic.   *   * @param dh handle to the helper @@ -600,9 +727,11 @@ run_test (void)             " Done (%u keys)\n",             num_keys);    ret = 0; -  // TODO: implement other tests    if (0 == ret)      ret = test_revocation (dh); +  if (0 == ret) +    ret = test_r_derive (dh); +  // TODO: implement other tests    // if (0 == ret)    //   ret = test_signing (dh);    // if (0 == ret) @@ -685,6 +814,7 @@ main (int argc,                  (int) code);      ret = 5;    } +  // TODO: remove    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                "I am here");    GNUNET_OS_process_destroy (helper); | 
