start with testing crypto rsa helper

This commit is contained in:
Christian Grothoff 2020-11-22 18:31:33 +01:00
parent 9b68dbb8e6
commit a9fb94e916
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
7 changed files with 662 additions and 224 deletions

1
src/util/.gitignore vendored
View File

@ -1,3 +1,4 @@
taler-config
test_payto
taler-helper-crypto-rsa
test_helper_rsa

View File

@ -7,7 +7,7 @@ if USE_COVERAGE
endif
libexecdir = $(pkglibdir)/libexec/
libexecdir = $(libdir)/taler/libexec
pkgcfgdir = $(prefix)/share/taler/config.d/
@ -17,7 +17,8 @@ pkgcfg_DATA = \
EXTRA_DIST = \
paths.conf \
taler-config.in
taler-config.in \
test_helper_rsa.conf
libexec_PROGRAMS = \
taler-helper-crypto-rsa
@ -72,9 +73,12 @@ libtalerutil_la_LDFLAGS = \
-export-dynamic -no-undefined
AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
check_PROGRAMS = \
test_amount \
test_crypto \
test_helper_rsa \
test_payto \
test_url
@ -100,6 +104,12 @@ test_payto_LDADD = \
-lgnunetutil \
libtalerutil.la
test_helper_rsa_SOURCES = \
test_helper_rsa.c
test_helper_rsa_LDADD = \
-lgnunetutil \
libtalerutil.la
test_url_SOURCES = \
test_url.c
test_url_LDADD = \

View File

@ -41,6 +41,16 @@ struct TALER_CRYPTO_DenominationHelper
*/
struct sockaddr_un sa;
/**
* Socket address of this process.
*/
struct sockaddr_un my_sa;
/**
* Template for @e my_sa.
*/
char *template;
/**
* The UNIX domain socket, -1 if we are currently not connected.
*/
@ -58,6 +68,10 @@ static void
do_disconnect (struct TALER_CRYPTO_DenominationHelper *dh)
{
GNUNET_break (0 == close (dh->sock));
if (0 != unlink (dh->my_sa.sun_path))
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
"unlink",
dh->my_sa.sun_path);
dh->sock = -1;
}
@ -82,18 +96,73 @@ try_connect (struct TALER_CRYPTO_DenominationHelper *dh)
"socket");
return;
}
if (0 != connect (dh->sock,
(const struct sockaddr *) &dh->sa,
sizeof (dh->sa)))
{
if (EINPROGRESS != dh->sock)
char *tmpdir;
tmpdir = GNUNET_DISK_mktemp (dh->template);
if (NULL == tmpdir)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"connect");
do_disconnect (dh);
return;
}
/* we use >= here because we want the sun_path to always
be 0-terminated */
if (strlen (tmpdir) >= sizeof (dh->sa.sun_path))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"PATHS",
"TALER_RUNTIME_DIR",
"path too long");
GNUNET_free (tmpdir);
do_disconnect (dh);
return;
}
dh->my_sa.sun_family = AF_UNIX;
strncpy (dh->my_sa.sun_path,
tmpdir,
sizeof (dh->sa.sun_path));
if (0 != unlink (tmpdir))
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
"unlink",
tmpdir);
GNUNET_free (tmpdir);
}
if (0 != bind (dh->sock,
(const struct sockaddr *) &dh->my_sa,
sizeof (dh->my_sa)))
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"bind");
do_disconnect (dh);
return;
}
{
struct GNUNET_MessageHeader hdr = {
.size = htons (sizeof (hdr)),
.type = htons (TALER_HELPER_RSA_MT_REQ_INIT)
};
ssize_t ret;
ret = sendto (dh->sock,
&hdr,
sizeof (hdr),
0,
(const struct sockaddr *) &dh->sa,
sizeof (dh->sa));
if (ret < 0)
{
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
"sendto",
dh->sa.sun_path);
do_disconnect (dh);
return;
}
/* We are using SOCK_DGRAM, partial writes should not be possible */
GNUNET_break (((size_t) ret) == sizeof (hdr));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Successfully sent REQ_INIT\n");
}
}
@ -117,7 +186,9 @@ TALER_CRYPTO_helper_denom_connect (
"UNIXPATH");
return NULL;
}
if (strlen (unixpath) > sizeof (dh->sa.sun_path))
/* we use >= here because we want the sun_path to always
be 0-terminated */
if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"taler-helper-crypto-rsa",
@ -129,10 +200,39 @@ TALER_CRYPTO_helper_denom_connect (
dh = GNUNET_new (struct TALER_CRYPTO_DenominationHelper);
dh->dkc = dkc;
dh->dkc_cls = dkc_cls;
dh->sa.sun_family = AF_UNIX;
strncpy (dh->sa.sun_path,
unixpath,
sizeof (dh->sa.sun_path));
dh->sock = -1;
{
char *tmpdir;
char *template;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
"PATHS",
"TALER_RUNTIME_DIR",
&tmpdir))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
"PATHS",
"TALER_RUNTIME_DIR");
tmpdir = GNUNET_strdup ("/tmp");
}
GNUNET_asprintf (&template,
"%s/crypto-rsa-client/XXXXXX",
tmpdir);
GNUNET_free (tmpdir);
if (GNUNET_OK !=
GNUNET_DISK_directory_create_for_file (template))
{
GNUNET_free (dh);
GNUNET_free (template);
return NULL;
}
dh->template = template;
}
TALER_CRYPTO_helper_poll (dh);
return dh;
}
@ -157,6 +257,8 @@ TALER_CRYPTO_helper_poll (struct TALER_CRYPTO_DenominationHelper *dh)
MSG_DONTWAIT);
if (ret < 0)
{
if (EAGAIN == errno)
break;
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"recv");
do_disconnect (dh);
@ -180,10 +282,22 @@ TALER_CRYPTO_helper_poll (struct TALER_CRYPTO_DenominationHelper *dh)
struct TALER_DenominationPublicKey denom_pub;
struct GNUNET_HashCode h_denom_pub;
if ( (sizeof (*kan) < ret) ||
(sizeof (*kan) + ntohs (kan->pub_size) + ntohs (
kan->section_name_len)) ||
('\0' != buf[ret - 1]) )
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);
@ -267,14 +381,16 @@ TALER_CRYPTO_helper_denom_sign (
memcpy (&sr[1],
msg,
msg_size);
ret = send (dh->sock,
buf,
sizeof (buf),
0);
ret = sendto (dh->sock,
buf,
sizeof (buf),
0,
&dh->sa,
sizeof (dh->sa));
if (ret < 0)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"send");
"sendto");
do_disconnect (dh);
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
return ds;
@ -378,14 +494,16 @@ TALER_CRYPTO_helper_denom_revoke (
try_connect (dh);
if (-1 == dh->sock)
return; /* give up */
ret = send (dh->sock,
&rr,
sizeof (rr),
0);
ret = sendto (dh->sock,
&rr,
sizeof (rr),
0,
(const struct sockaddr *) &dh->sa,
sizeof (dh->sa));
if (ret < 0)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"send");
"sendto");
do_disconnect (dh);
return;
}
@ -399,6 +517,7 @@ TALER_CRYPTO_helper_denom_disconnect (
struct TALER_CRYPTO_DenominationHelper *dh)
{
do_disconnect (dh);
GNUNET_free (dh->template);
GNUNET_free (dh);
}

View File

@ -92,7 +92,7 @@ struct DenominationKey
/**
* Hash of this denomination's public key.
*/
struct GNUNET_HashCode h_pub;
struct GNUNET_HashCode h_denom_pub;
/**
* Time at which this key is supposed to become valid.
@ -181,26 +181,14 @@ struct Client
struct Client *prev;
/**
* Work created by this client, NULL for none.
* Client address.
*/
struct WorkItem *work;
struct sockaddr_un addr;
/**
* Client socket.
* Number of bytes used in @e addr.
*/
struct GNUNET_NETWORK_Handle *sock;
/**
* Client task to read from @e sock. NULL if we are working.
*/
struct GNUNET_SCHEDULER_Task *task;
/**
* Flag set to true if this client has disconnected. Used
* by the workers to detect that they must free the client
* instead of returning the result.
*/
bool gone;
socklen_t addr_size;
};
@ -218,11 +206,6 @@ struct WorkItem
*/
struct WorkItem *prev;
/**
* The client that created the request.
*/
struct Client *client;
/**
* Key to be used for this operation.
*/
@ -244,6 +227,16 @@ struct WorkItem
*/
size_t blinded_msg_size;
/**
* Client address.
*/
struct sockaddr_un addr;
/**
* Number of bytes used in @e addr.
*/
socklen_t addr_size;
};
@ -305,7 +298,7 @@ static struct GNUNET_CONTAINER_MultiHashMap *keys;
/**
* Our listen socket.
*/
static struct GNUNET_NETWORK_Handle *lsock;
static struct GNUNET_NETWORK_Handle *unix_sock;
/**
* Path where we are listening.
@ -315,7 +308,7 @@ static char *unixpath;
/**
* Task run to accept new inbound connections.
*/
static struct GNUNET_SCHEDULER_Task *accept_task;
static struct GNUNET_SCHEDULER_Task *read_task;
/**
* Task run to generate new keys.
@ -464,20 +457,10 @@ sign_worker (void *cls)
static void
free_client (struct Client *client)
{
if (NULL != client->task)
{
GNUNET_SCHEDULER_cancel (client->task);
client->task = NULL;
}
GNUNET_NETWORK_socket_close (client->sock);
client->sock = NULL;
GNUNET_CONTAINER_DLL_remove (clients_head,
clients_tail,
client);
if (NULL != client->work)
client->gone = true;
else
GNUNET_free (client);
GNUNET_free (client);
}
@ -490,21 +473,6 @@ static void
read_job (void *cls);
/**
* Start reading requests from the @a client.
*
* @param client client to read requests from.
*/
static void
client_next (struct Client *client)
{
client->task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
client->sock,
&read_job,
client);
}
/**
* Free @a dk. It must already have been removed from #keys and the
* denomination's DLL.
@ -524,25 +492,27 @@ free_dk (struct DenominationKey *dk)
/**
* Send a message starting with @a hdr to @a client.
*
* @param client where to send @a hdr
* @param addr address where to send the message
* @param addr_size number of bytes in @a addr
* @param hdr beginning of the message, length indicated in size field
* @return #GNUNET_OK on success
*/
static int
transmit_to_client (struct Client *client,
const struct GNUNET_MessageHeader *hdr)
transmit (const struct sockaddr_un *addr,
socklen_t addr_size,
const struct GNUNET_MessageHeader *hdr)
{
ssize_t ret;
ret = send (GNUNET_NETWORK_get_fd (client->sock),
hdr,
ntohs (hdr->size),
0);
ret = GNUNET_NETWORK_socket_sendto (unix_sock,
hdr,
ntohs (hdr->size),
(const struct sockaddr *) addr,
addr_size);
if (ret != ntohs (hdr->size))
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"send");
free_client (client);
GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
"sendto");
return GNUNET_SYSERR;
}
return GNUNET_OK;
@ -598,8 +568,9 @@ handle_done (void *cls)
buf,
buf_size);
GNUNET_free (buf);
(void) transmit_to_client (wi->client,
&sr->header);
(void) transmit (&wi->addr,
wi->addr_size,
&sr->header);
GNUNET_free (sr);
}
GNUNET_free (wi);
@ -615,11 +586,13 @@ handle_done (void *cls)
* signature using the respective key and return the result to
* the client.
*
* @param client the client making the request
* @param addr address of the client making the request
* @param addr_size number of bytes in @a addr
* @param sr the request details
*/
static void
handle_sign_request (struct Client *client,
handle_sign_request (const struct sockaddr_un *addr,
socklen_t addr_size,
const struct TALER_CRYPTO_SignRequest *sr)
{
struct DenominationKey *dk;
@ -638,15 +611,17 @@ handle_sign_request (struct Client *client,
};
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Signing request failed, denomination key unknown\n");
transmit_to_client (client,
&sf.header);
client_next (client);
"Signing request failed, denomination key %s unknown\n",
GNUNET_h2s (&sr->h_denom_pub));
(void) transmit (addr,
addr_size,
&sf.header);
return;
}
wi = GNUNET_new (struct WorkItem);
wi->client = client;
wi->addr = *addr;
wi->addr_size = addr_size;
wi->dk = dk;
dk->rc++;
wi->blinded_msg = GNUNET_memdup (blinded_msg,
@ -680,7 +655,6 @@ notify_client_dk_add (struct Client *client,
void *buf;
void *p;
size_t tlen;
int ret;
buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dk->denom_pub.rsa_public_key,
&buf);
@ -703,10 +677,23 @@ notify_client_dk_add (struct Client *client,
memcpy (p + buf_len,
denom->section,
nlen);
ret = transmit_to_client (client,
&an->header);
GNUNET_free (an);
return ret;
{
int ret = GNUNET_OK;
if (GNUNET_OK !=
transmit (&client->addr,
client->addr_size,
&an->header))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Client %s must have disconnected\n",
client->addr.sun_path);
free_client (client);
ret = GNUNET_SYSERR;
}
GNUNET_free (an);
return ret;
}
}
@ -724,11 +711,21 @@ notify_client_dk_del (struct Client *client,
struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
.header.type = htons (TALER_HELPER_RSA_MT_PURGE),
.header.size = htons (sizeof (pn)),
.h_denom_pub = dk->h_pub
.h_denom_pub = dk->h_denom_pub
};
return transmit_to_client (client,
&pn.header);
if (GNUNET_OK !=
transmit (&client->addr,
client->addr_size,
&pn.header))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Client %s must have disconnected\n",
client->addr.sun_path);
free_client (client);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
@ -767,7 +764,7 @@ setup_key (struct DenominationKey *dk,
buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
&buf);
GNUNET_CRYPTO_rsa_public_key_hash (pub,
&dk->h_pub);
&dk->h_denom_pub);
GNUNET_asprintf (&dk->filename,
"%s/%s/%llu",
keydir,
@ -789,13 +786,17 @@ setup_key (struct DenominationKey *dk,
return GNUNET_SYSERR;
}
GNUNET_free (buf);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Setup fresh private key %s in `%s'\n",
GNUNET_h2s (&dk->h_denom_pub),
dk->filename);
dk->denom_priv.rsa_private_key = priv;
dk->denom_pub.rsa_public_key = pub;
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (
keys,
&dk->h_pub,
&dk->h_denom_pub,
dk,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
@ -839,11 +840,13 @@ setup_key (struct DenominationKey *dk,
* Check if the key is still in use, and if so replace (!)
* it with a fresh key.
*
* @param client the client sending the request
* @param addr address of the client making the request
* @param addr_size number of bytes in @a addr
* @param rr the revocation request
*/
static void
handle_revoke_request (struct Client *client,
handle_revoke_request (const struct sockaddr_un *addr,
socklen_t addr_size,
const struct TALER_CRYPTO_RevokeRequest *rr)
{
struct DenominationKey *dk;
@ -854,9 +857,9 @@ handle_revoke_request (struct Client *client,
&rr->h_denom_pub);
if (NULL == dk)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Revocation request ignored, denomination key unknown\n");
client_next (client);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Revocation request ignored, denomination key %s unknown\n",
GNUNET_h2s (&rr->h_denom_pub));
return;
}
@ -886,11 +889,13 @@ handle_revoke_request (struct Client *client,
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_remove (
keys,
&dk->h_pub,
&dk->h_denom_pub,
dk));
GNUNET_CONTAINER_DLL_remove (denom->keys_head,
denom->keys_tail,
dk);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Revocation complete\n");
/* Tell clients this key is gone */
{
@ -910,8 +915,6 @@ handle_revoke_request (struct Client *client,
}
if (0 == dk->rc)
free_dk (dk);
client_next (client);
}
@ -921,129 +924,107 @@ read_job (void *cls)
struct Client *client = cls;
char buf[65536];
ssize_t buf_size;
struct GNUNET_MessageHeader hdr;
const struct GNUNET_MessageHeader *hdr;
struct sockaddr_un addr;
socklen_t addr_size = sizeof (addr);
client->task = NULL;
buf_size = GNUNET_NETWORK_socket_recv (client->sock,
buf,
sizeof (buf));
read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
unix_sock,
&read_job,
NULL);
buf_size = GNUNET_NETWORK_socket_recvfrom (unix_sock,
buf,
sizeof (buf),
(struct sockaddr *) &addr,
&addr_size);
if (-1 == buf_size)
{
if (EAGAIN == errno)
{
client_next (client);
return;
}
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"recv");
free_client (client);
return;
}
if (0 == buf_size)
{
free_client (client);
return;
}
if (buf_size < sizeof (hdr))
if (buf_size < sizeof (struct GNUNET_MessageHeader))
{
GNUNET_break_op (0);
return;
}
hdr = (const struct GNUNET_MessageHeader *) buf;
if (ntohs (hdr->size) != buf_size)
{
GNUNET_break_op (0);
free_client (client);
return;
}
memcpy (&hdr,
buf,
sizeof (hdr));
if (ntohs (hdr.size) != buf_size)
switch (ntohs (hdr->type))
{
GNUNET_break_op (0);
free_client (client);
return;
}
switch (ntohs (hdr.type))
{
case TALER_HELPER_RSA_MT_REQ_SIGN:
if (ntohs (hdr.size) <= sizeof (struct TALER_CRYPTO_SignRequest))
case TALER_HELPER_RSA_MT_REQ_INIT:
if (ntohs (hdr->size) != sizeof (struct GNUNET_MessageHeader))
{
GNUNET_break_op (0);
free_client (client);
return;
}
handle_sign_request (client,
(const struct TALER_CRYPTO_SignRequest *) &hdr);
{
struct Client *client;
client = GNUNET_new (struct Client);
client->addr = addr;
client->addr_size = addr_size;
GNUNET_CONTAINER_DLL_insert (clients_head,
clients_tail,
client);
for (struct Denomination *denom = denom_head;
NULL != denom;
denom = denom->next)
{
for (struct DenominationKey *dk = denom->keys_head;
NULL != dk;
dk = dk->next)
{
if (GNUNET_OK !=
notify_client_dk_add (client,
dk))
{
/* client died, skip the rest */
client = NULL;
break;
}
}
if (NULL == client)
break;
}
}
break;
case TALER_HELPER_RSA_MT_REQ_SIGN:
if (ntohs (hdr->size) <= sizeof (struct TALER_CRYPTO_SignRequest))
{
GNUNET_break_op (0);
return;
}
handle_sign_request (&addr,
addr_size,
(const struct TALER_CRYPTO_SignRequest *) buf);
break;
case TALER_HELPER_RSA_MT_REQ_REVOKE:
if (ntohs (hdr.size) != sizeof (struct TALER_CRYPTO_RevokeRequest))
if (ntohs (hdr->size) != sizeof (struct TALER_CRYPTO_RevokeRequest))
{
GNUNET_break_op (0);
free_client (client);
return;
}
handle_revoke_request (client,
(const struct TALER_CRYPTO_RevokeRequest *) &hdr);
handle_revoke_request (&addr,
addr_size,
(const struct TALER_CRYPTO_RevokeRequest *) buf);
break;
default:
GNUNET_break_op (0);
free_client (client);
return;
}
}
/**
* Function run to accept incoming connections on #sock.
*
* @param cls NULL
*/
static void
accept_job (void *cls)
{
struct GNUNET_NETWORK_Handle *sock;
struct sockaddr_storage addr;
socklen_t alen;
accept_task = NULL;
alen = sizeof (addr);
sock = GNUNET_NETWORK_socket_accept (lsock,
(struct sockaddr *) &addr,
&alen);
if (NULL != sock)
{
struct Client *client;
client = GNUNET_new (struct Client);
client->sock = sock;
GNUNET_CONTAINER_DLL_insert (clients_head,
clients_tail,
client);
client_next (client);
for (struct Denomination *denom = denom_head;
NULL != denom;
denom = denom->next)
{
for (struct DenominationKey *dk = denom->keys_head;
NULL != dk;
dk = dk->next)
{
if (GNUNET_OK !=
notify_client_dk_add (client,
dk))
{
/* client died, skip the rest */
client = NULL;
break;
}
}
if (NULL == client)
break;
}
}
accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
lsock,
&accept_job,
NULL);
}
/**
* Create a new denomination key (we do not have enough).
*
@ -1137,7 +1118,7 @@ purge_key (struct DenominationKey *dk)
dk);
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_remove (keys,
&dk->h_pub,
&dk->h_denom_pub,
dk));
if (0 != unlink (dk->filename))
{
@ -1325,17 +1306,18 @@ parse_key (struct Denomination *denom,
dk->anchor = anchor;
dk->filename = GNUNET_strdup (filename);
GNUNET_CRYPTO_rsa_public_key_hash (pub,
&dk->h_pub);
&dk->h_denom_pub);
dk->denom_pub.rsa_public_key = pub;
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (
keys,
&dk->h_pub,
&dk->h_denom_pub,
dk,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Duplicate private key detected in file `%s'. Skipping.\n",
"Duplicate private key %s detected in file `%s'. Skipping.\n",
GNUNET_h2s (&dk->h_denom_pub),
filename);
GNUNET_CRYPTO_rsa_private_key_free (priv);
GNUNET_CRYPTO_rsa_public_key_free (pub);
@ -1355,8 +1337,9 @@ parse_key (struct Denomination *denom,
denom->keys_tail,
before,
dk);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Imported key from `%s'\n",
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Imported key %s from `%s'\n",
GNUNET_h2s (&dk->h_denom_pub),
filename);
}
}
@ -1566,7 +1549,7 @@ load_denominations (void *cls,
GNUNET_free (denom);
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Loading keys for denomination %s\n",
denom->section);
{
@ -1576,6 +1559,8 @@ load_denominations (void *cls,
"%s/%s",
keydir,
denom->section);
GNUNET_break (GNUNET_OK ==
GNUNET_DISK_directory_create (dname));
GNUNET_DISK_directory_scan (dname,
&import_key,
denom);
@ -1611,17 +1596,16 @@ load_durations (void)
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg,
"exchange",
"taler-helper-crypto-rsa",
"LOOKAHEAD_SIGN",
&lookahead_sign))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"taler-helper-crypto-rsa",
"LOOKAHEAD_SIGN");
return GNUNET_SYSERR;
}
GNUNET_TIME_round_rel (&lookahead_sign);
return GNUNET_OK;
}
@ -1635,16 +1619,16 @@ static void
do_shutdown (void *cls)
{
(void) cls;
if (NULL != accept_task)
if (NULL != read_task)
{
GNUNET_SCHEDULER_cancel (accept_task);
accept_task = NULL;
GNUNET_SCHEDULER_cancel (read_task);
read_task = NULL;
}
if (NULL != lsock)
if (NULL != unix_sock)
{
GNUNET_break (GNUNET_OK ==
GNUNET_NETWORK_socket_close (lsock));
lsock = NULL;
GNUNET_NETWORK_socket_close (unix_sock));
unix_sock = NULL;
}
if (0 != unlink (unixpath))
{
@ -1790,7 +1774,7 @@ run (void *cls,
return;
}
}
lsock = GNUNET_NETWORK_socket_box_native (sock);
unix_sock = GNUNET_NETWORK_socket_box_native (sock);
}
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
@ -1823,10 +1807,10 @@ run (void *cls,
}
/* start job to accept incoming requests on 'sock' */
accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
lsock,
&accept_job,
NULL);
read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
unix_sock,
&read_job,
NULL);
/* start job to keep keys up-to-date */
keygen_task = GNUNET_SCHEDULER_add_now (&update_denominations,
@ -1893,7 +1877,7 @@ main (int argc,
/* force linker to link against libtalerutil; if we do
not do this, the linker may "optimize" libtalerutil
away and skip #TALER_OS_init(), which we do need */
(void) TALER_project_data_default ();
GNUNET_OS_init (TALER_project_data_default ());
GNUNET_assert (GNUNET_OK ==
GNUNET_log_setup ("taler-helper-crypto-rsa",
"WARNING",

View File

@ -24,11 +24,12 @@
#define TALER_HELPER_RSA_MT_PURGE 1
#define TALER_HELPER_RSA_MT_AVAIL 2
#define TALER_HELPER_RSA_MT_REQ_SIGN 3
#define TALER_HELPER_RSA_MT_REQ_REVOKE 4
#define TALER_HELPER_RSA_MT_REQ_INIT 4
#define TALER_HELPER_RSA_MT_REQ_SIGN 5
#define TALER_HELPER_RSA_MT_REQ_REVOKE 6
#define TALER_HELPER_RSA_MT_RES_SIGNATURE 5
#define TALER_HELPER_RSA_MT_RES_SIGN_FAILURE 6
#define TALER_HELPER_RSA_MT_RES_SIGNATURE 7
#define TALER_HELPER_RSA_MT_RES_SIGN_FAILURE 8
GNUNET_NETWORK_STRUCT_BEGIN

314
src/util/test_helper_rsa.c Normal file
View File

@ -0,0 +1,314 @@
/*
This file is part of TALER
(C) 2020 Taler Systems SA
TALER 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.
TALER 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.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file util/test_helper_rsa.c
* @brief Tests for RSA crypto helper
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_util.h"
/**
* Configuration has 1 minute duration and 5 minutes lookahead, so
* we should never have more than 6 active keys, plus for during
* key expiration / revocation.
*/
#define MAX_KEYS 7
/**
* How many random key revocations should we test?
*/
#define NUM_REVOKES 10
/**
* Number of keys currently in #keys.
*/
static unsigned int num_keys;
/**
* Keys currently managed by the helper.
*/
struct KeyData
{
/**
* Validity start point.
*/
struct GNUNET_TIME_Absolute start_time;
/**
* Key expires for signing at @e start_time plus this value.
*/
struct GNUNET_TIME_Relative validity_duration;
/**
* Hash of the public key.
*/
struct GNUNET_HashCode h_denom_pub;
/**
* Full public key.
*/
struct TALER_DenominationPublicKey denom_pub;
/**
* Is this key currently valid?
*/
bool valid;
/**
* Did the test driver revoke this key?
*/
bool revoked;
};
static struct KeyData keys[MAX_KEYS];
static void
key_cb (void *cls,
const char *section_name,
struct GNUNET_TIME_Absolute start_time,
struct GNUNET_TIME_Relative validity_duration,
const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_DenominationPublicKey *denom_pub)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Key notification about key %s in `%s'\n",
GNUNET_h2s (h_denom_pub),
section_name);
if (0 == validity_duration.rel_value_us)
{
bool found = false;
GNUNET_break (NULL == denom_pub);
GNUNET_break (NULL == section_name);
for (unsigned int i = 0; i<MAX_KEYS; i++)
if (0 == GNUNET_memcmp (h_denom_pub,
&keys[i].h_denom_pub))
{
keys[i].valid = false;
keys[i].revoked = false;
GNUNET_CRYPTO_rsa_public_key_free (keys[i].denom_pub.rsa_public_key);
keys[i].denom_pub.rsa_public_key = NULL;
GNUNET_assert (num_keys > 0);
num_keys--;
found = true;
break;
}
if (! found)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error: helper announced expiration of unknown key!\n");
return;
}
GNUNET_break (NULL != denom_pub);
for (unsigned int i = 0; i<MAX_KEYS; i++)
if (! keys[i].valid)
{
keys[i].valid = true;
keys[i].h_denom_pub = *h_denom_pub;
keys[i].start_time = start_time;
keys[i].validity_duration = validity_duration;
keys[i].denom_pub.rsa_public_key
= GNUNET_CRYPTO_rsa_public_key_dup (denom_pub->rsa_public_key);
num_keys++;
return;
}
/* too many keys! */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Error: received %d live keys from the service!\n",
MAX_KEYS + 1);
}
/**
* Main entry point into the test logic with the helper already running.
*/
static int
run_test (void)
{
struct GNUNET_CONFIGURATION_Handle *cfg;
struct TALER_CRYPTO_DenominationHelper *dh;
struct timespec req = {
.tv_nsec = 250000000
};
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK !=
GNUNET_CONFIGURATION_load (cfg,
"test_helper_rsa.conf"))
{
GNUNET_break (0);
return 77;
}
dh = TALER_CRYPTO_helper_denom_connect (cfg,
&key_cb,
NULL);
GNUNET_CONFIGURATION_destroy (cfg);
if (NULL == dh)
{
GNUNET_break (0);
return 1;
}
/* wait for helper to start and give us keys */
fprintf (stderr, "Waiting for helper to start ");
for (unsigned int i = 0; i<80; i++)
{
TALER_CRYPTO_helper_poll (dh);
if (0 != num_keys)
break;
nanosleep (&req, NULL);
fprintf (stderr, ".");
}
if (0 == num_keys)
{
fprintf (stderr,
"\nFAILED: timeout trying to connect to helper\n");
TALER_CRYPTO_helper_denom_disconnect (dh);
return 1;
}
fprintf (stderr,
"\nOK: Helper ready (%u keys)\n",
num_keys);
for (unsigned int i = 0; i<NUM_REVOKES; i++)
{
uint32_t off;
off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
num_keys);
/* find index of key to revoke */
for (unsigned int j = 0; j < MAX_KEYS; j++)
{
if (! keys[j].valid)
continue;
if (0 != off)
{
off--;
continue;
}
keys[j].revoked = true;
fprintf (stderr,
"Revoking key %s ...",
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++)
{
TALER_CRYPTO_helper_poll (dh);
if (! keys[j].revoked)
break;
nanosleep (&req, NULL);
fprintf (stderr, ".");
}
if (keys[j].revoked)
{
fprintf (stderr,
"\nFAILED: timeout trying to revoke key %u\n",
j);
TALER_CRYPTO_helper_denom_disconnect (dh);
return 2;
}
break;
}
}
TALER_CRYPTO_helper_denom_disconnect (dh);
/* clean up our state */
for (unsigned int i = 0; i<MAX_KEYS; i++)
if (keys[i].valid)
{
GNUNET_CRYPTO_rsa_public_key_free (keys[i].denom_pub.rsa_public_key);
keys[i].denom_pub.rsa_public_key = NULL;
GNUNET_assert (num_keys > 0);
num_keys--;
}
return 0;
}
int
main (int argc,
const char *const argv[])
{
struct GNUNET_OS_Process *helper;
char *libexec_dir;
char *binary_name;
int ret;
enum GNUNET_OS_ProcessStatusType type;
unsigned long code;
(void) argc;
(void) argv;
GNUNET_log_setup ("test-helper-rsa",
"INFO",
NULL);
GNUNET_OS_init (TALER_project_data_default ());
libexec_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR);
GNUNET_asprintf (&binary_name,
"%s/%s",
libexec_dir,
"taler-helper-crypto-rsa");
GNUNET_free (libexec_dir);
helper = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR,
NULL, NULL, NULL,
binary_name,
binary_name,
"-c",
"test_helper_rsa.conf",
"-L",
"INFO",
NULL);
if (NULL == helper)
{
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
"exec",
binary_name);
GNUNET_free (binary_name);
return 77;
}
GNUNET_free (binary_name);
ret = run_test ();
GNUNET_OS_process_kill (helper,
SIGTERM);
if (GNUNET_OK !=
GNUNET_OS_process_wait_status (helper,
&type,
&code))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Helper process did not die voluntarily, killing hard\n");
GNUNET_OS_process_kill (helper,
SIGKILL);
ret = 4;
}
else if ( (GNUNET_OS_PROCESS_EXITED != type) ||
(0 != code) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Helper died with unexpected status %d/%d\n",
(int) type,
(int) code);
ret = 5;
}
GNUNET_OS_process_destroy (helper);
return ret;
}
/* end of test_helper_rsa.c */

View File

@ -0,0 +1,9 @@
[coin_1]
duration_withdraw = 1 minute
rsa_keysize = 2048
[taler-helper-crypto-rsa]
lookahead_sign = 5 minutes
overlap_duration = 1 s
KEY_DIR = ${TALER_RUNTIME_DIR}/test_helper_rsa/
UNIXPATH = ${TALER_RUNTIME_DIR}test_helper_rsa.unix