This file is part of GNUnet
Copyright (C) 2014,2016 GNUnet e.V.
- GNUnet is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
- You should have received a copy of the GNU General Public License along with
- GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
#include "platform.h"
#include <gcrypt.h>
#include "gnunet_crypto_lib.h"
+#include "benchmark.h"
-#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-rsa", __VA_ARGS__)
/**
gcry_sexp_t list;
gcry_sexp_t l2;
const char *s;
- unsigned int i;
unsigned int idx;
if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
{
if (! (l2 = gcry_sexp_find_token (list, s, 1)))
{
- for (i = 0; i < idx; i++)
+ for (unsigned int i = 0; i < idx; i++)
{
gcry_free (array[i]);
array[i] = NULL;
gcry_sexp_release (l2);
if (! array[idx])
{
- for (i = 0; i < idx; i++)
+ for (unsigned int i = 0; i < idx; i++)
{
gcry_free (array[i]);
array[i] = NULL;
gcry_sexp_t s_key;
gcry_sexp_t s_keyparam;
+ BENCHMARK_START (rsa_private_key_create);
+
GNUNET_assert (0 ==
gcry_sexp_build (&s_keyparam,
NULL,
#endif
ret = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
ret->sexp = s_key;
+ BENCHMARK_END (rsa_private_key_create);
return ret;
}
int rc;
gcry_sexp_t result;
+ BENCHMARK_START (rsa_private_key_get_public);
+
rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
if (0 != rc)
rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
gcry_mpi_release (ne[1]);
pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
pub->sexp = result;
+ BENCHMARK_END (rsa_private_key_get_public);
return pub;
}
char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
struct RsaBlindingKey *blind;
gcry_mpi_t n;
-
+
blind = GNUNET_new (struct RsaBlindingKey);
GNUNET_assert( NULL != blind );
}
-/*
+/*
We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
previous routine.
-There was previously a call to GNUNET_CRYPTO_kdf in
+There was previously a call to GNUNET_CRYPTO_kdf in
bkey = rsa_blinding_key_derive (len, bks);
-that gives exactly len bits where
+that gives exactly len bits where
len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
-pkey.n making the effective bkey be
+pkey.n making the effective bkey be
bkey mod pkey.n = bkey - pkey.n
so the effective bkey has its high bit set with probability r/2.
We expect r to be close to 1/2 if the exchange is honest, but the
exchange can choose r otherwise.
-In blind signing, the exchange sees
+In blind signing, the exchange sees
B = bkey * S mod pkey.n
On deposit, the exchange sees S so they can compute bkey' = B/S mod
pkey.n for all B they recorded to see if bkey' has it's high bit set.
I feared this gives the exchange a meaningful fraction of a bit of
information per coin involved in the transaction. It sounds damaging if
numerous coins were involved. And it could run across transactions in
-some scenarios.
+some scenarios.
We fixed this by using a more uniform deterministic pseudo-random number
generator for blinding factors. I do not believe this to be a problem
* @param pkey the public key of the signer
* @param[out] buf set to a buffer with the blinded message to be signed
* @param[out] buf_size number of bytes stored in @a buf
- * @return GNUNET_YES if successful, GNUNET_NO if RSA key is malicious
+ * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
*/
int
GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
gcry_mpi_t data_r_e;
int ret;
+ BENCHMARK_START (rsa_blind);
+
GNUNET_assert (buf != NULL && buf_size != NULL);
ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
if (0 != ret)
}
data = rsa_full_domain_hash (pkey, hash);
- if (NULL == data)
+ if (NULL == data)
goto rsa_gcd_validate_failure;
bkey = rsa_blinding_key_derive (pkey, bks);
gcry_mpi_release (ne[0]);
gcry_mpi_release (ne[1]);
gcry_mpi_release (r_e);
- rsa_blinding_key_free (bkey);
+ rsa_blinding_key_free (bkey);
*buf_size = numeric_mpi_alloc_n_print (data_r_e, buf);
gcry_mpi_release (data_r_e);
+
+ BENCHMARK_END (rsa_blind);
+
return GNUNET_YES;
rsa_gcd_validate_failure:
gcry_mpi_t v = NULL;
struct GNUNET_CRYPTO_RsaSignature *sig;
+ BENCHMARK_START (rsa_sign_blinded);
+
GNUNET_assert (0 ==
gcry_mpi_scan (&v,
GCRYMPI_FMT_USG,
sig = rsa_sign_mpi (key, v);
gcry_mpi_release (v);
+ BENCHMARK_END (rsa_sign_blinded);
return sig;
}
GNUNET_CRYPTO_rsa_public_key_free (pkey);
if (NULL == v) /* rsa_gcd_validate failed meaning */
return NULL; /* our *own* RSA key is malicious. */
-
+
sig = rsa_sign_mpi (key, v);
gcry_mpi_release (v);
return sig;
* @return unblinded signature on success, NULL if RSA key is bad or malicious.
*/
struct GNUNET_CRYPTO_RsaSignature *
-GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_RsaSignature *sig,
+GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,
const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
struct GNUNET_CRYPTO_RsaPublicKey *pkey)
{
int ret;
struct GNUNET_CRYPTO_RsaSignature *sret;
+ BENCHMARK_START (rsa_unblind);
+
ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
if (0 != ret)
ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
}
bkey = rsa_blinding_key_derive (pkey, bks);
- if (NULL == bkey)
+ if (NULL == bkey)
{
- /* RSA key is malicious since rsa_gcd_validate failed here.
+ /* RSA key is malicious since rsa_gcd_validate failed here.
* It should have failed during GNUNET_CRYPTO_rsa_blind too though,
- * so the exchange is being malicious in an unfamilair way, maybe
+ * so the exchange is being malicious in an unfamilair way, maybe
* just trying to crash us. */
GNUNET_break_op (0);
gcry_mpi_release (n);
n))
{
/* We cannot find r mod n, so gcd(r,n) != 1, which should get *
- * caught above, but we handle it the same here. */
+ * caught above, but we handle it the same here. */
GNUNET_break_op (0);
gcry_mpi_release (r_inv);
- rsa_blinding_key_free (bkey);
+ rsa_blinding_key_free (bkey);
gcry_mpi_release (n);
gcry_mpi_release (s);
return NULL;
"(sig-val (rsa (s %M)))",
ubsig));
gcry_mpi_release (ubsig);
+ BENCHMARK_END (rsa_unblind);
return sret;
}
gcry_mpi_t r;
int rc;
+ BENCHMARK_START (rsa_verify);
+
r = rsa_full_domain_hash (pkey, hash);
if (NULL == r) {
GNUNET_break_op (0);
- /* RSA key is malicious since rsa_gcd_validate failed here.
+ /* RSA key is malicious since rsa_gcd_validate failed here.
* It should have failed during GNUNET_CRYPTO_rsa_blind too though,
- * so the exchange is being malicious in an unfamilair way, maybe
+ * so the exchange is being malicious in an unfamilair way, maybe
* just trying to crash us. Arguably, we've only an internal error
- * though because we should've detected this in our previous call
+ * though because we should've detected this in our previous call
* to GNUNET_CRYPTO_rsa_unblind. */
return GNUNET_NO;
}
__LINE__,
gcry_strerror (rc));
return GNUNET_SYSERR;
+ BENCHMARK_END (rsa_verify);
}
+ BENCHMARK_END (rsa_verify);
return GNUNET_OK;
}