diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-11-22 22:25:49 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-11-22 22:25:49 +0100 |
commit | 171391057d82c6483ea40d589e2bf89a2064a125 (patch) | |
tree | b6b3c998bafc8bd8778269f0ef4e9a2c789f57d2 /src/util | |
parent | 1931869c3c64411ee4348c244e8b658493a2493d (diff) |
complete crypto helper denom testing
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/Makefile.am | 2 | ||||
-rw-r--r-- | src/util/crypto_helper_denom.c (renamed from src/util/crypto_helper.c) | 205 | ||||
-rw-r--r-- | src/util/taler-helper-crypto-rsa.c | 49 | ||||
-rw-r--r-- | src/util/test_helper_rsa.c | 171 |
4 files changed, 324 insertions, 103 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 505634381..73edce2cd 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -51,7 +51,7 @@ libtalerutil_la_SOURCES = \ amount.c \ config.c \ crypto.c \ - crypto_helper.c \ + crypto_helper_denom.c \ crypto_wire.c \ getopt.c \ lang.c \ diff --git a/src/util/crypto_helper.c b/src/util/crypto_helper_denom.c index 20ab61ff4..b999be02a 100644 --- a/src/util/crypto_helper.c +++ b/src/util/crypto_helper_denom.c @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** - * @file util/crypto_helper.c + * @file util/crypto_helper_denom.c * @brief utility functions for running out-of-process private key operations * @author Christian Grothoff */ @@ -238,6 +238,97 @@ TALER_CRYPTO_helper_denom_connect ( } +/** + * Handle a #TALER_HELPER_RSA_MT_AVAIL message from the helper. + * + * @param dh helper context + * @param hdr message that we received + * @return #GNUNET_OK on success + */ +static int +handle_mt_avail (struct TALER_CRYPTO_DenominationHelper *dh, + const struct GNUNET_MessageHeader *hdr) +{ + const struct TALER_CRYPTO_RsaKeyAvailableNotification *kan + = (const struct TALER_CRYPTO_RsaKeyAvailableNotification *) hdr; + const char *buf = (const char *) &kan[1]; + const char *section_name; + + if (sizeof (*kan) > ntohs (hdr->size)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (ntohs (hdr->size) != + sizeof (*kan) + + ntohs (kan->pub_size) + + ntohs (kan->section_name_len)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + section_name = &buf[ntohs (kan->pub_size)]; + if ('\0' != section_name[ntohs (kan->section_name_len) - 1]) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + { + struct TALER_DenominationPublicKey denom_pub; + struct GNUNET_HashCode h_denom_pub; + + denom_pub.rsa_public_key + = GNUNET_CRYPTO_rsa_public_key_decode (buf, + ntohs (kan->pub_size)); + if (NULL == denom_pub.rsa_public_key) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key, + &h_denom_pub); + dh->dkc (dh->dkc_cls, + section_name, + GNUNET_TIME_absolute_ntoh (kan->anchor_time), + GNUNET_TIME_relative_ntoh (kan->duration_withdraw), + &h_denom_pub, + &denom_pub); + GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key); + } + return GNUNET_OK; +} + + +/** + * Handle a #TALER_HELPER_RSA_MT_PURGE message from the helper. + * + * @param dh helper context + * @param hdr message that we received + * @return #GNUNET_OK on success + */ +static int +handle_mt_purge (struct TALER_CRYPTO_DenominationHelper *dh, + const struct GNUNET_MessageHeader *hdr) +{ + const struct TALER_CRYPTO_RsaKeyPurgeNotification *pn + = (const struct TALER_CRYPTO_RsaKeyPurgeNotification *) hdr; + + if (sizeof (*pn) != ntohs (hdr->size)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + dh->dkc (dh->dkc_cls, + NULL, + GNUNET_TIME_UNIT_ZERO_ABS, + GNUNET_TIME_UNIT_ZERO, + &pn->h_denom_pub, + NULL); + return GNUNET_OK; +} + + void TALER_CRYPTO_helper_poll (struct TALER_CRYPTO_DenominationHelper *dh) { @@ -275,73 +366,23 @@ TALER_CRYPTO_helper_poll (struct TALER_CRYPTO_DenominationHelper *dh) switch (ntohs (hdr->type)) { case TALER_HELPER_RSA_MT_AVAIL: + if (GNUNET_OK != + handle_mt_avail (dh, + hdr)) { - const struct TALER_CRYPTO_RsaKeyAvailableNotification *kan - = (const struct TALER_CRYPTO_RsaKeyAvailableNotification *) buf; - const char *section_name; - struct TALER_DenominationPublicKey denom_pub; - struct GNUNET_HashCode h_denom_pub; - - if (sizeof (*kan) > ret) - { - GNUNET_break_op (0); - do_disconnect (dh); - return; - } - if (ret != - sizeof (*kan) - + ntohs (kan->pub_size) - + ntohs (kan->section_name_len)) - { - GNUNET_break_op (0); - do_disconnect (dh); - return; - } - if ('\0' != buf[ret - 1]) - { - GNUNET_break_op (0); - do_disconnect (dh); - return; - } - denom_pub.rsa_public_key - = GNUNET_CRYPTO_rsa_public_key_decode (&buf[sizeof (*kan)], - ntohs (kan->pub_size)); - if (NULL == denom_pub.rsa_public_key) - { - GNUNET_break_op (0); - do_disconnect (dh); - return; - } - section_name = &buf[sizeof (*kan) + ntohs (kan->pub_size)]; - GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key, - &h_denom_pub); - dh->dkc (dh->dkc_cls, - section_name, - GNUNET_TIME_absolute_ntoh (kan->anchor_time), - GNUNET_TIME_relative_ntoh (kan->duration_withdraw), - &h_denom_pub, - &denom_pub); - GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key); + GNUNET_break_op (0); + do_disconnect (dh); + return; } break; case TALER_HELPER_RSA_MT_PURGE: + if (GNUNET_OK != + handle_mt_purge (dh, + hdr)) { - const struct TALER_CRYPTO_RsaKeyPurgeNotification *pn - = (const struct TALER_CRYPTO_RsaKeyPurgeNotification *) buf; - - if (sizeof (*pn) != ret) - { - GNUNET_break_op (0); - do_disconnect (dh); - return; - } - - dh->dkc (dh->dkc_cls, - NULL, - GNUNET_TIME_UNIT_ZERO_ABS, - GNUNET_TIME_UNIT_ZERO, - &pn->h_denom_pub, - NULL); + GNUNET_break_op (0); + do_disconnect (dh); + return; } break; default: @@ -399,6 +440,7 @@ TALER_CRYPTO_helper_denom_sign ( GNUNET_break (((size_t) ret) == sizeof (buf)); } + while (1) { char buf[UINT16_MAX]; ssize_t ret; @@ -433,7 +475,7 @@ TALER_CRYPTO_helper_denom_sign ( GNUNET_break_op (0); do_disconnect (dh); *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; - break; + return ds; } { const struct TALER_CRYPTO_SignResponse *sr = @@ -447,7 +489,7 @@ TALER_CRYPTO_helper_denom_sign ( GNUNET_break_op (0); do_disconnect (dh); *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; - break; + return ds; } *ec = TALER_EC_NONE; ds.rsa_signature = rsa_signature; @@ -459,25 +501,44 @@ TALER_CRYPTO_helper_denom_sign ( GNUNET_break_op (0); do_disconnect (dh); *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; - break; + return ds; } { const struct TALER_CRYPTO_SignFailure *sf = (const struct TALER_CRYPTO_SignFailure *) buf; *ec = (enum TALER_ErrorCode) ntohl (sf->ec); - break; + return ds; + } + case TALER_HELPER_RSA_MT_AVAIL: + if (GNUNET_OK != + handle_mt_avail (dh, + hdr)) + { + GNUNET_break_op (0); + do_disconnect (dh); + *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + return ds; + } + break; /* while(1) loop ensures we recvfrom() again */ + case TALER_HELPER_RSA_MT_PURGE: + if (GNUNET_OK != + handle_mt_purge (dh, + hdr)) + { + GNUNET_break_op (0); + do_disconnect (dh); + *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + return ds; } - // FIXME: *could* also receive change in key status! - // Handle that here, and then try again! + break; /* while(1) loop ensures we recvfrom() again */ default: GNUNET_break_op (0); do_disconnect (dh); *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; - break; + return ds; } } - return ds; } @@ -524,4 +585,4 @@ TALER_CRYPTO_helper_denom_disconnect ( } -/* end of crypto_helper.c */ +/* end of crypto_helper_denom.c */ diff --git a/src/util/taler-helper-crypto-rsa.c b/src/util/taler-helper-crypto-rsa.c index 6fda5fec1..abd8014fd 100644 --- a/src/util/taler-helper-crypto-rsa.c +++ b/src/util/taler-helper-crypto-rsa.c @@ -551,6 +551,21 @@ handle_done (void *cls) done_tail, wi); GNUNET_assert (0 == pthread_mutex_unlock (&done_lock)); + if (NULL == wi->rsa_signature) + { + struct TALER_CRYPTO_SignFailure sf = { + .header.size = htons (sizeof (sf)), + .header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE), + .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE) + }; + + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Signing request failed, worker failed to produce signature\n"); + (void) transmit (&wi->addr, + wi->addr_size, + &sf.header); + } + else { struct TALER_CRYPTO_SignResponse *sr; void *buf; @@ -598,7 +613,7 @@ handle_sign_request (const struct sockaddr_un *addr, struct DenominationKey *dk; struct WorkItem *wi; const void *blinded_msg = &sr[1]; - size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (sr); + size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr); dk = GNUNET_CONTAINER_multihashmap_get (keys, &sr->h_denom_pub); @@ -618,9 +633,29 @@ handle_sign_request (const struct sockaddr_un *addr, &sf.header); return; } - // FIXME: check denomination key is valid for signing - // at this time! + if (0 != + GNUNET_TIME_absolute_get_remaining (dk->anchor).rel_value_us) + { + /* it is too early */ + struct TALER_CRYPTO_SignFailure sf = { + .header.size = htons (sizeof (sr)), + .header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE), + .ec = htonl (TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY) + }; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Signing request failed, denomination key %s is not yet valid\n", + GNUNET_h2s (&sr->h_denom_pub)); + (void) transmit (addr, + addr_size, + &sf.header); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received request to sign over %u bytes with key %s\n", + (unsigned int) blinded_msg_size, + GNUNET_h2s (&sr->h_denom_pub)); wi = GNUNET_new (struct WorkItem); wi->addr = *addr; wi->addr_size = addr_size; @@ -1038,11 +1073,13 @@ create_key (struct Denomination *denom) { struct DenominationKey *dk; struct GNUNET_TIME_Absolute anchor; + struct GNUNET_TIME_Absolute now; + now = GNUNET_TIME_absolute_get (); + (void) GNUNET_TIME_round_abs (&now); if (NULL == denom->keys_tail) { - anchor = GNUNET_TIME_absolute_get (); - (void) GNUNET_TIME_round_abs (&anchor); + anchor = now; } else { @@ -1050,6 +1087,8 @@ create_key (struct Denomination *denom) GNUNET_TIME_relative_subtract ( denom->duration_withdraw, overlap_duration)); + if (now.abs_value_us > anchor.abs_value_us) + anchor = now; } dk = GNUNET_new (struct DenominationKey); dk->denom = denom; diff --git a/src/util/test_helper_rsa.c b/src/util/test_helper_rsa.c index 14b3c4a56..2b6c850f8 100644 --- a/src/util/test_helper_rsa.c +++ b/src/util/test_helper_rsa.c @@ -33,6 +33,11 @@ */ #define NUM_REVOKES 10 +/** + * How many iterations of the successful signing test should we run? + */ +#define NUM_SIGN_TESTS 100 + /** * Number of keys currently in #keys. @@ -189,7 +194,7 @@ test_revocation (struct TALER_CRYPTO_DenominationHelper *dh) GNUNET_h2s (&keys[j].h_denom_pub)); TALER_CRYPTO_helper_denom_revoke (dh, &keys[j].h_denom_pub); - for (unsigned int k = 0; k<80; k++) + for (unsigned int k = 0; k<1000; k++) { TALER_CRYPTO_helper_poll (dh); if (! keys[j].revoked) @@ -205,6 +210,7 @@ test_revocation (struct TALER_CRYPTO_DenominationHelper *dh) TALER_CRYPTO_helper_denom_disconnect (dh); return 2; } + fprintf (stderr, "\n"); break; } } @@ -225,7 +231,11 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh) enum TALER_ErrorCode ec; bool success = false; struct GNUNET_HashCode m_hash; + struct GNUNET_CRYPTO_RsaBlindingKeySecret bks; + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + &bks, + sizeof (bks)); GNUNET_CRYPTO_hash ("Hello", strlen ("Hello"), &m_hash); @@ -233,11 +243,26 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh) { if (! keys[i].valid) continue; - ds = TALER_CRYPTO_helper_denom_sign (dh, - &keys[i].h_denom_pub, - &m_hash, - sizeof (m_hash), - &ec); + { + void *buf; + size_t buf_size; + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_rsa_blind (&m_hash, + &bks, + keys[i].denom_pub.rsa_public_key, + &buf, + &buf_size)); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Requesting signature over %u bytes with key %s\n", + (unsigned int) buf_size, + GNUNET_h2s (&keys[i].h_denom_pub)); + ds = TALER_CRYPTO_helper_denom_sign (dh, + &keys[i].h_denom_pub, + buf, + buf_size, + &ec); + GNUNET_free (buf); + } switch (ec) { case TALER_EC_NONE: @@ -255,21 +280,38 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh) GNUNET_break (0); return 5; } - if (GNUNET_OK != - GNUNET_CRYPTO_rsa_verify (&m_hash, - ds.rsa_signature, - keys[i].denom_pub.rsa_public_key)) { - /* signature invalid */ - GNUNET_break (0); + struct GNUNET_CRYPTO_RsaSignature *rs; + + rs = GNUNET_CRYPTO_rsa_unblind (ds.rsa_signature, + &bks, + keys[i].denom_pub.rsa_public_key); + if (NULL == rs) + { + GNUNET_break (0); + return 6; + } GNUNET_CRYPTO_rsa_signature_free (ds.rsa_signature); - return 6; + if (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (&m_hash, + rs, + keys[i].denom_pub.rsa_public_key)) + { + /* signature invalid */ + GNUNET_break (0); + GNUNET_CRYPTO_rsa_signature_free (rs); + return 7; + } + GNUNET_CRYPTO_rsa_signature_free (rs); } - GNUNET_CRYPTO_rsa_signature_free (ds.rsa_signature); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received valid signature for key %s\n", + GNUNET_h2s (&keys[i].h_denom_pub)); success = true; break; -#if FIXME - case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_INVALID: + case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY: + /* This 'failure' is expected, we're testing also for the + error handling! */ if ( (0 == GNUNET_TIME_absolute_get_remaining ( keys[i].start_time).rel_value_us) && @@ -282,7 +324,6 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh) return 6; } break; -#endif default: /* unexpected error */ GNUNET_break (0); @@ -313,12 +354,95 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh) GNUNET_break (0); return 17; } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Signing with invalid key %s failed as desired\n", + GNUNET_h2s (&rnd)); } return 0; } /** + * Benchmark signing logic. + * + * @param dh handle to the helper + * @return 0 on success + */ +static int +perf_signing (struct TALER_CRYPTO_DenominationHelper *dh) +{ + struct TALER_DenominationSignature ds; + enum TALER_ErrorCode ec; + bool success = false; + struct GNUNET_HashCode m_hash; + struct GNUNET_CRYPTO_RsaBlindingKeySecret bks; + struct GNUNET_TIME_Relative duration; + + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + &bks, + sizeof (bks)); + GNUNET_CRYPTO_hash ("Hello", + strlen ("Hello"), + &m_hash); + duration = GNUNET_TIME_UNIT_ZERO; + for (unsigned int j = 0; j<NUM_SIGN_TESTS;) + { + TALER_CRYPTO_helper_poll (dh); + for (unsigned int i = 0; i<MAX_KEYS; i++) + { + if (! keys[i].valid) + continue; + if (GNUNET_TIME_absolute_get_remaining (keys[i].start_time).rel_value_us > + GNUNET_TIME_UNIT_SECONDS.rel_value_us) + continue; + if (GNUNET_TIME_absolute_get_duration (keys[i].start_time).rel_value_us > + keys[i].validity_duration.rel_value_us) + continue; + { + void *buf; + size_t buf_size; + + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_rsa_blind (&m_hash, + &bks, + keys[i].denom_pub.rsa_public_key, + &buf, + &buf_size)); + /* use this key as long as it works */ + while (1) + { + struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get (); + struct GNUNET_TIME_Relative delay; + + ds = TALER_CRYPTO_helper_denom_sign (dh, + &keys[i].h_denom_pub, + buf, + buf_size, + &ec); + if (TALER_EC_NONE != ec) + break; + delay = GNUNET_TIME_absolute_get_duration (start); + duration = GNUNET_TIME_relative_add (duration, + delay); + GNUNET_CRYPTO_rsa_signature_free (ds.rsa_signature); + j++; + if (NUM_SIGN_TESTS == j) + break; + } + GNUNET_free (buf); + } + } /* for i */ + } /* for j */ + fprintf (stderr, + "%u (sequential) signature operations took %s\n", + (unsigned int) NUM_SIGN_TESTS, + GNUNET_STRINGS_relative_time_to_string (duration, + GNUNET_YES)); + return 0; +} + + +/** * Main entry point into the test logic with the helper already running. */ static int @@ -350,7 +474,7 @@ run_test (void) } /* wait for helper to start and give us keys */ fprintf (stderr, "Waiting for helper to start "); - for (unsigned int i = 0; i<80; i++) + for (unsigned int i = 0; i<1000; i++) { TALER_CRYPTO_helper_poll (dh); if (0 != num_keys) @@ -370,15 +494,12 @@ run_test (void) num_keys); ret = 0; -#if 1 if (0 == ret) ret = test_revocation (dh); -#endif -#if 0 if (0 == ret) ret = test_signing (dh); -#endif - + if (0 == ret) + ret = perf_signing (dh); TALER_CRYPTO_helper_denom_disconnect (dh); /* clean up our state */ for (unsigned int i = 0; i<MAX_KEYS; i++) @@ -407,7 +528,7 @@ main (int argc, (void) argc; (void) argv; GNUNET_log_setup ("test-helper-rsa", - "INFO", + "WARNING", NULL); GNUNET_OS_init (TALER_project_data_default ()); libexec_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR); @@ -423,7 +544,7 @@ main (int argc, "-c", "test_helper_rsa.conf", "-L", - "INFO", + "WARNING", NULL); if (NULL == helper) { |