diff options
Diffstat (limited to 'src/util/util.c')
-rw-r--r-- | src/util/util.c | 406 |
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 | |||
38 | static void | ||
39 | fatal_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 | */ | ||
49 | void | ||
50 | TALER_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 | */ | ||
69 | int | ||
70 | TALER_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 | */ | ||
163 | struct TALER_AmountNBO | ||
164 | TALER_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 | */ | ||
178 | struct TALER_Amount | ||
179 | TALER_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 | */ | ||
199 | int | ||
200 | TALER_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 | */ | ||
225 | struct TALER_Amount | ||
226 | TALER_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 | */ | ||
263 | struct TALER_Amount | ||
264 | TALER_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 | */ | ||
304 | struct TALER_Amount | ||
305 | TALER_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 | */ | ||
322 | char * | ||
323 | TALER_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 | */ | ||
394 | int | ||
395 | TALER_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 | |||
420 | static void | ||
421 | derive_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 | |||
441 | int | ||
442 | TALER_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 | |||
453 | int | ||
454 | TALER_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 */ |