diff options
Diffstat (limited to 'src/util/crypto_helper_rsa.c')
-rw-r--r-- | src/util/crypto_helper_rsa.c | 313 |
1 files changed, 290 insertions, 23 deletions
diff --git a/src/util/crypto_helper_rsa.c b/src/util/crypto_helper_rsa.c index 92b79c951..e23e12a88 100644 --- a/src/util/crypto_helper_rsa.c +++ b/src/util/crypto_helper_rsa.c @@ -113,21 +113,28 @@ try_connect (struct TALER_CRYPTO_RsaDenominationHelper *dh) struct TALER_CRYPTO_RsaDenominationHelper * TALER_CRYPTO_helper_rsa_connect ( const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, TALER_CRYPTO_RsaDenominationKeyStatusCallback dkc, void *dkc_cls) { struct TALER_CRYPTO_RsaDenominationHelper *dh; char *unixpath; + char *secname; + + GNUNET_asprintf (&secname, + "%s-secmod-rsa", + section); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, - "taler-exchange-secmod-rsa", + secname, "UNIXPATH", &unixpath)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "taler-exchange-secmod-rsa", + secname, "UNIXPATH"); + GNUNET_free (secname); return NULL; } /* we use >= here because we want the sun_path to always @@ -135,12 +142,14 @@ TALER_CRYPTO_helper_rsa_connect ( if (strlen (unixpath) >= sizeof (dh->sa.sun_path)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "taler-exchange-secmod-rsa", + secname, "UNIXPATH", "path too long"); GNUNET_free (unixpath); + GNUNET_free (secname); return NULL; } + GNUNET_free (secname); dh = GNUNET_new (struct TALER_CRYPTO_RsaDenominationHelper); dh->dkc = dkc; dh->dkc_cls = dkc_cls; @@ -203,23 +212,27 @@ handle_mt_avail (struct TALER_CRYPTO_RsaDenominationHelper *dh, } { - struct TALER_DenominationPublicKey denom_pub; + struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub; struct TALER_RsaPubHashP h_rsa; - denom_pub.cipher = TALER_DENOMINATION_RSA; - denom_pub.details.rsa_public_key + bs_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); + bs_pub->cipher = GNUNET_CRYPTO_BSA_RSA; + bs_pub->details.rsa_public_key = GNUNET_CRYPTO_rsa_public_key_decode (buf, ntohs (kan->pub_size)); - if (NULL == denom_pub.details.rsa_public_key) + if (NULL == bs_pub->details.rsa_public_key) { GNUNET_break_op (0); + GNUNET_free (bs_pub); return GNUNET_SYSERR; } - GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.details.rsa_public_key, - &h_rsa.hash); + bs_pub->rc = 1; + GNUNET_CRYPTO_rsa_public_key_hash (bs_pub->details.rsa_public_key, + &bs_pub->pub_key_hash); + h_rsa.hash = bs_pub->pub_key_hash; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received RSA key %s (%s)\n", - GNUNET_h2s (&h_rsa.hash), + GNUNET_h2s (&bs_pub->pub_key_hash), section_name); if (GNUNET_OK != TALER_exchange_secmod_rsa_verify ( @@ -231,7 +244,7 @@ handle_mt_avail (struct TALER_CRYPTO_RsaDenominationHelper *dh, &kan->secm_sig)) { GNUNET_break_op (0); - TALER_denom_pub_free (&denom_pub); + GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub); return GNUNET_SYSERR; } dh->dkc (dh->dkc_cls, @@ -239,10 +252,10 @@ handle_mt_avail (struct TALER_CRYPTO_RsaDenominationHelper *dh, GNUNET_TIME_timestamp_ntoh (kan->anchor_time), GNUNET_TIME_relative_ntoh (kan->duration_withdraw), &h_rsa, - &denom_pub, + bs_pub, &kan->secm_pub, &kan->secm_sig); - TALER_denom_pub_free (&denom_pub); + GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub); } return GNUNET_OK; } @@ -395,7 +408,9 @@ TALER_CRYPTO_helper_rsa_sign ( { enum TALER_ErrorCode ec = TALER_EC_INVALID; - bs->cipher = TALER_DENOMINATION_INVALID; + memset (bs, + 0, + sizeof (*bs)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting signature process\n"); if (GNUNET_OK != @@ -417,9 +432,9 @@ TALER_CRYPTO_helper_rsa_sign ( sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN); sr->reserved = htonl (0); sr->h_rsa = *rsr->h_rsa; - memcpy (&sr[1], - rsr->msg, - rsr->msg_size); + GNUNET_memcpy (&sr[1], + rsr->msg, + rsr->msg_size); if (GNUNET_OK != TALER_crypto_helper_send_all (dh->sock, buf, @@ -503,6 +518,7 @@ more: const struct TALER_CRYPTO_SignResponse *sr = (const struct TALER_CRYPTO_SignResponse *) buf; struct GNUNET_CRYPTO_RsaSignature *rsa_signature; + struct GNUNET_CRYPTO_BlindedSignature *blind_sig; rsa_signature = GNUNET_CRYPTO_rsa_signature_decode ( &sr[1], @@ -518,8 +534,11 @@ more: "Received signature\n"); ec = TALER_EC_NONE; finished = true; - bs->cipher = TALER_DENOMINATION_RSA; - bs->details.blinded_rsa_signature = rsa_signature; + blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature); + blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA; + blind_sig->rc = 1; + blind_sig->details.blinded_rsa_signature = rsa_signature; + bs->blinded_sig = blind_sig; break; } case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE: @@ -597,12 +616,260 @@ end: enum TALER_ErrorCode TALER_CRYPTO_helper_rsa_batch_sign ( struct TALER_CRYPTO_RsaDenominationHelper *dh, - const struct TALER_CRYPTO_RsaSignRequest *rsrs, unsigned int rsrs_length, - struct TALER_BlindedDenominationSignature *bss) + const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length], + struct TALER_BlindedDenominationSignature bss[static rsrs_length]) { - GNUNET_break (0); - return -1; /* FIXME #7272: NOT IMPLEMENTED! */ + enum TALER_ErrorCode ec = TALER_EC_INVALID; + unsigned int rpos; + unsigned int rend; + unsigned int wpos; + + memset (bss, + 0, + sizeof (*bss) * rsrs_length); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting signature process\n"); + if (GNUNET_OK != + try_connect (dh)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to connect to helper\n"); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Requesting %u signatures\n", + rsrs_length); + rpos = 0; + rend = 0; + wpos = 0; + while (rpos < rsrs_length) + { + unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest); + + while ( (rend < rsrs_length) && + (mlen + + sizeof (struct TALER_CRYPTO_SignRequest) + + rsrs[rend].msg_size < UINT16_MAX) ) + { + mlen += sizeof (struct TALER_CRYPTO_SignRequest) + rsrs[rend].msg_size; + rend++; + } + { + char obuf[mlen] GNUNET_ALIGN; + struct TALER_CRYPTO_BatchSignRequest *bsr + = (struct TALER_CRYPTO_BatchSignRequest *) obuf; + void *wbuf; + + bsr->header.type = htons (TALER_HELPER_RSA_MT_REQ_BATCH_SIGN); + bsr->header.size = htons (mlen); + bsr->batch_size = htonl (rend - rpos); + wbuf = &bsr[1]; + for (unsigned int i = rpos; i<rend; i++) + { + struct TALER_CRYPTO_SignRequest *sr = wbuf; + const struct TALER_CRYPTO_RsaSignRequest *rsr = &rsrs[i]; + + sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN); + sr->header.size = htons (sizeof (*sr) + rsr->msg_size); + sr->reserved = htonl (0); + sr->h_rsa = *rsr->h_rsa; + GNUNET_memcpy (&sr[1], + rsr->msg, + rsr->msg_size); + wbuf += sizeof (*sr) + rsr->msg_size; + } + GNUNET_assert (wbuf == &obuf[mlen]); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending batch request [%u-%u)\n", + rpos, + rend); + if (GNUNET_OK != + TALER_crypto_helper_send_all (dh->sock, + obuf, + sizeof (obuf))) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "send"); + do_disconnect (dh); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; + } + } + rpos = rend; + { + char buf[UINT16_MAX]; + size_t off = 0; + const struct GNUNET_MessageHeader *hdr + = (const struct GNUNET_MessageHeader *) buf; + bool finished = false; + + while (1) + { + uint16_t msize; + ssize_t ret; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Awaiting reply at %u (up to %u)\n", + wpos, + rend); + 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); + break; + } + 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; + if (TALER_EC_NONE == ec) + break; + return ec; + } + 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_RSA_MT_RES_SIGNATURE: + if (msize < sizeof (struct TALER_CRYPTO_SignResponse)) + { + GNUNET_break_op (0); + do_disconnect (dh); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + } + if (finished) + { + GNUNET_break_op (0); + do_disconnect (dh); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + } + { + const struct TALER_CRYPTO_SignResponse *sr = + (const struct TALER_CRYPTO_SignResponse *) buf; + struct GNUNET_CRYPTO_RsaSignature *rsa_signature; + struct GNUNET_CRYPTO_BlindedSignature *blind_sig; + + rsa_signature = GNUNET_CRYPTO_rsa_signature_decode ( + &sr[1], + msize - sizeof (*sr)); + if (NULL == rsa_signature) + { + GNUNET_break_op (0); + do_disconnect (dh); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received %u signature\n", + wpos); + blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature); + blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA; + blind_sig->rc = 1; + blind_sig->details.blinded_rsa_signature = rsa_signature; + bss[wpos].blinded_sig = blind_sig; + wpos++; + if (wpos == rend) + { + if (TALER_EC_INVALID == ec) + ec = TALER_EC_NONE; + finished = true; + } + break; + } + case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE: + if (msize != sizeof (struct TALER_CRYPTO_SignFailure)) + { + GNUNET_break_op (0); + do_disconnect (dh); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + } + { + const struct TALER_CRYPTO_SignFailure *sf = + (const struct TALER_CRYPTO_SignFailure *) buf; + + ec = (enum TALER_ErrorCode) ntohl (sf->ec); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Signing %u failed with status %d!\n", + wpos, + ec); + wpos++; + if (wpos == rend) + { + finished = true; + } + break; + } + case TALER_HELPER_RSA_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); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + } + break; /* while(1) loop ensures we recvfrom() again */ + case TALER_HELPER_RSA_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); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + } + break; /* while(1) loop ensures we recvfrom() again */ + case TALER_HELPER_RSA_SYNCED: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Synchronized add odd time with RSA 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); + return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG; + } + memmove (buf, + &buf[msize], + off - msize); + off -= msize; + goto more; + } /* while(1) */ + } /* scope */ + } /* while (rpos < rsrs_length) */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Existing with %u signatures and status %d\n", + wpos, + ec); + return ec; } |