aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-01-27 16:18:33 +0100
committerChristian Grothoff <christian@grothoff.org>2015-01-27 16:18:33 +0100
commit2cda5ea7ee7e0e87b875ce54b483fdde86ed0dac (patch)
treedd8bfcc5cb1a8c7b77687de8863b2b330abb9309
parent610b7b62c09cb19410dc283f0629e4b24c343b57 (diff)
downloadexchange-2cda5ea7ee7e0e87b875ce54b483fdde86ed0dac.tar.gz
exchange-2cda5ea7ee7e0e87b875ce54b483fdde86ed0dac.zip
rework taler lib, moving some code to GNUnet, cleaner refresh encrypt/decypt API
-rw-r--r--src/include/taler_util.h142
-rw-r--r--src/mint/mint.h73
-rw-r--r--src/util/Makefile.am2
-rw-r--r--src/util/amount.c329
-rw-r--r--src/util/crypto.c118
-rw-r--r--src/util/util.c406
6 files changed, 600 insertions, 470 deletions
diff --git a/src/include/taler_util.h b/src/include/taler_util.h
index d37ac356f..f1264d254 100644
--- a/src/include/taler_util.h
+++ b/src/include/taler_util.h
@@ -65,22 +65,50 @@
65 do {int rc; rc = cmd; if (!rc) break; LOG_ERROR("A Gcrypt call failed at %s:%d with error: %s\n", __FILE__, __LINE__, gcry_strerror(rc)); abort(); } while (0) 65 do {int rc; rc = cmd; if (!rc) break; LOG_ERROR("A Gcrypt call failed at %s:%d with error: %s\n", __FILE__, __LINE__, gcry_strerror(rc)); abort(); } while (0)
66 66
67 67
68
69/**
70 * Initialize Gcrypt library.
71 */
72void
73TALER_gcrypt_init (void);
74
75
76/* *********************** Amount management ****************** */
77
78
79/**
80 * Number of characters (plus 1 for 0-termination) we use to
81 * represent currency names (i.e. EUR, USD, etc.).
82 */
68#define TALER_CURRENCY_LEN 4 83#define TALER_CURRENCY_LEN 4
69 84
70 85
71GNUNET_NETWORK_STRUCT_BEGIN 86GNUNET_NETWORK_STRUCT_BEGIN
72 87
88/**
89 * Amount, encoded for network transmission.
90 */
73struct TALER_AmountNBO 91struct TALER_AmountNBO
74{ 92{
93 /**
94 * Value in the main currency, in NBO.
95 */
75 uint32_t value; 96 uint32_t value;
97
98 /**
99 * Additinal fractional value, in NBO.
100 */
76 uint32_t fraction; 101 uint32_t fraction;
102
103 /**
104 * Type of the currency being represented.
105 */
77 char currency[TALER_CURRENCY_LEN]; 106 char currency[TALER_CURRENCY_LEN];
78}; 107};
79 108
80GNUNET_NETWORK_STRUCT_END 109GNUNET_NETWORK_STRUCT_END
81 110
82 111
83
84/** 112/**
85 * Representation of monetary value in a given currency. 113 * Representation of monetary value in a given currency.
86 */ 114 */
@@ -90,10 +118,12 @@ struct TALER_Amount
90 * Value (numerator of fraction) 118 * Value (numerator of fraction)
91 */ 119 */
92 uint32_t value; 120 uint32_t value;
121
93 /** 122 /**
94 * Fraction (denominator of fraction) 123 * Fraction (denominator of fraction)
95 */ 124 */
96 uint32_t fraction; 125 uint32_t fraction;
126
97 /** 127 /**
98 * Currency string, left adjusted and padded with zeros. 128 * Currency string, left adjusted and padded with zeros.
99 */ 129 */
@@ -102,37 +132,38 @@ struct TALER_Amount
102 132
103 133
104/** 134/**
105 * Initialize Gcrypt library.
106 */
107void
108TALER_gcrypt_init (void);
109
110
111/**
112 * Parse denomination description, in the format "T : V : F". 135 * Parse denomination description, in the format "T : V : F".
113 * 136 *
114 * @param str denomination description 137 * @param str denomination description
115 * @param denom denomination to write the result to 138 * @param denom denomination to write the result to
116 * @return GNUNET_OK if the string is a valid denomination specification, 139 * @return #GNUNET_OK if the string is a valid denomination specification,
117 * GNUNET_SYSERR if it is invalid. 140 * #GNUNET_SYSERR if it is invalid.
118 */ 141 */
119int 142int
120TALER_string_to_amount (const char *str, struct TALER_Amount *denom); 143TALER_string_to_amount (const char *str,
144 struct TALER_Amount *denom);
121 145
122 146
123/** 147/**
124 * FIXME 148 * Convert amount from host to network representation.
149 *
150 * @param d amount in host representation
151 * @return amount in network representation
125 */ 152 */
126struct TALER_AmountNBO 153struct TALER_AmountNBO
127TALER_amount_hton (struct TALER_Amount d); 154TALER_amount_hton (struct TALER_Amount d);
128 155
129 156
130/** 157/**
131 * FIXME 158 * Convert amount from network to host representation.
159 *
160 * @param d amount in network representation
161 * @return amount in host representation
132 */ 162 */
133struct TALER_Amount 163struct TALER_Amount
134TALER_amount_ntoh (struct TALER_AmountNBO dn); 164TALER_amount_ntoh (struct TALER_AmountNBO dn);
135 165
166
136/** 167/**
137 * Compare the value/fraction of two amounts. Does not compare the currency, 168 * Compare the value/fraction of two amounts. Does not compare the currency,
138 * i.e. comparing amounts with the same value and fraction but different 169 * i.e. comparing amounts with the same value and fraction but different
@@ -143,7 +174,8 @@ TALER_amount_ntoh (struct TALER_AmountNBO dn);
143 * @return result of the comparison 174 * @return result of the comparison
144 */ 175 */
145int 176int
146TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2); 177TALER_amount_cmp (struct TALER_Amount a1,
178 struct TALER_Amount a2);
147 179
148 180
149/** 181/**
@@ -154,7 +186,8 @@ TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2);
154 * @return (a1-a2) or 0 if a2>=a1 186 * @return (a1-a2) or 0 if a2>=a1
155 */ 187 */
156struct TALER_Amount 188struct TALER_Amount
157TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2); 189TALER_amount_subtract (struct TALER_Amount a1,
190 struct TALER_Amount a2);
158 191
159 192
160/** 193/**
@@ -165,7 +198,8 @@ TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2);
165 * @return sum of a1 and a2 198 * @return sum of a1 and a2
166 */ 199 */
167struct TALER_Amount 200struct TALER_Amount
168TALER_amount_add (struct TALER_Amount a1, struct TALER_Amount a2); 201TALER_amount_add (struct TALER_Amount a1,
202 struct TALER_Amount a2);
169 203
170 204
171/** 205/**
@@ -187,43 +221,89 @@ TALER_amount_normalize (struct TALER_Amount amount);
187char * 221char *
188TALER_amount_to_string (struct TALER_Amount amount); 222TALER_amount_to_string (struct TALER_Amount amount);
189 223
224/* ****************** FIXME: move to GNUnet? ************** */
190 225
191/** 226/**
192 * Return the base32crockford encoding of the given buffer. 227 * Return the base32crockford encoding of the given buffer.
193 * 228 *
194 * The returned string will be freshly allocated, and must be free'd 229 * The returned string will be freshly allocated, and must be free'd
195 * with GNUNET_free. 230 * with #GNUNET_free().
196 * 231 *
197 * @param buffer with data 232 * @param buffer with data
198 * @param size size of the buffer 233 * @param size size of the buffer
199 * @return freshly allocated, null-terminated string 234 * @return freshly allocated, null-terminated string
200 */ 235 */
201char * 236char *
202TALER_data_to_string_alloc (const void *buf, size_t size); 237TALER_data_to_string_alloc (const void *buf,
238 size_t size);
239
203 240
241/* ****************** Refresh crypto primitives ************* */
204 242
205/** 243/**
206 * Get encoded binary data from a configuration. 244 * Representation of an encrypted refresh link.
207 *
208 * @return GNUNET_OK on success
209 * GNUNET_NO is the value does not exist
210 * GNUNET_SYSERR on encoding error
211 */ 245 */
212int 246struct TALER_RefreshLinkEncrypted
213TALER_configuration_get_data (const struct GNUNET_CONFIGURATION_Handle *cfg, 247{
214 const char *section, const char *option,
215 void *buf, size_t buf_size);
216 248
249 /**
250 * Encrypted private key of the coin.
251 */
252 char [sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)] coin_priv_enc;
217 253
254 /**
255 * Encrypted blinding key with @e blinding_key_enc_size bytes.
256 */
257 char *blinding_key_enc;
218 258
259 /**
260 * Number of bytes in @e blinding_key_enc.
261 */
262 size_t blinding_key_enc_size;
263};
219 264
220int
221TALER_refresh_decrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result);
222 265
223int 266/**
224TALER_refresh_encrypt (const void *input, size_t input_size, const struct GNUNET_HashCode *secret, void *result); 267 * Representation of an refresh link in cleartext.
268 */
269struct TALER_RefreshLinkDecrypted
270{
271
272 /**
273 * Private key of the coin.
274 */
275 struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv;
276
277 /**
278 * Blinding key with @e blinding_key_enc_size bytes.
279 */
280 struct GNUNET_CRYPTO_rsa_BlindingKey *blinding_key;
281
282};
225 283
226 284
285/**
286 * Decrypt refresh link information.
287 *
288 * @param input encrypted refresh link data
289 * @param secret shared secret to use for decryption
290 * @return NULL on error
291 */
292struct TALER_RefreshLinkDecrypted *
293TALER_refresh_decrypt (const struct TALER_RefreshLinkEncrypted *input,
294 const struct GNUNET_HashCode *secret);
295
296
297/**
298 * Encrypt refresh link information.
299 *
300 * @param input plaintext refresh link data
301 * @param secret shared secret to use for encryption
302 * @return NULL on error (should never happen)
303 */
304struct TALER_RefreshLinkEncrypted *
305TALER_refresh_encrypt (const struct TALER_RefreshLinkDecrypted *input,
306 const struct GNUNET_HashCode *secret);
227 307
228 308
229#endif 309#endif
diff --git a/src/mint/mint.h b/src/mint/mint.h
index 3f98b368d..b194be687 100644
--- a/src/mint/mint.h
+++ b/src/mint/mint.h
@@ -117,9 +117,9 @@ struct CollectableBlindcoin
117 117
118struct RefreshSession 118struct RefreshSession
119{ 119{
120 int has_commit_sig;
121 struct GNUNET_CRYPTO_EddsaSignature commit_sig; 120 struct GNUNET_CRYPTO_EddsaSignature commit_sig;
122 struct GNUNET_CRYPTO_EddsaPublicKey session_pub; 121 struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
122 int has_commit_sig;
123 uint16_t num_oldcoins; 123 uint16_t num_oldcoins;
124 uint16_t num_newcoins; 124 uint16_t num_newcoins;
125 uint16_t kappa; 125 uint16_t kappa;
@@ -128,46 +128,33 @@ struct RefreshSession
128}; 128};
129 129
130 130
131#define TALER_REFRESH_SHARED_SECRET_LENGTH (sizeof (struct GNUNET_HashCode)) 131/**
132#define TALER_REFRESH_LINK_LENGTH (sizeof (struct LinkData)) 132 * FIXME
133 133 */
134struct RefreshCommitLink 134struct RefreshCommitLink
135{ 135{
136 struct GNUNET_CRYPTO_EddsaPublicKey session_pub; 136 struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
137 struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; 137 struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub;
138 struct GNUNET_HashCode shared_secret;
138 uint16_t cnc_index; 139 uint16_t cnc_index;
139 uint16_t oldcoin_index; 140 uint16_t oldcoin_index;
140 char shared_secret_enc[sizeof (struct GNUNET_HashCode)];
141};
142
143struct LinkData
144{
145 struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv;
146 struct GNUNET_CRYPTO_rsa_BlindingKey *bkey_enc;
147}; 141};
148 142
149 143
150GNUNET_NETWORK_STRUCT_BEGIN 144/**
151 145 * FIXME
152struct SharedSecretEnc 146 */
153{
154 char data[TALER_REFRESH_SHARED_SECRET_LENGTH];
155};
156
157
158struct LinkDataEnc
159{
160 char data[sizeof (struct LinkData)];
161};
162
163GNUNET_NETWORK_STRUCT_END
164
165struct RefreshCommitCoin 147struct RefreshCommitCoin
166{ 148{
149 /**
150 * Refresh session's public key.
151 */
167 struct GNUNET_CRYPTO_EddsaPublicKey session_pub; 152 struct GNUNET_CRYPTO_EddsaPublicKey session_pub;
168 153
154 struct TALER_RefreshLinkEncrypted refresh_link;
155
169 /** 156 /**
170 * Blinded message to be signed (in envelope). 157 * Blinded message to be signed (in envelope), with @e coin_env_size bytes.
171 */ 158 */
172 char *coin_ev; 159 char *coin_ev;
173 160
@@ -176,22 +163,36 @@ struct RefreshCommitCoin
176 */ 163 */
177 size_t coin_ev_size; 164 size_t coin_ev_size;
178 165
166 /**
167 * FIXME: needed?
168 */
179 uint16_t cnc_index; 169 uint16_t cnc_index;
170
171 /**
172 * FIXME: needed?
173 */
180 uint16_t newcoin_index; 174 uint16_t newcoin_index;
181 char link_enc[sizeof (struct LinkData)]; 175
182}; 176};
183 177
184 178
179/**
180 * FIXME
181 */
185struct KnownCoin 182struct KnownCoin
186{ 183{
187 struct TALER_CoinPublicInfo public_info; 184 struct TALER_CoinPublicInfo public_info;
188 struct TALER_Amount expended_balance; 185
189 int is_refreshed;
190 /** 186 /**
191 * Refreshing session, only valid if 187 * Refreshing session, only valid if
192 * is_refreshed==1. 188 * is_refreshed==1.
193 */ 189 */
194 struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub; 190 struct GNUNET_CRYPTO_EddsaPublicKey refresh_session_pub;
191
192 struct TALER_Amount expended_balance;
193
194 int is_refreshed;
195
195}; 196};
196 197
197 198
@@ -356,11 +357,15 @@ TALER_MINT_config_load (const char *mint_base_dir);
356 357
357 358
358int 359int
359TALER_TALER_DB_extract_amount (PGresult *result, unsigned int row, 360TALER_TALER_DB_extract_amount (PGresult *result,
360 int indices[3], struct TALER_Amount *denom); 361 unsigned int row,
362 int indices[3],
363 struct TALER_Amount *denom);
361 364
362int 365int
363TALER_TALER_DB_extract_amount_nbo (PGresult *result, unsigned int row, 366TALER_TALER_DB_extract_amount_nbo (PGresult *result,
364 int indices[3], struct TALER_AmountNBO *denom_nbo); 367 unsigned int row,
368 int indices[3],
369 struct TALER_AmountNBO *denom_nbo);
365 370
366#endif /* _MINT_H */ 371#endif /* _MINT_H */
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 2fbcb54b4..bb07e2ca3 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -4,6 +4,8 @@ lib_LTLIBRARIES = \
4 libtalerutil.la 4 libtalerutil.la
5 5
6libtalerutil_la_SOURCES = \ 6libtalerutil_la_SOURCES = \
7 amount.c \
8 crypto.c \
7 util.c \ 9 util.c \
8 json.c \ 10 json.c \
9 db.c 11 db.c
diff --git a/src/util/amount.c b/src/util/amount.c
new file mode 100644
index 000000000..8bd899bf5
--- /dev/null
+++ b/src/util/amount.c
@@ -0,0 +1,329 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file amount.c
19 * @brief Common utility functions to deal with units of currency
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 * @author Florian Dold
22 * @author Benedikt Mueller
23 */
24#include "platform.h"
25#include "taler_util.h"
26#include <gnunet/gnunet_common.h>
27#include <gnunet/gnunet_util_lib.h>
28#include <gcrypt.h>
29
30#define AMOUNT_FRAC_BASE 1000000
31
32#define AMOUNT_FRAC_LEN 6
33
34
35/**
36 * Parse money amount description, in the format "A:B.C".
37 *
38 * @param str amount description
39 * @param denom amount to write the result to
40 * @return #GNUNET_OK if the string is a valid amount specification,
41 * #GNUNET_SYSERR if it is invalid.
42 */
43int
44TALER_string_to_amount (const char *str,
45 struct TALER_Amount *denom)
46{
47 unsigned int i; // pos in str
48 int n; // number tmp
49 unsigned int c; // currency pos
50 uint32_t b; // base for suffix
51
52 memset (denom, 0, sizeof (struct TALER_Amount));
53
54 i = n = c = 0;
55
56 while (isspace(str[i]))
57 i++;
58
59 if (0 == str[i])
60 {
61 printf("null before currency\n");
62 return GNUNET_SYSERR;
63 }
64
65 while (str[i] != ':')
66 {
67 if (0 == str[i])
68 {
69 printf("null before colon");
70 return GNUNET_SYSERR;
71 }
72 if (c > 3)
73 {
74 printf("currency too long\n");
75 return GNUNET_SYSERR;
76 }
77 denom->currency[c] = str[i];
78 c++;
79 i++;
80 }
81
82 // skip colon
83 i++;
84
85 if (0 == str[i])
86 {
87 printf("null before value\n");
88 return GNUNET_SYSERR;
89 }
90
91 while (str[i] != '.')
92 {
93 if (0 == str[i])
94 {
95 return GNUNET_OK;
96 }
97 n = str[i] - '0';
98 if (n < 0 || n > 9)
99 {
100 printf("invalid character '%c' before comma at %u\n", (char) n, i);
101 return GNUNET_SYSERR;
102 }
103 denom->value = (denom->value * 10) + n;
104 i++;
105 }
106
107 // skip the dot
108 i++;
109
110 if (0 == str[i])
111 {
112 printf("null after dot");
113 return GNUNET_SYSERR;
114 }
115
116 b = 100000;
117
118 while (0 != str[i])
119 {
120 n = str[i] - '0';
121 if (b == 0 || n < 0 || n > 9)
122 {
123 printf("error after comma");
124 return GNUNET_SYSERR;
125 }
126 denom->fraction += n * b;
127 b /= 10;
128 i++;
129 }
130
131 return GNUNET_OK;
132}
133
134
135/**
136 * FIXME
137 */
138struct TALER_AmountNBO
139TALER_amount_hton (struct TALER_Amount d)
140{
141 struct TALER_AmountNBO dn;
142 dn.value = htonl (d.value);
143 dn.fraction = htonl (d.fraction);
144 memcpy (dn.currency, d.currency, TALER_CURRENCY_LEN);
145
146 return dn;
147}
148
149
150/**
151 * FIXME
152 */
153struct TALER_Amount
154TALER_amount_ntoh (struct TALER_AmountNBO dn)
155{
156 struct TALER_Amount d;
157 d.value = ntohl (dn.value);
158 d.fraction = ntohl (dn.fraction);
159 memcpy (d.currency, dn.currency, sizeof(dn.currency));
160
161 return d;
162}
163
164
165/**
166 * Compare the value/fraction of two amounts. Does not compare the currency,
167 * i.e. comparing amounts with the same value and fraction but different
168 * currency would return 0.
169 *
170 * @param a1 first amount
171 * @param a2 second amount
172 * @return result of the comparison
173 */
174int
175TALER_amount_cmp (struct TALER_Amount a1, struct TALER_Amount a2)
176{
177 a1 = TALER_amount_normalize (a1);
178 a2 = TALER_amount_normalize (a2);
179 if (a1.value == a2.value)
180 {
181 if (a1.fraction < a2.fraction)
182 return -1;
183 if (a1.fraction > a2.fraction)
184 return 1;
185 return 0;
186 }
187 if (a1.value < a2.value)
188 return -1;
189 return 1;
190}
191
192
193/**
194 * Perform saturating subtraction of amounts.
195 *
196 * @param a1 amount to subtract from
197 * @param a2 amount to subtract
198 * @return (a1-a2) or 0 if a2>=a1
199 */
200struct TALER_Amount
201TALER_amount_subtract (struct TALER_Amount a1, struct TALER_Amount a2)
202{
203 a1 = TALER_amount_normalize (a1);
204 a2 = TALER_amount_normalize (a2);
205
206 if (a1.value < a2.value)
207 {
208 a1.value = 0;
209 a1.fraction = 0;
210 return a1;
211 }
212
213 if (a1.fraction < a2.fraction)
214 {
215 if (0 == a1.value)
216 {
217 a1.fraction = 0;
218 return a1;
219 }
220 a1.fraction += AMOUNT_FRAC_BASE;
221 a1.value -= 1;
222 }
223
224 a1.fraction -= a2.fraction;
225 a1.value -= a2.value;
226
227 return a1;
228}
229
230
231/**
232 * Perform saturating addition of amounts.
233 *
234 * @param a1 first amount to add
235 * @param a2 second amount to add
236 * @return sum of a1 and a2
237 */
238struct TALER_Amount
239TALER_amount_add (struct TALER_Amount a1, struct TALER_Amount a2)
240{
241 a1 = TALER_amount_normalize (a1);
242 a2 = TALER_amount_normalize (a2);
243
244 a1.value += a2.value;
245 a1.fraction += a2.fraction;
246
247 if (0 == a1.currency[0])
248 {
249 memcpy (a2.currency, a1.currency, TALER_CURRENCY_LEN);
250 }
251
252 if (0 == a2.currency[0])
253 {
254 memcpy (a1.currency, a2.currency, TALER_CURRENCY_LEN);
255 }
256
257 if (0 != a1.currency[0] && 0 != memcmp (a1.currency, a2.currency, TALER_CURRENCY_LEN))
258 {
259 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "adding mismatching currencies\n");
260 }
261
262 if (a1.value < a2.value)
263 {
264 a1.value = UINT32_MAX;
265 a2.value = UINT32_MAX;
266 return a1;
267 }
268
269 return TALER_amount_normalize (a1);
270}
271
272
273/**
274 * Normalize the given amount.
275 *
276 * @param amout amount to normalize
277 * @return normalized amount
278 */
279struct TALER_Amount
280TALER_amount_normalize (struct TALER_Amount amount)
281{
282 while (amount.value != UINT32_MAX && amount.fraction >= AMOUNT_FRAC_BASE)
283 {
284 amount.fraction -= AMOUNT_FRAC_BASE;
285 amount.value += 1;
286 }
287 return amount;
288}
289
290
291/**
292 * Convert amount to string.
293 *
294 * @param amount amount to convert to string
295 * @return freshly allocated string representation
296 */
297char *
298TALER_amount_to_string (struct TALER_Amount amount)
299{
300 char tail[AMOUNT_FRAC_LEN + 1] = { 0 };
301 char curr[TALER_CURRENCY_LEN + 1] = { 0 };
302 char *result = NULL;
303 int len;
304
305 memcpy (curr, amount.currency, TALER_CURRENCY_LEN);
306
307 amount = TALER_amount_normalize (amount);
308 if (0 != amount.fraction)
309 {
310 unsigned int i;
311 uint32_t n = amount.fraction;
312 for (i = 0; (i < AMOUNT_FRAC_LEN) && (n != 0); i++)
313 {
314 tail[i] = '0' + (n / (AMOUNT_FRAC_BASE / 10));
315 n = (n * 10) % (AMOUNT_FRAC_BASE);
316 }
317 tail[i] = 0;
318 len = GNUNET_asprintf (&result, "%s:%lu.%s", curr, (unsigned long) amount.value, tail);
319 }
320 else
321 {
322 len = GNUNET_asprintf (&result, "%s:%lu", curr, (unsigned long) amount.value);
323 }
324 GNUNET_assert (len > 0);
325 return result;
326}
327
328
329/* end of amount.c */
diff --git a/src/util/crypto.c b/src/util/crypto.c
new file mode 100644
index 000000000..7ff741159
--- /dev/null
+++ b/src/util/crypto.c
@@ -0,0 +1,118 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file crypto.c
19 * @brief Cryptographic utility functions
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 * @author Florian Dold
22 * @author Benedikt Mueller
23 */
24
25#include "platform.h"
26#include "taler_util.h"
27#include <gnunet/gnunet_common.h>
28#include <gnunet/gnunet_util_lib.h>
29#include <gcrypt.h>
30
31#define CURVE "Ed25519"
32
33
34static void
35fatal_error_handler (void *cls, int wtf, const char *msg)
36{
37 LOG_ERROR("Fatal error in Gcrypt: %s\n", msg);
38 abort();
39}
40
41
42/**
43 * Initialize Gcrypt library.
44 */
45void
46TALER_gcrypt_init()
47{
48 gcry_set_fatalerror_handler (&fatal_error_handler, NULL);
49 TALER_assert_as(gcry_check_version(NEED_LIBGCRYPT_VERSION),
50 "libgcrypt version mismatch");
51 /* Disable secure memory. */
52 gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
53 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
54}
55
56
57/**
58 * Derive symmetric key material for refresh operations from
59 * a given shared secret.
60 *
61 * @param secret the shared secret
62 * @param[out] iv set to initialization vector
63 * @param[out] skey set to session key
64 */
65static void
66derive_refresh_key (const struct GNUNET_HashCode *secret,
67 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
68 struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
69{
70 static const char ctx_key[] = "taler-key-skey";
71 static const char ctx_iv[] = "taler-key-iv";
72
73 GNUNET_assert (GNUNET_YES ==
74 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
75 ctx_key, strlen (ctx_key),
76 secret, sizeof (struct GNUNET_HashCode),
77 NULL, 0));
78 GNUNET_assert (GNUNET_YES ==
79 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
80 ctx_iv, strlen (ctx_iv),
81 secret, sizeof (struct GNUNET_HashCode),
82 NULL, 0));
83}
84
85
86int
87TALER_refresh_decrypt (const void *input,
88 size_t input_size,
89 const struct GNUNET_HashCode *secret,
90 void *result)
91{
92 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
93 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
94
95 derive_refresh_key (secret, &iv, &skey);
96
97 return GNUNET_CRYPTO_symmetric_decrypt (input, input_size, &skey, &iv, result);
98}
99
100
101int
102TALER_refresh_encrypt (const void *input,
103 size_t input_size,
104 const struct GNUNET_HashCode *secret,
105 void *result)
106{
107 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
108 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
109
110 derive_refresh_key (secret, &iv, &skey);
111
112 return GNUNET_CRYPTO_symmetric_encrypt (input, input_size, &skey, &iv, result);
113}
114
115
116
117
118/* end of crypto.c */
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 */