implement TALER_CRYPTO_helper_cs_r_derive and related tests
This commit is contained in:
parent
875a8b397e
commit
106664ed0c
@ -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,
|
* Will cause the helper to tell all clients that the key is now unavailable,
|
||||||
* and to create a replacement key.
|
* and to create a replacement key.
|
||||||
*
|
*
|
||||||
@ -1812,7 +1812,7 @@ TALER_CRYPTO_helper_cs_sign (
|
|||||||
* callback.
|
* callback.
|
||||||
*
|
*
|
||||||
* @param dh helper to process connection
|
* @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
|
void
|
||||||
TALER_CRYPTO_helper_cs_revoke (
|
TALER_CRYPTO_helper_cs_revoke (
|
||||||
@ -1820,6 +1820,30 @@ TALER_CRYPTO_helper_cs_revoke (
|
|||||||
const struct TALER_CsPubHashP *h_cs);
|
const struct TALER_CsPubHashP *h_cs);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Close connection to @a dh.
|
||||||
*
|
*
|
||||||
|
@ -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
|
void
|
||||||
TALER_CRYPTO_helper_cs_disconnect (
|
TALER_CRYPTO_helper_cs_disconnect (
|
||||||
struct TALER_CRYPTO_CsDenominationHelper *dh)
|
struct TALER_CRYPTO_CsDenominationHelper *dh)
|
||||||
|
@ -618,7 +618,6 @@ handle_r_derive_request (struct TES_Client *client,
|
|||||||
&rdf.header);
|
&rdf.header);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: print nonce too?
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Received request to derive R with key %s\n",
|
"Received request to derive R with key %s\n",
|
||||||
GNUNET_h2s (&rdr->h_cs.hash));
|
GNUNET_h2s (&rdr->h_cs.hash));
|
||||||
@ -692,7 +691,7 @@ cs_work_dispatch (struct TES_Client *client,
|
|||||||
return handle_revoke_request (
|
return handle_revoke_request (
|
||||||
client,
|
client,
|
||||||
(const struct TALER_CRYPTO_CsRevokeRequest *) hdr);
|
(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))
|
if (msize != sizeof (struct TALER_CRYPTO_CsRDeriveRequest))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
|
@ -255,6 +255,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.
|
* Test signing logic.
|
||||||
*
|
*
|
||||||
@ -600,9 +727,11 @@ run_test (void)
|
|||||||
" Done (%u keys)\n",
|
" Done (%u keys)\n",
|
||||||
num_keys);
|
num_keys);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
// TODO: implement other tests
|
|
||||||
if (0 == ret)
|
if (0 == ret)
|
||||||
ret = test_revocation (dh);
|
ret = test_revocation (dh);
|
||||||
|
if (0 == ret)
|
||||||
|
ret = test_r_derive (dh);
|
||||||
|
// TODO: implement other tests
|
||||||
// if (0 == ret)
|
// if (0 == ret)
|
||||||
// ret = test_signing (dh);
|
// ret = test_signing (dh);
|
||||||
// if (0 == ret)
|
// if (0 == ret)
|
||||||
@ -685,6 +814,7 @@ main (int argc,
|
|||||||
(int) code);
|
(int) code);
|
||||||
ret = 5;
|
ret = 5;
|
||||||
}
|
}
|
||||||
|
// TODO: remove
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"I am here");
|
"I am here");
|
||||||
GNUNET_OS_process_destroy (helper);
|
GNUNET_OS_process_destroy (helper);
|
||||||
|
Loading…
Reference in New Issue
Block a user