aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/.gitignore1
-rw-r--r--src/util/Makefile.am13
-rw-r--r--src/util/age_restriction.c3
-rw-r--r--src/util/amount.c27
-rw-r--r--src/util/conversion.c402
-rw-r--r--src/util/crypto_confirmation.c8
-rw-r--r--src/util/crypto_contract.c42
-rw-r--r--src/util/crypto_helper_esign.c6
-rw-r--r--src/util/crypto_helper_rsa.c12
-rw-r--r--src/util/exchange_signatures.c16
-rw-r--r--src/util/iban.c6
-rw-r--r--src/util/offline_signatures.c86
-rw-r--r--src/util/payto.c6
-rw-r--r--src/util/taler-exchange-secmod-cs.c24
-rw-r--r--src/util/taler-exchange-secmod-eddsa.c6
-rw-r--r--src/util/taler-exchange-secmod-rsa.c36
-rw-r--r--src/util/test_conversion.c149
-rwxr-xr-xsrc/util/test_conversion.sh5
-rw-r--r--src/util/test_crypto.c25
-rw-r--r--src/util/util.c169
20 files changed, 935 insertions, 107 deletions
diff --git a/src/util/.gitignore b/src/util/.gitignore
index c5f8c76dd..d79786ec7 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -9,3 +9,4 @@ test_helper_cs
test_helper_cs_home/
test_helper_eddsa
test_helper_eddsa_home/
+test_conversion
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 115ea5055..9d1ec9d42 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -20,7 +20,8 @@ EXTRA_DIST = \
taler-config.in \
test_helper_eddsa.conf \
test_helper_rsa.conf \
- test_helper_cs.conf
+ test_helper_cs.conf \
+ test_conversion.sh
bin_PROGRAMS = \
taler-exchange-secmod-eddsa \
@@ -80,6 +81,7 @@ libtalerutil_la_SOURCES = \
aml_signatures.c \
auditor_signatures.c \
config.c \
+ conversion.c \
crypto.c \
crypto_confirmation.c \
crypto_contract.c \
@@ -125,6 +127,7 @@ AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=
check_PROGRAMS = \
test_age_restriction \
test_amount \
+ test_conversion \
test_crypto \
test_helper_eddsa \
test_helper_rsa \
@@ -141,6 +144,14 @@ test_age_restriction_LDADD = \
-lgnunetutil \
libtalerutil.la
+test_conversion_SOURCES = \
+ test_conversion.c
+test_conversion_LDADD = \
+ -lgnunetjson \
+ -lgnunetutil \
+ -ljansson \
+ libtalerutil.la
+
test_amount_SOURCES = \
test_amount.c
test_amount_LDADD = \
diff --git a/src/util/age_restriction.c b/src/util/age_restriction.c
index beb68e5a6..cf81d915b 100644
--- a/src/util/age_restriction.c
+++ b/src/util/age_restriction.c
@@ -513,6 +513,9 @@ TALER_parse_age_group_string (
unsigned int val = 0;
char c;
+ /* reset mask */
+ mask->bits = 0;
+
while (*pos)
{
c = *pos++;
diff --git a/src/util/amount.c b/src/util/amount.c
index d5698e8b6..9cd0739c9 100644
--- a/src/util/amount.c
+++ b/src/util/amount.c
@@ -72,9 +72,8 @@ TALER_string_to_amount (const char *str,
}
GNUNET_assert (TALER_CURRENCY_LEN > (colon - str));
- memcpy (amount->currency,
- str,
- colon - str);
+ for (unsigned int i = 0; i<colon - str; i++)
+ amount->currency[i] = toupper (str[i]);
/* 0-terminate *and* normalize buffer by setting everything to '\0' */
memset (&amount->currency [colon - str],
0,
@@ -193,9 +192,8 @@ TALER_amount_hton (struct TALER_AmountNBO *res,
TALER_amount_is_valid (d));
res->value = GNUNET_htonll (d->value);
res->fraction = htonl (d->fraction);
- memcpy (res->currency,
- d->currency,
- TALER_CURRENCY_LEN);
+ for (unsigned int i = 0; i<TALER_CURRENCY_LEN; i++)
+ res->currency[i] = toupper (d->currency[i]);
}
@@ -205,9 +203,9 @@ TALER_amount_ntoh (struct TALER_Amount *res,
{
res->value = GNUNET_ntohll (dn->value);
res->fraction = ntohl (dn->fraction);
- memcpy (res->currency,
- dn->currency,
- TALER_CURRENCY_LEN);
+ GNUNET_memcpy (res->currency,
+ dn->currency,
+ TALER_CURRENCY_LEN);
GNUNET_assert (GNUNET_YES ==
TALER_amount_is_valid (res));
}
@@ -225,9 +223,8 @@ TALER_amount_set_zero (const char *cur,
memset (amount,
0,
sizeof (struct TALER_Amount));
- memcpy (amount->currency,
- cur,
- slen);
+ for (unsigned int i = 0; i<slen; i++)
+ amount->currency[i] = toupper (cur[i]);
return GNUNET_OK;
}
@@ -680,9 +677,9 @@ TALER_amount_multiply (struct TALER_Amount *result,
if (GNUNET_SYSERR ==
TALER_amount_normalize (&in))
return TALER_AAR_INVALID_NORMALIZATION_FAILED;
- memcpy (result->currency,
- amount->currency,
- TALER_CURRENCY_LEN);
+ GNUNET_memcpy (result->currency,
+ amount->currency,
+ TALER_CURRENCY_LEN);
if ( (0 == factor) ||
( (0 == in.value) &&
(0 == in.fraction) ) )
diff --git a/src/util/conversion.c b/src/util/conversion.c
new file mode 100644
index 000000000..501ca0145
--- /dev/null
+++ b/src/util/conversion.c
@@ -0,0 +1,402 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023 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 conversion.c
+ * @brief helper routines to run some external JSON-to-JSON converter
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include <gnunet/gnunet_util_lib.h>
+
+
+struct TALER_JSON_ExternalConversion
+{
+ /**
+ * Callback to call with the result.
+ */
+ TALER_JSON_JsonCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Handle to the helper process.
+ */
+ struct GNUNET_OS_Process *helper;
+
+ /**
+ * Pipe for the stdin of the @e helper.
+ */
+ struct GNUNET_DISK_FileHandle *chld_stdin;
+
+ /**
+ * Pipe for the stdout of the @e helper.
+ */
+ struct GNUNET_DISK_FileHandle *chld_stdout;
+
+ /**
+ * Handle to wait on the child to terminate.
+ */
+ struct GNUNET_ChildWaitHandle *cwh;
+
+ /**
+ * Task to read JSON output from the child.
+ */
+ struct GNUNET_SCHEDULER_Task *read_task;
+
+ /**
+ * Task to send JSON input to the child.
+ */
+ struct GNUNET_SCHEDULER_Task *write_task;
+
+ /**
+ * Buffer with data we need to send to the helper.
+ */
+ void *write_buf;
+
+ /**
+ * Buffer for reading data from the helper.
+ */
+ void *read_buf;
+
+ /**
+ * Total length of @e write_buf.
+ */
+ size_t write_size;
+
+ /**
+ * Current write position in @e write_buf.
+ */
+ size_t write_pos;
+
+ /**
+ * Current size of @a read_buf.
+ */
+ size_t read_size;
+
+ /**
+ * Current offset in @a read_buf.
+ */
+ size_t read_pos;
+
+};
+
+
+/**
+ * Function called when we can read more data from
+ * the child process.
+ *
+ * @param cls our `struct TALER_JSON_ExternalConversion *`
+ */
+static void
+read_cb (void *cls)
+{
+ struct TALER_JSON_ExternalConversion *ec = cls;
+
+ ec->read_task = NULL;
+ while (1)
+ {
+ ssize_t ret;
+
+ if (ec->read_size == ec->read_pos)
+ {
+ /* Grow input buffer */
+ size_t ns;
+ void *tmp;
+
+ ns = GNUNET_MAX (2 * ec->read_size,
+ 1024);
+ if (ns > GNUNET_MAX_MALLOC_CHECKED)
+ ns = GNUNET_MAX_MALLOC_CHECKED;
+ if (ec->read_size == ns)
+ {
+ /* Helper returned more than 40 MB of data! Stop reading! */
+ GNUNET_break (0);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_close (ec->chld_stdin));
+ return;
+ }
+ tmp = GNUNET_malloc_large (ns);
+ if (NULL == tmp)
+ {
+ /* out of memory, also stop reading */
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "malloc");
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_close (ec->chld_stdin));
+ return;
+ }
+ GNUNET_memcpy (tmp,
+ ec->read_buf,
+ ec->read_pos);
+ GNUNET_free (ec->read_buf);
+ ec->read_buf = tmp;
+ ec->read_size = ns;
+ }
+ ret = GNUNET_DISK_file_read (ec->chld_stdout,
+ ec->read_buf,
+ ec->read_size - ec->read_pos);
+ if (ret < 0)
+ {
+ if ( (EAGAIN != errno) &&
+ (EWOULDBLOCK != errno) &&
+ (EINTR != errno) )
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "read");
+ return;
+ }
+ break;
+ }
+ if (0 == ret)
+ {
+ /* regular end of stream, good! */
+ return;
+ }
+ GNUNET_assert (ec->read_size >= ec->read_pos + ret);
+ ec->read_pos += ret;
+ }
+ ec->read_task
+ = GNUNET_SCHEDULER_add_read_file (
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ ec->chld_stdout,
+ &read_cb,
+ ec);
+}
+
+
+/**
+ * Function called when we can write more data to
+ * the child process.
+ *
+ * @param cls our `struct TALER_JSON_ExternalConversion *`
+ */
+static void
+write_cb (void *cls)
+{
+ struct TALER_JSON_ExternalConversion *ec = cls;
+ ssize_t ret;
+
+ ec->write_task = NULL;
+ while (ec->write_size > ec->write_pos)
+ {
+ ret = GNUNET_DISK_file_write (ec->chld_stdin,
+ ec->write_buf + ec->write_pos,
+ ec->write_size - ec->write_pos);
+ if (ret < 0)
+ {
+ if ( (EAGAIN != errno) &&
+ (EINTR != errno) )
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "write");
+ break;
+ }
+ if (0 == ret)
+ {
+ GNUNET_break (0);
+ break;
+ }
+ GNUNET_assert (ec->write_size >= ec->write_pos + ret);
+ ec->write_pos += ret;
+ }
+ if ( (ec->write_size > ec->write_pos) &&
+ ( (EAGAIN == errno) ||
+ (EWOULDBLOCK == errno) ||
+ (EINTR == errno) ) )
+ {
+ ec->write_task
+ = GNUNET_SCHEDULER_add_write_file (
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ ec->chld_stdin,
+ &write_cb,
+ ec);
+ }
+ else
+ {
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_close (ec->chld_stdin));
+ ec->chld_stdin = NULL;
+ }
+}
+
+
+/**
+ * Defines a GNUNET_ChildCompletedCallback which is sent back
+ * upon death or completion of a child process.
+ *
+ * @param cls handle for the callback
+ * @param type type of the process
+ * @param exit_code status code of the process
+ *
+ */
+static void
+child_done_cb (void *cls,
+ enum GNUNET_OS_ProcessStatusType type,
+ long unsigned int exit_code)
+{
+ struct TALER_JSON_ExternalConversion *ec = cls;
+ json_t *j;
+ json_error_t err;
+
+ ec->cwh = NULL;
+ if (NULL != ec->read_task)
+ {
+ GNUNET_SCHEDULER_cancel (ec->read_task);
+ /* We could get the process termination notification before having drained
+ the read buffer. So drain it now, just in case. */
+ read_cb (ec);
+ }
+ if (NULL != ec->read_task)
+ {
+ GNUNET_SCHEDULER_cancel (ec->read_task);
+ ec->read_task = NULL;
+ }
+ GNUNET_OS_process_destroy (ec->helper);
+ ec->helper = NULL;
+ j = json_loadb (ec->read_buf,
+ ec->read_pos,
+ JSON_REJECT_DUPLICATES,
+ &err);
+ if (NULL == j)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to parse JSON from helper at %d: %s\n",
+ err.position,
+ err.text);
+ }
+ ec->cb (ec->cb_cls,
+ type,
+ exit_code,
+ j);
+ json_decref (j);
+ TALER_JSON_external_conversion_stop (ec);
+}
+
+
+struct TALER_JSON_ExternalConversion *
+TALER_JSON_external_conversion_start (const json_t *input,
+ TALER_JSON_JsonCallback cb,
+ void *cb_cls,
+ const char *binary,
+ ...)
+{
+ struct TALER_JSON_ExternalConversion *ec;
+ struct GNUNET_DISK_PipeHandle *pipe_stdin;
+ struct GNUNET_DISK_PipeHandle *pipe_stdout;
+ va_list ap;
+
+ ec = GNUNET_new (struct TALER_JSON_ExternalConversion);
+ ec->cb = cb;
+ ec->cb_cls = cb_cls;
+ pipe_stdin = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_READ);
+ GNUNET_assert (NULL != pipe_stdin);
+ pipe_stdout = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_WRITE);
+ GNUNET_assert (NULL != pipe_stdout);
+ va_start (ap,
+ binary);
+ ec->helper = GNUNET_OS_start_process_va (GNUNET_OS_INHERIT_STD_ERR,
+ pipe_stdin,
+ pipe_stdout,
+ NULL,
+ binary,
+ ap);
+ va_end (ap);
+ if (NULL == ec->helper)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to run conversion helper `%s'\n",
+ binary);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_pipe_close (pipe_stdin));
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_pipe_close (pipe_stdout));
+ GNUNET_free (ec);
+ return NULL;
+ }
+ ec->chld_stdin =
+ GNUNET_DISK_pipe_detach_end (pipe_stdin,
+ GNUNET_DISK_PIPE_END_WRITE);
+ ec->chld_stdout =
+ GNUNET_DISK_pipe_detach_end (pipe_stdout,
+ GNUNET_DISK_PIPE_END_READ);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_pipe_close (pipe_stdin));
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_pipe_close (pipe_stdout));
+ ec->write_buf = json_dumps (input, JSON_COMPACT);
+ ec->write_size = strlen (ec->write_buf);
+ ec->read_task
+ = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+ ec->chld_stdout,
+ &read_cb,
+ ec);
+ ec->write_task
+ = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+ ec->chld_stdin,
+ &write_cb,
+ ec);
+ ec->cwh = GNUNET_wait_child (ec->helper,
+ &child_done_cb,
+ ec);
+ return ec;
+}
+
+
+void
+TALER_JSON_external_conversion_stop (
+ struct TALER_JSON_ExternalConversion *ec)
+{
+ if (NULL != ec->cwh)
+ {
+ GNUNET_wait_child_cancel (ec->cwh);
+ ec->cwh = NULL;
+ }
+ if (NULL != ec->helper)
+ {
+ GNUNET_break (0 ==
+ GNUNET_OS_process_kill (ec->helper,
+ SIGKILL));
+ GNUNET_OS_process_destroy (ec->helper);
+ }
+ if (NULL != ec->read_task)
+ {
+ GNUNET_SCHEDULER_cancel (ec->read_task);
+ ec->read_task = NULL;
+ }
+ if (NULL != ec->write_task)
+ {
+ GNUNET_SCHEDULER_cancel (ec->write_task);
+ ec->write_task = NULL;
+ }
+ if (NULL != ec->chld_stdin)
+ {
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_close (ec->chld_stdin));
+ ec->chld_stdin = NULL;
+ }
+ if (NULL != ec->chld_stdout)
+ {
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_close (ec->chld_stdout));
+ ec->chld_stdout = NULL;
+ }
+ GNUNET_free (ec->read_buf);
+ free (ec->write_buf);
+ GNUNET_free (ec);
+}
diff --git a/src/util/crypto_confirmation.c b/src/util/crypto_confirmation.c
index e52562e3e..a238d5376 100644
--- a/src/util/crypto_confirmation.c
+++ b/src/util/crypto_confirmation.c
@@ -90,9 +90,9 @@ compute_totp (struct GNUNET_TIME_Timestamp ts,
mc = gcry_md_read (md,
GCRY_MD_SHA1);
GNUNET_assert (NULL != mc);
- memcpy (hmac,
- mc,
- sizeof (hmac));
+ GNUNET_memcpy (hmac,
+ mc,
+ sizeof (hmac));
gcry_md_close (md);
}
@@ -102,7 +102,7 @@ compute_totp (struct GNUNET_TIME_Timestamp ts,
offset = hmac[sizeof (hmac) - 1] & 0x0f;
for (int count = 0; count < 4; count++)
- code |= hmac[offset + 3 - count] << (8 * count);
+ code |= ((uint32_t) hmac[offset + 3 - count]) << (8 * count);
code &= 0x7fffffff;
/* always use 8 digits (maximum) */
code = code % 100000000;
diff --git a/src/util/crypto_contract.c b/src/util/crypto_contract.c
index 3bfe9eb89..bec34c983 100644
--- a/src/util/crypto_contract.c
+++ b/src/util/crypto_contract.c
@@ -131,9 +131,9 @@ blob_encrypt (const struct NonceP *nonce,
+ data_size;
*res_size = ciphertext_size;
*res = GNUNET_malloc (ciphertext_size);
- memcpy (*res,
- nonce,
- crypto_secretbox_NONCEBYTES);
+ GNUNET_memcpy (*res,
+ nonce,
+ crypto_secretbox_NONCEBYTES);
GNUNET_assert (0 ==
crypto_secretbox_easy (*res + crypto_secretbox_NONCEBYTES,
data,
@@ -274,9 +274,9 @@ TALER_CRYPTO_contract_encrypt_for_merge (
hdr->header.ctype = htonl (TALER_EXCHANGE_CONTRACT_PAYMENT_OFFER);
hdr->header.clen = htonl ((uint32_t) clen);
hdr->merge_priv = *merge_priv;
- memcpy (&hdr[1],
- xbuf,
- cbuf_size);
+ GNUNET_memcpy (&hdr[1],
+ xbuf,
+ cbuf_size);
GNUNET_free (xbuf);
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&nonce,
@@ -423,9 +423,9 @@ TALER_CRYPTO_contract_encrypt_for_deposit (
hdr = GNUNET_malloc (sizeof (*hdr) + cbuf_size);
hdr->ctype = htonl (TALER_EXCHANGE_CONTRACT_PAYMENT_REQUEST);
hdr->clen = htonl ((uint32_t) clen);
- memcpy (&hdr[1],
- xbuf,
- cbuf_size);
+ GNUNET_memcpy (&hdr[1],
+ xbuf,
+ cbuf_size);
GNUNET_free (xbuf);
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&nonce,
@@ -441,12 +441,12 @@ TALER_CRYPTO_contract_encrypt_for_deposit (
GNUNET_free (hdr);
/* prepend purse_pub */
*econtract = GNUNET_malloc (xecontract_size + sizeof (*purse_pub));
- memcpy (*econtract,
- purse_pub,
- sizeof (*purse_pub));
- memcpy (sizeof (*purse_pub) + *econtract,
- xecontract,
- xecontract_size);
+ GNUNET_memcpy (*econtract,
+ purse_pub,
+ sizeof (*purse_pub));
+ GNUNET_memcpy (sizeof (*purse_pub) + *econtract,
+ xecontract,
+ xecontract_size);
*econtract_size = xecontract_size + sizeof (*purse_pub);
GNUNET_free (xecontract);
}
@@ -573,9 +573,9 @@ TALER_CRYPTO_kyc_attributes_encrypt (
cbuf_size = compressBound (clen);
xbuf = GNUNET_malloc (cbuf_size + sizeof (uint32_t));
belen = htonl ((uint32_t) clen);
- memcpy (xbuf,
- &belen,
- sizeof (belen));
+ GNUNET_memcpy (xbuf,
+ &belen,
+ sizeof (belen));
ret = compress (xbuf + 4,
&cbuf_size,
(const Bytef *) cstr,
@@ -623,9 +623,9 @@ TALER_CRYPTO_kyc_attributes_decrypt (
GNUNET_break_op (0);
return NULL;
}
- memcpy (&belen,
- xhdr,
- sizeof (belen));
+ GNUNET_memcpy (&belen,
+ xhdr,
+ sizeof (belen));
clen = ntohl (belen);
if (clen >= GNUNET_MAX_MALLOC_CHECKED)
{
diff --git a/src/util/crypto_helper_esign.c b/src/util/crypto_helper_esign.c
index 5a9ad74e2..5b04d0ead 100644
--- a/src/util/crypto_helper_esign.c
+++ b/src/util/crypto_helper_esign.c
@@ -357,9 +357,9 @@ TALER_CRYPTO_helper_esign_sign_ (
sr->header.size = htons (sizeof (buf));
sr->header.type = htons (TALER_HELPER_EDDSA_MT_REQ_SIGN);
sr->reserved = htonl (0);
- memcpy (&sr->purpose,
- purpose,
- purpose_size);
+ GNUNET_memcpy (&sr->purpose,
+ purpose,
+ purpose_size);
if (GNUNET_OK !=
TALER_crypto_helper_send_all (esh->sock,
buf,
diff --git a/src/util/crypto_helper_rsa.c b/src/util/crypto_helper_rsa.c
index efded50a1..4098a846b 100644
--- a/src/util/crypto_helper_rsa.c
+++ b/src/util/crypto_helper_rsa.c
@@ -417,9 +417,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,
@@ -655,9 +655,9 @@ TALER_CRYPTO_helper_rsa_batch_sign (
sr->header.size = htons (sizeof (*sr) + rsr->msg_size);
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);
wbuf += sizeof (*sr) + rsr->msg_size;
}
GNUNET_assert (wbuf == &obuf[mlen]);
diff --git a/src/util/exchange_signatures.c b/src/util/exchange_signatures.c
index d8bf716c7..6f8ebdaff 100644
--- a/src/util/exchange_signatures.c
+++ b/src/util/exchange_signatures.c
@@ -1177,10 +1177,10 @@ TALER_exchange_online_denomination_expired_sign (
};
/* strncpy would create a compiler warning */
- memcpy (dua.operation,
- op,
- GNUNET_MIN (sizeof (dua.operation),
- strlen (op)));
+ GNUNET_memcpy (dua.operation,
+ op,
+ GNUNET_MIN (sizeof (dua.operation),
+ strlen (op)));
return scb (&dua.purpose,
pub,
sig);
@@ -1204,10 +1204,10 @@ TALER_exchange_online_denomination_expired_verify (
};
/* strncpy would create a compiler warning */
- memcpy (dua.operation,
- op,
- GNUNET_MIN (sizeof (dua.operation),
- strlen (op)));
+ GNUNET_memcpy (dua.operation,
+ op,
+ GNUNET_MIN (sizeof (dua.operation),
+ strlen (op)));
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED,
&dua,
diff --git a/src/util/iban.c b/src/util/iban.c
index efd8c4282..c2274d3cb 100644
--- a/src/util/iban.c
+++ b/src/util/iban.c
@@ -233,9 +233,9 @@ TALER_iban_validate (const char *iban)
return GNUNET_strdup ("IBAN number too short to be valid");
if (len > 34)
return GNUNET_strdup ("IBAN number too long to be valid");
- memcpy (cc, iban, 2);
- memcpy (ibancpy, iban + 4, len - 4);
- memcpy (ibancpy + len - 4, iban, 4);
+ GNUNET_memcpy (cc, iban, 2);
+ GNUNET_memcpy (ibancpy, iban + 4, len - 4);
+ GNUNET_memcpy (ibancpy + len - 4, iban, 4);
ibancpy[len] = '\0';
cc_entry.code = cc;
cc_entry.english = NULL;
diff --git a/src/util/offline_signatures.c b/src/util/offline_signatures.c
index b1e3b93a3..fbff850df 100644
--- a/src/util/offline_signatures.c
+++ b/src/util/offline_signatures.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2020-2022 Taler Systems SA
+ Copyright (C) 2020-2023 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
@@ -677,6 +677,22 @@ struct TALER_MasterAddWirePS
* Hash over the exchange's payto URI.
*/
struct TALER_PaytoHashP h_payto GNUNET_PACKED;
+
+ /**
+ * Hash over the conversion URL, all zeros if there
+ * is no conversion URL.
+ */
+ struct GNUNET_HashCode h_conversion_url;
+
+ /**
+ * Hash over the debit restrictions.
+ */
+ struct GNUNET_HashCode h_debit_restrictions;
+
+ /**
+ * Hash over the credit restrictions.
+ */
+ struct GNUNET_HashCode h_credit_restrictions;
};
GNUNET_NETWORK_STRUCT_END
@@ -685,6 +701,9 @@ GNUNET_NETWORK_STRUCT_END
void
TALER_exchange_offline_wire_add_sign (
const char *payto_uri,
+ const char *conversion_url,
+ const json_t *debit_restrictions,
+ const json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp now,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig)
@@ -697,6 +716,14 @@ TALER_exchange_offline_wire_add_sign (
TALER_payto_hash (payto_uri,
&kv.h_payto);
+ if (NULL != conversion_url)
+ GNUNET_CRYPTO_hash (conversion_url,
+ strlen (conversion_url) + 1,
+ &kv.h_conversion_url);
+ TALER_json_hash (debit_restrictions,
+ &kv.h_debit_restrictions);
+ TALER_json_hash (credit_restrictions,
+ &kv.h_credit_restrictions);
GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
&kv,
&master_sig->eddsa_signature);
@@ -706,6 +733,9 @@ TALER_exchange_offline_wire_add_sign (
enum GNUNET_GenericReturnValue
TALER_exchange_offline_wire_add_verify (
const char *payto_uri,
+ const char *conversion_url,
+ const json_t *debit_restrictions,
+ const json_t *credit_restrictions,
struct GNUNET_TIME_Timestamp sign_time,
const struct TALER_MasterPublicKeyP *master_pub,
const struct TALER_MasterSignatureP *master_sig)
@@ -718,6 +748,14 @@ TALER_exchange_offline_wire_add_verify (
TALER_payto_hash (payto_uri,
&aw.h_payto);
+ if (NULL != conversion_url)
+ GNUNET_CRYPTO_hash (conversion_url,
+ strlen (conversion_url) + 1,
+ &aw.h_conversion_url);
+ TALER_json_hash (debit_restrictions,
+ &aw.h_debit_restrictions);
+ TALER_json_hash (credit_restrictions,
+ &aw.h_credit_restrictions);
return
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_MASTER_ADD_WIRE,
@@ -967,9 +1005,9 @@ TALER_exchange_offline_global_fee_sign (
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig)
{
- struct TALER_MasterGlobalFeePS kv = {
+ struct TALER_MasterGlobalFeePS wf = {
.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_GLOBAL_FEES),
- .purpose.size = htonl (sizeof (kv)),
+ .purpose.size = htonl (sizeof (wf)),
.start_date = GNUNET_TIME_timestamp_hton (start_time),
.end_date = GNUNET_TIME_timestamp_hton (end_time),
.purse_timeout = GNUNET_TIME_relative_hton (purse_timeout),
@@ -977,10 +1015,10 @@ TALER_exchange_offline_global_fee_sign (
.purse_account_limit = htonl (purse_account_limit)
};
- TALER_global_fee_set_hton (&kv.fees,
+ TALER_global_fee_set_hton (&wf.fees,
fees);
GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
- &kv,
+ &wf,
&master_sig->eddsa_signature);
}
@@ -1095,6 +1133,22 @@ struct TALER_MasterWireDetailsPS
*/
struct TALER_PaytoHashP h_wire_details GNUNET_PACKED;
+ /**
+ * Hash over the conversion URL, all zeros if there
+ * is no conversion URL.
+ */
+ struct GNUNET_HashCode h_conversion_url;
+
+ /**
+ * Hash over the debit restrictions.
+ */
+ struct GNUNET_HashCode h_debit_restrictions;
+
+ /**
+ * Hash over the credit restrictions.
+ */
+ struct GNUNET_HashCode h_credit_restrictions;
+
};
GNUNET_NETWORK_STRUCT_END
@@ -1103,6 +1157,9 @@ GNUNET_NETWORK_STRUCT_END
enum GNUNET_GenericReturnValue
TALER_exchange_wire_signature_check (
const char *payto_uri,
+ const char *conversion_url,
+ const json_t *debit_restrictions,
+ const json_t *credit_restrictions,
const struct TALER_MasterPublicKeyP *master_pub,
const struct TALER_MasterSignatureP *master_sig)
{
@@ -1113,6 +1170,14 @@ TALER_exchange_wire_signature_check (
TALER_payto_hash (payto_uri,
&wd.h_wire_details);
+ if (NULL != conversion_url)
+ GNUNET_CRYPTO_hash (conversion_url,
+ strlen (conversion_url) + 1,
+ &wd.h_conversion_url);
+ TALER_json_hash (debit_restrictions,
+ &wd.h_debit_restrictions);
+ TALER_json_hash (credit_restrictions,
+ &wd.h_credit_restrictions);
return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_DETAILS,
&wd,
&master_sig->eddsa_signature,
@@ -1123,6 +1188,9 @@ TALER_exchange_wire_signature_check (
void
TALER_exchange_wire_signature_make (
const char *payto_uri,
+ const char *conversion_url,
+ const json_t *debit_restrictions,
+ const json_t *credit_restrictions,
const struct TALER_MasterPrivateKeyP *master_priv,
struct TALER_MasterSignatureP *master_sig)
{
@@ -1133,6 +1201,14 @@ TALER_exchange_wire_signature_make (
TALER_payto_hash (payto_uri,
&wd.h_wire_details);
+ if (NULL != conversion_url)
+ GNUNET_CRYPTO_hash (conversion_url,
+ strlen (conversion_url) + 1,
+ &wd.h_conversion_url);
+ TALER_json_hash (debit_restrictions,
+ &wd.h_debit_restrictions);
+ TALER_json_hash (credit_restrictions,
+ &wd.h_credit_restrictions);
GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
&wd,
&master_sig->eddsa_signature);
diff --git a/src/util/payto.c b/src/util/payto.c
index 81664b1df..9b0e83e85 100644
--- a/src/util/payto.c
+++ b/src/util/payto.c
@@ -267,9 +267,9 @@ TALER_payto_hash (const char *payto,
&sha512);
GNUNET_static_assert (sizeof (sha512) > sizeof (*h_payto));
/* truncate */
- memcpy (h_payto,
- &sha512,
- sizeof (*h_payto));
+ GNUNET_memcpy (h_payto,
+ &sha512,
+ sizeof (*h_payto));
}
diff --git a/src/util/taler-exchange-secmod-cs.c b/src/util/taler-exchange-secmod-cs.c
index 2cdf09adf..ed0eba15d 100644
--- a/src/util/taler-exchange-secmod-cs.c
+++ b/src/util/taler-exchange-secmod-cs.c
@@ -423,9 +423,9 @@ generate_response (struct DenominationKey *dk)
&an->secm_sig);
an->secm_pub = TES_smpub;
p = (void *) &an[1];
- memcpy (p,
- denom->section,
- nlen);
+ GNUNET_memcpy (p,
+ denom->section,
+ nlen);
dk->an = an;
}
@@ -1373,9 +1373,9 @@ cs_client_init (struct TES_Client *client)
NULL != dk;
dk = dk->next)
{
- memcpy (&buf[obs],
- dk->an,
- ntohs (dk->an->header.size));
+ GNUNET_memcpy (&buf[obs],
+ dk->an,
+ ntohs (dk->an->header.size));
obs += ntohs (dk->an->header.size);
}
}
@@ -1472,18 +1472,18 @@ cs_update_client_keys (struct TES_Client *client)
.h_cs = key->h_cs
};
- memcpy (&buf[obs],
- &pn,
- sizeof (pn));
+ GNUNET_memcpy (&buf[obs],
+ &pn,
+ sizeof (pn));
GNUNET_assert (obs + sizeof (pn)
> obs);
obs += sizeof (pn);
}
else
{
- memcpy (&buf[obs],
- key->an,
- ntohs (key->an->header.size));
+ GNUNET_memcpy (&buf[obs],
+ key->an,
+ ntohs (key->an->header.size));
GNUNET_assert (obs + ntohs (key->an->header.size)
> obs);
obs += ntohs (key->an->header.size);
diff --git a/src/util/taler-exchange-secmod-eddsa.c b/src/util/taler-exchange-secmod-eddsa.c
index e07e9a71d..3b78e71df 100644
--- a/src/util/taler-exchange-secmod-eddsa.c
+++ b/src/util/taler-exchange-secmod-eddsa.c
@@ -826,9 +826,9 @@ parse_key (const char *filename,
filename);
return GNUNET_SYSERR;
}
- memcpy (&priv,
- buf,
- buf_size);
+ GNUNET_memcpy (&priv,
+ buf,
+ buf_size);
{
struct GNUNET_CRYPTO_EddsaPublicKey pub;
diff --git a/src/util/taler-exchange-secmod-rsa.c b/src/util/taler-exchange-secmod-rsa.c
index c651d78a8..414cb4acc 100644
--- a/src/util/taler-exchange-secmod-rsa.c
+++ b/src/util/taler-exchange-secmod-rsa.c
@@ -394,13 +394,13 @@ generate_response (struct DenominationKey *dk)
&an->secm_sig);
an->secm_pub = TES_smpub;
p = (void *) &an[1];
- memcpy (p,
- buf,
- buf_len);
+ GNUNET_memcpy (p,
+ buf,
+ buf_len);
GNUNET_free (buf);
- memcpy (p + buf_len,
- denom->section,
- nlen);
+ GNUNET_memcpy (p + buf_len,
+ denom->section,
+ nlen);
dk->an = an;
}
@@ -524,9 +524,9 @@ send_signature (struct TES_Client *client,
sr = GNUNET_malloc (tsize);
sr->header.size = htons (tsize);
sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE);
- memcpy (&sr[1],
- buf,
- buf_size);
+ GNUNET_memcpy (&sr[1],
+ buf,
+ buf_size);
GNUNET_free (buf);
ret = TES_transmit (client->csock,
&sr->header);
@@ -1111,9 +1111,9 @@ rsa_client_init (struct TES_Client *client)
NULL != dk;
dk = dk->next)
{
- memcpy (&buf[obs],
- dk->an,
- ntohs (dk->an->header.size));
+ GNUNET_memcpy (&buf[obs],
+ dk->an,
+ ntohs (dk->an->header.size));
GNUNET_assert (obs + ntohs (dk->an->header.size)
> obs);
obs += ntohs (dk->an->header.size);
@@ -1212,18 +1212,18 @@ rsa_update_client_keys (struct TES_Client *client)
.h_rsa = key->h_rsa
};
- memcpy (&buf[obs],
- &pn,
- sizeof (pn));
+ GNUNET_memcpy (&buf[obs],
+ &pn,
+ sizeof (pn));
GNUNET_assert (obs + sizeof (pn)
> obs);
obs += sizeof (pn);
}
else
{
- memcpy (&buf[obs],
- key->an,
- ntohs (key->an->header.size));
+ GNUNET_memcpy (&buf[obs],
+ key->an,
+ ntohs (key->an->header.size));
GNUNET_assert (obs + ntohs (key->an->header.size)
> obs);
obs += ntohs (key->an->header.size);
diff --git a/src/util/test_conversion.c b/src/util/test_conversion.c
new file mode 100644
index 000000000..00cb35e72
--- /dev/null
+++ b/src/util/test_conversion.c
@@ -0,0 +1,149 @@
+/*
+ This file is part of TALER
+ (C) 2023 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_conversion.c
+ * @brief Tests for conversion logic
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include <gnunet/gnunet_json_lib.h>
+
+/**
+ * Return value from main().
+ */
+static int global_ret;
+
+/**
+ * Handle to our helper.
+ */
+static struct TALER_JSON_ExternalConversion *ec;
+
+
+/**
+ * Type of a callback that receives a JSON @a result.
+ *
+ * @param cls closure
+ * @param status_type how did the process die
+ * @apram code termination status code from the process
+ * @param result some JSON result, NULL if we failed to get an JSON output
+ */
+static void
+conv_cb (void *cls,
+ enum GNUNET_OS_ProcessStatusType status_type,
+ unsigned long code,
+ const json_t *result)
+{
+ json_t *expect;
+
+ (void) cls;
+ (void) status_type;
+ ec = NULL;
+ global_ret = 3;
+ if (42 != code)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected return value from helper: %u\n",
+ (unsigned int) code);
+ return;
+ }
+ expect = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("foo",
+ "arg")
+ );
+ if (1 == json_equal (expect,
+ result))
+ {
+ global_ret = 0;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected JSON result\n");
+ json_dumpf (result,
+ stderr,
+ JSON_INDENT (2));
+ global_ret = 4;
+ }
+ json_decref (expect);
+}
+
+
+/**
+ * Function called on shutdown/CTRL-C.
+ *
+ * @param cls NULL
+ */
+static void
+do_shutdown (void *cls)
+{
+ (void) cls;
+ if (NULL != ec)
+ {
+ GNUNET_break (0);
+ global_ret = 2;
+ TALER_JSON_external_conversion_stop (ec);
+ ec = NULL;
+ }
+}
+
+
+/**
+ * Main test function.
+ *
+ * @param cls NULL
+ */
+static void
+run (void *cls)
+{
+ json_t *input;
+
+ (void) cls;
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+ NULL);
+ input = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("key",
+ "foo")
+ );
+ ec = TALER_JSON_external_conversion_start (input,
+ &conv_cb,
+ NULL,
+ "./test_conversion.sh",
+ "test_conversion.sh",
+ "arg",
+ NULL);
+ json_decref (input);
+ GNUNET_assert (NULL != ec);
+}
+
+
+int
+main (int argc,
+ const char *const argv[])
+{
+ (void) argc;
+ (void) argv;
+ unsetenv ("XDG_DATA_HOME");
+ unsetenv ("XDG_CONFIG_HOME");
+ GNUNET_log_setup ("test-conversion",
+ "WARNING",
+ NULL);
+ GNUNET_OS_init (TALER_project_data_default ());
+ global_ret = 1;
+ GNUNET_SCHEDULER_run (&run,
+ NULL);
+ return global_ret;
+}
diff --git a/src/util/test_conversion.sh b/src/util/test_conversion.sh
new file mode 100755
index 000000000..26e1a36d8
--- /dev/null
+++ b/src/util/test_conversion.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+KEY=$(jq -r .key)
+echo -n "{\"$KEY\":\"$1\"}"
+exit 42
diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c
index 80a247770..80ce9083d 100644
--- a/src/util/test_crypto.c
+++ b/src/util/test_crypto.c
@@ -355,15 +355,24 @@ test_exchange_sigs (void)
struct TALER_MasterPrivateKeyP priv;
struct TALER_MasterPublicKeyP pub;
struct TALER_MasterSignatureP sig;
+ json_t *rest;
GNUNET_CRYPTO_eddsa_key_create (&priv.eddsa_priv);
+ rest = json_array ();
+ GNUNET_assert (NULL != rest);
TALER_exchange_wire_signature_make (pt,
+ NULL,
+ rest,
+ rest,
&priv,
&sig);
GNUNET_CRYPTO_eddsa_key_get_public (&priv.eddsa_priv,
&pub.eddsa_pub);
if (GNUNET_OK !=
TALER_exchange_wire_signature_check (pt,
+ NULL,
+ rest,
+ rest,
&pub,
&sig))
{
@@ -373,12 +382,28 @@ test_exchange_sigs (void)
if (GNUNET_OK ==
TALER_exchange_wire_signature_check (
"payto://x-taler-bank/localhost/Other",
+ NULL,
+ rest,
+ rest,
&pub,
&sig))
{
GNUNET_break (0);
return 1;
}
+ if (GNUNET_OK ==
+ TALER_exchange_wire_signature_check (
+ pt,
+ "http://example.com/",
+ rest,
+ rest,
+ &pub,
+ &sig))
+ {
+ GNUNET_break (0);
+ return 1;
+ }
+ json_decref (rest);
return 0;
}
diff --git a/src/util/util.c b/src/util/util.c
index 96d791912..da5727487 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -25,6 +25,7 @@
#include "taler_util.h"
#include "taler_attributes.h"
#include <gnunet/gnunet_json_lib.h>
+#include <unistr.h>
const char *
@@ -40,9 +41,9 @@ TALER_b2s (const void *buf,
&hc);
tmp = GNUNET_STRINGS_data_to_string_alloc (&hc,
sizeof (hc));
- memcpy (ret,
- tmp,
- 8);
+ GNUNET_memcpy (ret,
+ tmp,
+ 8);
GNUNET_free (tmp);
ret[8] = '\0';
return ret;
@@ -205,6 +206,164 @@ TALER_denom_fee_check_currency (
/**
+ * Dump character in the low range into @a buf
+ * following RFC 8785.
+ *
+ * @param[in,out] buf buffer to modify
+ * @param val value to dump
+ */
+static void
+lowdump (struct GNUNET_Buffer *buf,
+ unsigned char val)
+{
+ char scratch[7];
+
+ switch (val)
+ {
+ case 0x8:
+ GNUNET_buffer_write (buf,
+ "\\b",
+ 2);
+ break;
+ case 0x9:
+ GNUNET_buffer_write (buf,
+ "\\t",
+ 2);
+ break;
+ case 0xA:
+ GNUNET_buffer_write (buf,
+ "\\n",
+ 2);
+ break;
+ case 0xC:
+ GNUNET_buffer_write (buf,
+ "\\f",
+ 2);
+ break;
+ case 0xD:
+ GNUNET_buffer_write (buf,
+ "\\r",
+ 2);
+ break;
+ default:
+ GNUNET_snprintf (scratch,
+ sizeof (scratch),
+ "\\u%04x",
+ (unsigned int) val);
+ GNUNET_buffer_write (buf,
+ scratch,
+ 6);
+ break;
+ }
+}
+
+
+size_t
+TALER_rfc8785encode (char **inp)
+{
+ struct GNUNET_Buffer buf = { 0 };
+ size_t left = strlen (*inp) + 1;
+ size_t olen;
+ char *in = *inp;
+ const char *pos = in;
+
+ GNUNET_buffer_prealloc (&buf,
+ left + 40);
+ buf.warn_grow = 0; /* disable, + 40 is just a wild guess */
+ while (1)
+ {
+ int mbl = u8_mblen ((unsigned char *) pos,
+ left);
+ unsigned char val;
+
+ if (0 == mbl)
+ break;
+ val = (unsigned char) *pos;
+ if ( (1 == mbl) &&
+ (val <= 0x1F) )
+ {
+ /* Should not happen, as input is produced by
+ * JSON stringification */
+ GNUNET_break (0);
+ lowdump (&buf,
+ val);
+ }
+ else if ( (1 == mbl) && ('\\' == *pos) )
+ {
+ switch (*(pos + 1))
+ {
+ case '\\':
+ mbl = 2;
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ break;
+ case 'u':
+ {
+ unsigned int num;
+ uint32_t n32;
+ unsigned char res[8];
+ size_t rlen;
+
+ GNUNET_assert ( (1 ==
+ sscanf (pos + 2,
+ "%4x",
+ &num)) ||
+ (1 ==
+ sscanf (pos + 2,
+ "%4X",
+ &num)) );
+ mbl = 6;
+ n32 = (uint32_t) num;
+ rlen = sizeof (res);
+ u32_to_u8 (&n32,
+ 1,
+ res,
+ &rlen);
+ if ( (1 == rlen) &&
+ (res[0] <= 0x1F) )
+ {
+ lowdump (&buf,
+ res[0]);
+ }
+ else
+ {
+ GNUNET_buffer_write (&buf,
+ (const char *) res,
+ rlen);
+ }
+ }
+ break;
+ default:
+ mbl = 2;
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ break;
+ }
+ }
+ else
+ {
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ }
+ left -= mbl;
+ pos += mbl;
+ }
+
+ /* 0-terminate buffer */
+ GNUNET_buffer_write (&buf,
+ "",
+ 1);
+ GNUNET_free (in);
+ *inp = GNUNET_buffer_reap (&buf,
+ &olen);
+ return olen;
+}
+
+
+/**
* Hash normalized @a j JSON object or array and
* store the result in @a hc.
*
@@ -221,11 +380,11 @@ TALER_json_hash (const json_t *j,
cstr = json_dumps (j,
JSON_COMPACT | JSON_SORT_KEYS);
GNUNET_assert (NULL != cstr);
- clen = strlen (cstr);
+ clen = TALER_rfc8785encode (&cstr);
GNUNET_CRYPTO_hash (cstr,
clen,
hc);
- free (cstr);
+ GNUNET_free (cstr);
}