aboutsummaryrefslogtreecommitdiff
path: root/src/util/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/util.c')
-rw-r--r--src/util/util.c406
1 files changed, 1 insertions, 405 deletions
diff --git a/src/util/util.c b/src/util/util.c
index 80f8fc5f0..440b49fab 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -28,335 +28,11 @@
28#include <gnunet/gnunet_util_lib.h> 28#include <gnunet/gnunet_util_lib.h>
29#include <gcrypt.h> 29#include <gcrypt.h>
30 30
31#define CURVE "Ed25519"
32
33#define AMOUNT_FRAC_BASE 1000000
34#define AMOUNT_FRAC_LEN 6
35
36
37
38static void
39fatal_error_handler (void *cls, int wtf, const char *msg)
40{
41 LOG_ERROR("Fatal error in Gcrypt: %s\n", msg);
42 abort();
43}
44
45
46/**
47 * Initialize Gcrypt library.
48 */
49void
50TALER_gcrypt_init()
51{
52 gcry_set_fatalerror_handler (&fatal_error_handler, NULL);
53 TALER_assert_as(gcry_check_version(NEED_LIBGCRYPT_VERSION),
54 "libgcrypt version mismatch");
55 /* Disable secure memory. */
56 gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
57 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
58}
59
60
61/**
62 * Parse money amount description, in the format "A:B.C".
63 *
64 * @param str amount description
65 * @param denom amount to write the result to
66 * @return GNUNET_OK if the string is a valid amount specification,
67 * GNUNET_SYSERR if it is invalid.
68 */
69int
70TALER_string_to_amount (const char *str, struct TALER_Amount *denom)
71{
72 unsigned int i; // pos in str
73 int n; // number tmp
74 unsigned int c; // currency pos
75 uint32_t b; // base for suffix
76
77 memset (denom, 0, sizeof (struct TALER_Amount));
78
79 i = n = c = 0;
80
81 while (isspace(str[i]))
82 i++;
83
84 if (0 == str[i])
85 {
86 printf("null before currency\n");
87 return GNUNET_SYSERR;
88 }
89
90 while (str[i] != ':')
91 {
92 if (0 == str[i])
93 {
94 printf("null before colon");
95 return GNUNET_SYSERR;
96 }
97 if (c > 3)
98 {
99 printf("currency too long\n");
100 return GNUNET_SYSERR;
101 }
102 denom->currency[c] = str[i];
103 c++;
104 i++;
105 }
106
107 // skip colon
108 i++;
109
110 if (0 == str[i])
111 {
112 printf("null before value\n");
113 return GNUNET_SYSERR;
114 }
115
116 while (str[i] != '.')
117 {
118 if (0 == str[i])
119 {
120 return GNUNET_OK;
121 }
122 n = str[i] - '0';
123 if (n < 0 || n > 9)
124 {
125 printf("invalid character '%c' before comma at %u\n", (char) n, i);
126 return GNUNET_SYSERR;
127 }
128 denom->value = (denom->value * 10) + n;
129 i++;
130 }
131
132 // skip the dot
133 i++;
134
135 if (0 == str[i])
136 {
137 printf("null after dot");
138 return GNUNET_SYSERR;
139 }
140
141 b = 100000;
142
143 while (0 != str[i])
144 {
145 n = str[i] - '0';
146 if (b == 0 || n < 0 || n > 9)
147 {
148 printf("error after comma");
149 return GNUNET_SYSERR;
150 }
151 denom->fraction += n * b;
152 b /= 10;
153 i++;
154 }
155
156 return GNUNET_OK;
157}
158
159
160/**
161 * FIXME
162 */
163struct TALER_AmountNBO
164TALER_amount_hton (struct TALER_Amount d)
165{
166 struct TALER_AmountNBO dn;
167 dn.value = htonl (d.value);
168 dn.fraction = htonl (d.fraction);
169 memcpy (dn.currency, d.currency, TALER_CURRENCY_LEN);
170
171 return dn;
172}
173
174
175/**
176 * FIXME
177 */
178struct TALER_Amount
179TALER_amount_ntoh (struct TALER_AmountNBO dn)
180{
181 struct TALER_Amount d;
182 d.value = ntohl (dn.value);
183 d.fraction = ntohl (dn.fraction);
184 memcpy (d.currency, dn.currency, sizeof(dn.currency));
185
186 return d;
187}
188
189
190/**
191 * Compare the value/fraction of two amounts. Does not compare the currency,
192 * i.e. comparing amounts with the same value and fraction but different
193 * currency would return 0.
194 *
195 * @param a1 first amount
196 * @param a2 second amount
197 * @return result of the comparison
198 */
199int
200TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2)
201{
202 a1 = TALER_amount_normalize (a1);
203 a2 = TALER_amount_normalize (a2);
204 if (a1.value == a2.value)
205 {
206 if (a1.fraction < a2.fraction)
207 return -1;
208 if (a1.fraction > a2.fraction)
209 return 1;
210 return 0;
211 }
212 if (a1.value < a2.value)
213 return -1;
214 return 1;
215}
216
217
218/**
219 * Perform saturating subtraction of amounts.
220 *
221 * @param a1 amount to subtract from
222 * @param a2 amount to subtract
223 * @return (a1-a2) or 0 if a2>=a1
224 */
225struct TALER_Amount
226TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2)
227{
228 a1 = TALER_amount_normalize (a1);
229 a2 = TALER_amount_normalize (a2);
230
231 if (a1.value < a2.value)
232 {
233 a1.value = 0;
234 a1.fraction = 0;
235 return a1;
236 }
237
238 if (a1.fraction < a2.fraction)
239 {
240 if (0 == a1.value)
241 {
242 a1.fraction = 0;
243 return a1;
244 }
245 a1.fraction += AMOUNT_FRAC_BASE;
246 a1.value -= 1;
247 }
248
249 a1.fraction -= a2.fraction;
250 a1.value -= a2.value;
251
252 return a1;
253}
254
255
256/**
257 * Perform saturating addition of amounts.
258 *
259 * @param a1 first amount to add
260 * @param a2 second amount to add
261 * @return sum of a1 and a2
262 */
263struct TALER_Amount
264TALER_amount_add (struct TALER_Amount a1, struct TALER_Amount a2)
265{
266 a1 = TALER_amount_normalize (a1);
267 a2 = TALER_amount_normalize (a2);
268
269 a1.value += a2.value;
270 a1.fraction += a2.fraction;
271
272 if (0 == a1.currency[0])
273 {
274 memcpy (a2.currency, a1.currency, TALER_CURRENCY_LEN);
275 }
276
277 if (0 == a2.currency[0])
278 {
279 memcpy (a1.currency, a2.currency, TALER_CURRENCY_LEN);
280 }
281
282 if (0 != a1.currency[0] && 0 != memcmp (a1.currency, a2.currency, TALER_CURRENCY_LEN))
283 {
284 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "adding mismatching currencies\n");
285 }
286
287 if (a1.value < a2.value)
288 {
289 a1.value = UINT32_MAX;
290 a2.value = UINT32_MAX;
291 return a1;
292 }
293
294 return TALER_amount_normalize (a1);
295}
296
297
298/**
299 * Normalize the given amount.
300 *
301 * @param amout amount to normalize
302 * @return normalized amount
303 */
304struct TALER_Amount
305TALER_amount_normalize (struct TALER_Amount amount)
306{
307 while (amount.value != UINT32_MAX && amount.fraction >= AMOUNT_FRAC_BASE)
308 {
309 amount.fraction -= AMOUNT_FRAC_BASE;
310 amount.value += 1;
311 }
312 return amount;
313}
314
315
316/**
317 * Convert amount to string.
318 *
319 * @param amount amount to convert to string
320 * @return freshly allocated string representation
321 */
322char *
323TALER_amount_to_string (struct TALER_Amount amount)
324{
325 char tail[AMOUNT_FRAC_LEN + 1] = { 0 };
326 char curr[TALER_CURRENCY_LEN + 1] = { 0 };
327 char *result = NULL;
328 int len;
329
330 memcpy (curr, amount.currency, TALER_CURRENCY_LEN);
331
332 amount = TALER_amount_normalize (amount);
333 if (0 != amount.fraction)
334 {
335 unsigned int i;
336 uint32_t n = amount.fraction;
337 for (i = 0; (i < AMOUNT_FRAC_LEN) && (n != 0); i++)
338 {
339 tail[i] = '0' + (n / (AMOUNT_FRAC_BASE / 10));
340 n = (n * 10) % (AMOUNT_FRAC_BASE);
341 }
342 tail[i] = 0;
343 len = GNUNET_asprintf (&result, "%s:%lu.%s", curr, (unsigned long) amount.value, tail);
344 }
345 else
346 {
347 len = GNUNET_asprintf (&result, "%s:%lu", curr, (unsigned long) amount.value);
348 }
349 GNUNET_assert (len > 0);
350 return result;
351}
352
353
354
355/** 31/**
356 * Return the base32crockford encoding of the given buffer. 32 * Return the base32crockford encoding of the given buffer.
357 * 33 *
358 * The returned string will be freshly allocated, and must be free'd 34 * The returned string will be freshly allocated, and must be free'd
359 * with GNUNET_free. 35 * with GNUNET_free().
360 * 36 *
361 * @param buffer with data 37 * @param buffer with data
362 * @param size size of the buffer 38 * @param size size of the buffer
@@ -384,84 +60,4 @@ TALER_data_to_string_alloc (const void *buf, size_t size)
384} 60}
385 61
386 62
387/**
388 * Get encoded binary data from a configuration.
389 *
390 * @return GNUNET_OK on success
391 * GNUNET_NO is the value does not exist
392 * GNUNET_SYSERR on encoding error
393 */
394int
395TALER_configuration_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg,
396 const char *section, const char *option,
397 void *buf, size_t buf_size)
398{
399 char *enc;
400 int res;
401 size_t data_size;
402 if (GNUNET_OK != (res = GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &enc)))
403 return res;
404 data_size = (strlen (enc) * 5) / 8;
405 if (data_size != buf_size)
406 {
407 GNUNET_free (enc);
408 return GNUNET_SYSERR;
409 }
410 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, strlen (enc),
411 buf, buf_size))
412 {
413 GNUNET_free (enc);
414 return GNUNET_SYSERR;
415 }
416 return GNUNET_OK;
417}
418
419
420static void
421derive_refresh_key (const struct GNUNET_HashCode *secret,
422 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
423 struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
424{
425 static const char ctx_key[] = "taler-key-skey";
426 static const char ctx_iv[] = "taler-key-iv";
427
428 GNUNET_assert (GNUNET_YES ==
429 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
430 ctx_key, strlen (ctx_key),
431 secret, sizeof (struct GNUNET_HashCode),
432 NULL, 0));
433 GNUNET_assert (GNUNET_YES ==
434 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
435 ctx_iv, strlen (ctx_iv),
436 secret, sizeof (struct GNUNET_HashCode),
437 NULL, 0));
438}
439
440
441int
442TALER_refresh_decrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result)
443{
444 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
445 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
446
447 derive_refresh_key (secret, &iv, &skey);
448
449 return GNUNET_CRYPTO_symmetric_decrypt (input, input_size, &skey, &iv, result);
450}
451
452
453int
454TALER_refresh_encrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result)
455{
456 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
457 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
458
459 derive_refresh_key (secret, &iv, &skey);
460
461 return GNUNET_CRYPTO_symmetric_encrypt (input, input_size, &skey, &iv, result);
462}
463
464
465
466
467/* end of util.c */ 63/* end of util.c */