aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_crypto_lib.h322
-rw-r--r--src/util/Makefile.am10
-rw-r--r--src/util/crypto_ecc.c430
-rw-r--r--src/util/gnunet-ecc.c246
-rw-r--r--src/util/util.conf3
5 files changed, 714 insertions, 297 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index f73c1ae76..59f1dad78 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -96,11 +96,31 @@ enum GNUNET_CRYPTO_Quality
96 */ 96 */
97#define GNUNET_CRYPTO_HASH_LENGTH 512/8 97#define GNUNET_CRYPTO_HASH_LENGTH 512/8
98 98
99
100/**
101 * FIXME: what is an acceptable value here?
102 * Note: round to multiple of 8 minus 2.
103 */
104#define GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH 510
105
106/**
107 * FIXME: what is an acceptable value here?
108 * Maximum length of the public key (q-point, Q = dP) when encoded.
109 */
110#define GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH 254
111
112
99/** 113/**
100 * The private information of an RSA key pair. 114 * The private information of an RSA key pair.
101 */ 115 */
102struct GNUNET_CRYPTO_RsaPrivateKey; 116struct GNUNET_CRYPTO_RsaPrivateKey;
103 117
118/**
119 * The private information of an ECC private key.
120 */
121struct GNUNET_CRYPTO_EccPrivateKey;
122
123
104GNUNET_NETWORK_STRUCT_BEGIN 124GNUNET_NETWORK_STRUCT_BEGIN
105 125
106/** 126/**
@@ -220,6 +240,102 @@ struct GNUNET_CRYPTO_RsaEncryptedData
220 240
221 241
222/** 242/**
243 * @brief header of what an ECC signature signs
244 * this must be followed by "size - 8" bytes of
245 * the actual signed data
246 */
247struct GNUNET_CRYPTO_EccSignaturePurpose
248{
249 /**
250 * How many bytes does this signature sign?
251 * (including this purpose header); in network
252 * byte order (!).
253 */
254 uint32_t size GNUNET_PACKED;
255
256 /**
257 * What does this signature vouch for? This
258 * must contain a GNUNET_SIGNATURE_PURPOSE_XXX
259 * constant (from gnunet_signatures.h). In
260 * network byte order!
261 */
262 uint32_t purpose GNUNET_PACKED;
263
264};
265
266
267/**
268 * @brief an ECC signature
269 */
270struct GNUNET_CRYPTO_EccSignature
271{
272 /**
273 * Overall size of the encrypted data.
274 */
275 uint16_t size;
276
277 /**
278 * S-expression, padded with zeros.
279 */
280 char sexpr[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
281};
282
283
284/**
285 * Public ECC key (always for NIST P-521) encoded in a format suitable
286 * for network transmission as created using 'gcry_sexp_sprint'.
287 */
288struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
289{
290 /**
291 * Size of the encoding, in network byte order.
292 */
293 uint16_t size;
294
295 /**
296 * Actual length of the q-point binary encoding.
297 */
298 uint16_t len;
299
300 /**
301 * 0-padded q-point in binary encoding (GCRYPT_MPI_FMT_USG).
302 */
303 unsigned char key[GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH];
304};
305
306
307struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded
308{
309 /**
310 * Overall size of the private key.
311 */
312 uint16_t size;
313
314 /* followd by S-expression, opaque to applications */
315
316 /* FIXME: consider defining padding to make this a fixed-size struct */
317
318};
319
320
321/**
322 * ECC Encrypted data.
323 */
324struct GNUNET_CRYPTO_EccEncryptedData
325{
326 /**
327 * Overall size of the encrypted data.
328 */
329 uint16_t size;
330
331 /**
332 * S-expression, padded with zeros.
333 */
334 char encoding[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
335};
336
337
338/**
223 * @brief type for session keys 339 * @brief type for session keys
224 */ 340 */
225struct GNUNET_CRYPTO_AesSessionKey 341struct GNUNET_CRYPTO_AesSessionKey
@@ -1068,6 +1184,212 @@ GNUNET_CRYPTO_rsa_verify (uint32_t purpose,
1068 1184
1069 1185
1070/** 1186/**
1187 * Function called upon completion of 'GNUNET_CRYPTO_ecc_key_create_async'.
1188 *
1189 * @param cls closure
1190 * @param pk NULL on error, otherwise the private key (which must be free'd by the callee)
1191 * @param emsg NULL on success, otherwise an error message
1192 */
1193typedef void (*GNUNET_CRYPTO_EccKeyCallback)(void *cls,
1194 struct GNUNET_CRYPTO_EccPrivateKey *pk,
1195 const char *emsg);
1196
1197
1198/**
1199 * Free memory occupied by ECC key
1200 *
1201 * @param privatekey pointer to the memory to free
1202 */
1203void
1204GNUNET_CRYPTO_ecc_key_free (struct GNUNET_CRYPTO_EccPrivateKey *privatekey);
1205
1206
1207/**
1208 * Extract the public key for the given private key.
1209 *
1210 * @param priv the private key
1211 * @param pub where to write the public key
1212 */
1213void
1214GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey *priv,
1215 struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub);
1216
1217/**
1218 * Convert a public key to a string.
1219 *
1220 * @param pub key to convert
1221 * @return string representing 'pub'
1222 */
1223char *
1224GNUNET_CRYPTO_ecc_public_key_to_string (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub);
1225
1226
1227/**
1228 * Convert a string representing a public key to a public key.
1229 *
1230 * @param enc encoded public key
1231 * @param enclen number of bytes in enc (without 0-terminator)
1232 * @param pub where to store the public key
1233 * @return GNUNET_OK on success
1234 */
1235int
1236GNUNET_CRYPTO_ecc_public_key_from_string (const char *enc,
1237 size_t enclen,
1238 struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub);
1239
1240
1241/**
1242 * Encode the private key in a format suitable for
1243 * storing it into a file.
1244 *
1245 * @param key key to encode
1246 * @return encoding of the private key.
1247 * The first 4 bytes give the size of the array, as usual.
1248 */
1249struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *
1250GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *key);
1251
1252
1253/**
1254 * Decode the private key from the file-format back
1255 * to the "normal", internal format.
1256 *
1257 * @param buf the buffer where the private key data is stored
1258 * @param len the length of the data in 'buffer'
1259 * @return NULL on error
1260 */
1261struct GNUNET_CRYPTO_EccPrivateKey *
1262GNUNET_CRYPTO_ecc_decode_key (const char *buf,
1263 size_t len);
1264
1265
1266/**
1267 * Create a new private key by reading it from a file. If the
1268 * files does not exist, create a new key and write it to the
1269 * file. Caller must free return value. Note that this function
1270 * can not guarantee that another process might not be trying
1271 * the same operation on the same file at the same time.
1272 * If the contents of the file
1273 * are invalid the old file is deleted and a fresh key is
1274 * created.
1275 *
1276 * @return new private key, NULL on error (for example,
1277 * permission denied)
1278 */
1279struct GNUNET_CRYPTO_EccPrivateKey *
1280GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename);
1281
1282
1283/**
1284 * Handle to cancel private key generation and state for the
1285 * key generation operation.
1286 */
1287struct GNUNET_CRYPTO_EccKeyGenerationContext;
1288
1289
1290/**
1291 * Create a new private key by reading it from a file. If the files
1292 * does not exist, create a new key and write it to the file. If the
1293 * contents of the file are invalid the old file is deleted and a
1294 * fresh key is created.
1295 *
1296 * @param filename name of file to use for storage
1297 * @param cont function to call when done (or on errors)
1298 * @param cont_cls closure for 'cont'
1299 * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned)
1300 */
1301struct GNUNET_CRYPTO_EccKeyGenerationContext *
1302GNUNET_CRYPTO_ecc_key_create_start (const char *filename,
1303 GNUNET_CRYPTO_EccKeyCallback cont,
1304 void *cont_cls);
1305
1306
1307/**
1308 * Abort ECC key generation.
1309 *
1310 * @param gc key generation context to abort
1311 */
1312void
1313GNUNET_CRYPTO_ecc_key_create_stop (struct GNUNET_CRYPTO_EccKeyGenerationContext *gc);
1314
1315/**
1316 * Setup a hostkey file for a peer given the name of the
1317 * configuration file (!). This function is used so that
1318 * at a later point code can be certain that reading a
1319 * hostkey is fast (for example in time-dependent testcases).
1320 *
1321 * @param cfg_name name of the configuration file to use
1322 */
1323void
1324GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name);
1325
1326
1327/**
1328 * Encrypt a block with the public key of another host that uses the
1329 * same cipher.
1330 *
1331 * @param block the block to encrypt
1332 * @param size the size of block
1333 * @param publicKey the encoded public key used to encrypt
1334 * @param target where to store the encrypted block
1335 * @returns GNUNET_SYSERR on error, GNUNET_OK if ok
1336 */
1337int
1338GNUNET_CRYPTO_ecc_encrypt (const void *block, size_t size,
1339 const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
1340 *publicKey,
1341 struct GNUNET_CRYPTO_EccEncryptedData *target);
1342
1343
1344/**
1345 * Decrypt a given block with the hostkey.
1346 *
1347 * @param key the key with which to decrypt this block
1348 * @param block the data to decrypt, encoded as returned by encrypt
1349 * @param result pointer to a location where the result can be stored
1350 * @param max the maximum number of bits to store for the result, if
1351 * the decrypted block is bigger, an error is returned
1352 * @return the size of the decrypted block, -1 on error
1353 */
1354ssize_t
1355GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey *key,
1356 const struct GNUNET_CRYPTO_EccEncryptedData *block,
1357 void *result, size_t max);
1358
1359
1360/**
1361 * Sign a given block.
1362 *
1363 * @param key private key to use for the signing
1364 * @param purpose what to sign (size, purpose)
1365 * @param sig where to write the signature
1366 * @return GNUNET_SYSERR on error, GNUNET_OK on success
1367 */
1368int
1369GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *key,
1370 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1371 struct GNUNET_CRYPTO_EccSignature *sig);
1372
1373
1374/**
1375 * Verify signature.
1376 *
1377 * @param purpose what is the purpose that the signature should have?
1378 * @param validate block to validate (size, purpose, data)
1379 * @param sig signature that is being validated
1380 * @param publicKey public key of the signer
1381 * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
1382 */
1383int
1384GNUNET_CRYPTO_ecc_verify (uint32_t purpose,
1385 const struct GNUNET_CRYPTO_EccSignaturePurpose
1386 *validate,
1387 const struct GNUNET_CRYPTO_EccSignature *sig,
1388 const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
1389 *publicKey);
1390
1391
1392/**
1071 * This function should only be called in testcases 1393 * This function should only be called in testcases
1072 * where strong entropy gathering is not desired 1394 * where strong entropy gathering is not desired
1073 * (for example, for hostkey generation). 1395 * (for example, for hostkey generation).
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 28d3d6a3e..e25bb8556 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -124,6 +124,7 @@ bin_PROGRAMS = \
124 gnunet-service-resolver \ 124 gnunet-service-resolver \
125 gnunet-resolver \ 125 gnunet-resolver \
126 gnunet-config \ 126 gnunet-config \
127 gnunet-ecc \
127 gnunet-rsa \ 128 gnunet-rsa \
128 gnunet-uri 129 gnunet-uri
129 130
@@ -155,6 +156,15 @@ gnunet_rsa_DEPENDENCIES = \
155 libgnunetutil.la 156 libgnunetutil.la
156 157
157 158
159gnunet_ecc_SOURCES = \
160 gnunet-ecc.c
161gnunet_ecc_LDADD = \
162 $(top_builddir)/src/util/libgnunetutil.la \
163 $(GN_LIBINTL) -lgcrypt
164gnunet_ecc_DEPENDENCIES = \
165 libgnunetutil.la
166
167
158gnunet_config_SOURCES = \ 168gnunet_config_SOURCES = \
159 gnunet-config.c 169 gnunet-config.c
160gnunet_config_LDADD = \ 170gnunet_config_LDADD = \
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index 1ef1ec7b5..af3fe3359 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -46,103 +46,12 @@
46 46
47#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) 47#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
48 48
49
50/**
51 * FIXME: what is an acceptable value here?
52 */
53#define GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH 64
54
55/**
56 * Length of the q-point (Q = dP) in the public key.
57 * FIXME: double-check that this is right.
58 */
59#define GNUNET_CRYPTO_ECC_PUBLIC_KEY_LENGTH 64
60
61
62/**
63 * @brief an ECC signature
64 */
65struct GNUNET_CRYPTO_EccSignature
66{
67 unsigned char sig[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
68};
69
70
71GNUNET_NETWORK_STRUCT_BEGIN
72
73/**
74 * @brief header of what an ECC signature signs
75 * this must be followed by "size - 8" bytes of
76 * the actual signed data
77 */
78struct GNUNET_CRYPTO_EccSignaturePurpose
79{
80 /**
81 * How many bytes does this signature sign?
82 * (including this purpose header); in network
83 * byte order (!).
84 */
85 uint32_t size GNUNET_PACKED;
86
87 /**
88 * What does this signature vouch for? This
89 * must contain a GNUNET_SIGNATURE_PURPOSE_XXX
90 * constant (from gnunet_signatures.h). In
91 * network byte order!
92 */
93 uint32_t purpose GNUNET_PACKED;
94
95};
96
97
98/** 49/**
99 * Public ECC key (always for NIST P-521) encoded in a format suitable 50 * Log an error message at log-level 'level' that indicates
100 * for network transmission. 51 * a failure of the command 'cmd' with the message given
101 */ 52 * by gcry_strerror(rc).
102struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
103{
104 /**
105 * Size of the encoding, in network byte order.
106 */
107 uint16_t size;
108
109 /**
110 * Actual length of the q-point binary encoding.
111 */
112 uint16_t len;
113
114 /**
115 * 0-padded q-point in binary encoding (GCRYPT_MPI_FMT_USG).
116 */
117 unsigned char key[GNUNET_CRYPTO_ECC_PUBLIC_KEY_LENGTH];
118};
119
120
121struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded
122{
123 /**
124 * Overall size of the private key.
125 */
126 uint16_t size;
127
128 /**
129 * Size of the q and d components of the private key.
130 * Note that the other parameters are from NIST P-521.
131 */
132 uint16_t sizes[2];
133};
134
135
136/**
137 * ECC Encrypted data.
138 */ 53 */
139struct GNUNET_CRYPTO_EccEncryptedData 54#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0);
140{
141 unsigned char encoding[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
142};
143
144GNUNET_NETWORK_STRUCT_END
145
146 55
147 56
148/** 57/**
@@ -159,27 +68,6 @@ struct GNUNET_CRYPTO_EccPrivateKey
159 68
160 69
161/** 70/**
162 * Function called upon completion of 'GNUNET_CRYPTO_ecc_key_create_async'.
163 *
164 * @param cls closure
165 * @param pk NULL on error, otherwise the private key (which must be free'd by the callee)
166 * @param emsg NULL on success, otherwise an error message
167 */
168typedef void (*GNUNET_CRYPTO_EccKeyCallback)(void *cls,
169 struct GNUNET_CRYPTO_EccPrivateKey *pk,
170 const char *emsg);
171
172
173
174/**
175 * Log an error message at log-level 'level' that indicates
176 * a failure of the command 'cmd' with the message given
177 * by gcry_strerror(rc).
178 */
179#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0);
180
181
182/**
183 * If target != size, move target bytes to the 71 * If target != size, move target bytes to the
184 * end of the size-sized buffer and zero out the 72 * end of the size-sized buffer and zero out the
185 * first target-size bytes. 73 * first target-size bytes.
@@ -200,7 +88,8 @@ adjust (unsigned char *buf, size_t size, size_t target)
200 88
201 89
202/** 90/**
203 * Free memory occupied by hostkey 91 * Free memory occupied by ECC key
92 *
204 * @param privatekey pointer to the memory to free 93 * @param privatekey pointer to the memory to free
205 */ 94 */
206void 95void
@@ -292,12 +181,12 @@ GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey *priv
292 rc = key_from_sexp (&skey, priv->sexp, "ecc", "q"); 181 rc = key_from_sexp (&skey, priv->sexp, "ecc", "q");
293 GNUNET_assert (0 == rc); 182 GNUNET_assert (0 == rc);
294 pub->size = htons (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)); 183 pub->size = htons (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
295 size = GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH; 184 size = GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH;
296 GNUNET_assert (0 == 185 GNUNET_assert (0 ==
297 gcry_mpi_print (GCRYMPI_FMT_USG, pub->key, size, &size, 186 gcry_mpi_print (GCRYMPI_FMT_USG, pub->key, size, &size,
298 skey)); 187 skey));
299 pub->len = htons (size); 188 pub->len = htons (size);
300 adjust (&pub->key[0], size, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH); 189 adjust (&pub->key[0], size, GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH);
301 gcry_mpi_release (skey); 190 gcry_mpi_release (skey);
302} 191}
303 192
@@ -407,19 +296,16 @@ decode_public_key (const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *publicK
407 * Encode the private key in a format suitable for 296 * Encode the private key in a format suitable for
408 * storing it into a file. 297 * storing it into a file.
409 * 298 *
410 * @returns encoding of the private key. 299 * @param key key to encode
300 * @return encoding of the private key.
411 * The first 4 bytes give the size of the array, as usual. 301 * The first 4 bytes give the size of the array, as usual.
412 */ 302 */
413struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded * 303struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *
414GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *hostkey) 304GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *key)
415{ 305{
416 struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *retval; 306 struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *retval;
417 gcry_mpi_t pkv[2]; 307 char buf[65536];
418 void *pbu[2]; 308 uint16_t be;
419 size_t sizes[2];
420 size_t off;
421 int rc;
422 unsigned int i;
423 size_t size; 309 size_t size;
424 310
425#if EXTRA_CHECKS 311#if EXTRA_CHECKS
@@ -429,43 +315,20 @@ GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *hostkey)
429 return NULL; 315 return NULL;
430 } 316 }
431#endif 317#endif
432 318 size = gcry_sexp_sprint (key->sexp,
433 memset (pkv, 0, sizeof (gcry_mpi_t) * 2); 319 GCRYSEXP_FMT_DEFAULT,
434 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "qd"); 320 &buf[2], sizeof (buf) - sizeof (uint16_t));
435 if (rc) 321 if (0 == size)
436 rc = key_from_sexp (pkv, hostkey->sexp, "ecc", "qd");
437 GNUNET_assert (0 == rc);
438 size = sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded);
439 for (i=0;i<2;i++)
440 { 322 {
441 if (NULL != pkv[i]) 323 GNUNET_break (0);
442 { 324 return NULL;
443 GNUNET_assert (0 ==
444 gcry_mpi_aprint (GCRYMPI_FMT_USG,
445 (unsigned char **) &pbu[i], &sizes[i],
446 pkv[i]));
447 size += sizes[i];
448 }
449 else
450 {
451 pbu[i] = NULL;
452 sizes[i] = 0;
453 }
454 } 325 }
455 GNUNET_assert (size < 65536); 326 GNUNET_assert (size < 65536 - sizeof (uint16_t));
327 be = htons ((uint16_t) size);
328 memcpy (buf, &be, sizeof (be));
329 size += sizeof (be);
456 retval = GNUNET_malloc (size); 330 retval = GNUNET_malloc (size);
457 retval->size = htons (size); 331 memcpy (retval, buf, size);
458 off = 0;
459 for (i=0;i<2;i++)
460 {
461 retval->sizes[i] = htons (sizes[0]);
462 memcpy (&((char *) (&retval[1]))[off], pbu[i], sizes[i]);
463 off += sizes[i];
464 if (NULL != pkv[i])
465 gcry_mpi_release (pkv[i]);
466 if (NULL != pbu[i])
467 free (pbu[i]);
468 }
469 return retval; 332 return retval;
470} 333}
471 334
@@ -479,61 +342,35 @@ GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *hostkey)
479 * @return NULL on error 342 * @return NULL on error
480 */ 343 */
481struct GNUNET_CRYPTO_EccPrivateKey * 344struct GNUNET_CRYPTO_EccPrivateKey *
482GNUNET_CRYPTO_ecc_decode_key (const char *buf, uint16_t len) 345GNUNET_CRYPTO_ecc_decode_key (const char *buf,
346 size_t len)
483{ 347{
484 struct GNUNET_CRYPTO_EccPrivateKey *ret; 348 struct GNUNET_CRYPTO_EccPrivateKey *ret;
485 const struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *encoding = 349 uint16_t be;
486 (const struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *) buf; 350 gcry_sexp_t sexp;
487 gcry_sexp_t res;
488 gcry_mpi_t q;
489 gcry_mpi_t d;
490 int rc; 351 int rc;
491 size_t size;
492 size_t pos;
493 uint16_t enc_len;
494 size_t erroff; 352 size_t erroff;
495 353
496 enc_len = ntohs (encoding->size); 354 if (len < sizeof (uint16_t))
497 if (len != enc_len)
498 return NULL; 355 return NULL;
499 pos = 0; 356 memcpy (&be, buf, sizeof (be));
500 size = ntohs (encoding->sizes[0]); 357 if (len != ntohs (be))
501 rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG,
502 &((const unsigned char *) (&encoding[1]))[pos], size,
503 &size);
504 pos += ntohs (encoding->sizes[0]);
505 if (0 != rc)
506 {
507 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
508 return NULL; 358 return NULL;
509 } 359 if (0 != (rc = gcry_sexp_sscan (&sexp,
510 size = ntohs (encoding->sizes[1]); 360 &erroff,
511 rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG, 361 &buf[2],
512 &((const unsigned char *) (&encoding[1]))[pos], size, 362 len - sizeof (uint16_t))))
513 &size);
514 pos += ntohs (encoding->sizes[1]);
515 if (0 != rc)
516 { 363 {
517 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); 364 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_scan", rc);
518 gcry_mpi_release (d);
519 return NULL; 365 return NULL;
520 } 366 }
521 rc = gcry_sexp_build (&res, &erroff, 367 if (0 != (rc = gcry_pk_testkey (sexp)))
522 "(private-key(ecc(q %m)(d %m)(curve \"" CURVE "\")))",
523 q, d);
524 gcry_mpi_release (q);
525 gcry_mpi_release (d);
526 if (0 != rc)
527 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
528#if EXTRA_CHECKS
529 if (0 != (rc = gcry_pk_testkey (res)))
530 { 368 {
531 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); 369 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
532 return NULL; 370 return NULL;
533 } 371 }
534#endif
535 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey)); 372 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey));
536 ret->sexp = res; 373 ret->sexp = sexp;
537 return ret; 374 return ret;
538} 375}
539 376
@@ -574,10 +411,8 @@ static struct GNUNET_CRYPTO_EccPrivateKey *
574try_read_key (const char *filename) 411try_read_key (const char *filename)
575{ 412{
576 struct GNUNET_CRYPTO_EccPrivateKey *ret; 413 struct GNUNET_CRYPTO_EccPrivateKey *ret;
577 struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc;
578 struct GNUNET_DISK_FileHandle *fd; 414 struct GNUNET_DISK_FileHandle *fd;
579 OFF_T fs; 415 OFF_T fs;
580 uint16_t len;
581 416
582 if (GNUNET_YES != GNUNET_DISK_file_test (filename)) 417 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
583 return NULL; 418 return NULL;
@@ -611,26 +446,22 @@ try_read_key (const char *filename)
611 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); 446 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
612 return NULL; 447 return NULL;
613 } 448 }
614
615 enc = GNUNET_malloc (fs);
616 GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
617 len = ntohs (enc->size);
618 ret = NULL;
619 if ((len != fs) ||
620 (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, len))))
621 { 449 {
622 LOG (GNUNET_ERROR_TYPE_ERROR, 450 char enc[fs];
623 _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"),
624 filename,
625 (unsigned long long) fs);
626 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
627 if (0 != UNLINK (filename))
628 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
629 GNUNET_free (enc);
630 return NULL;
631 }
632 GNUNET_free (enc);
633 451
452 GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
453 if (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, fs)))
454 {
455 LOG (GNUNET_ERROR_TYPE_ERROR,
456 _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"),
457 filename,
458 (unsigned long long) fs);
459 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
460 if (0 != UNLINK (filename))
461 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
462 return NULL;
463 }
464 }
634 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); 465 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
635 return ret; 466 return ret;
636} 467}
@@ -1084,7 +915,7 @@ GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name)
1084 cfg = GNUNET_CONFIGURATION_create (); 915 cfg = GNUNET_CONFIGURATION_create ();
1085 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name); 916 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1086 if (GNUNET_OK == 917 if (GNUNET_OK ==
1087 GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", &fn)) 918 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
1088 { 919 {
1089 pk = GNUNET_CRYPTO_ecc_key_create_from_file (fn); 920 pk = GNUNET_CRYPTO_ecc_key_create_from_file (fn);
1090 if (NULL != pk) 921 if (NULL != pk)
@@ -1115,7 +946,6 @@ GNUNET_CRYPTO_ecc_encrypt (const void *block, size_t size,
1115 gcry_sexp_t data; 946 gcry_sexp_t data;
1116 gcry_sexp_t psexp; 947 gcry_sexp_t psexp;
1117 gcry_mpi_t val; 948 gcry_mpi_t val;
1118 gcry_mpi_t rval;
1119 size_t isize; 949 size_t isize;
1120 size_t erroff; 950 size_t erroff;
1121 951
@@ -1132,16 +962,18 @@ GNUNET_CRYPTO_ecc_encrypt (const void *block, size_t size,
1132 GNUNET_assert (0 == gcry_pk_encrypt (&result, data, psexp)); 962 GNUNET_assert (0 == gcry_pk_encrypt (&result, data, psexp));
1133 gcry_sexp_release (data); 963 gcry_sexp_release (data);
1134 gcry_sexp_release (psexp); 964 gcry_sexp_release (psexp);
1135 965 isize = gcry_sexp_sprint (result,
1136 GNUNET_assert (0 == key_from_sexp (&rval, result, "ecc", "a")); 966 GCRYSEXP_FMT_DEFAULT,
1137 gcry_sexp_release (result); 967 target->encoding,
1138 isize = sizeof (struct GNUNET_CRYPTO_EccEncryptedData); 968 GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH);
1139 GNUNET_assert (0 == 969 if (0 == isize)
1140 gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) target, 970 {
1141 isize, &isize, rval)); 971 GNUNET_break (0);
1142 gcry_mpi_release (rval); 972 return GNUNET_SYSERR;
1143 adjust (&target->encoding[0], isize, 973 }
1144 sizeof (struct GNUNET_CRYPTO_EccEncryptedData)); 974 target->size = htons ((uint16_t) isize);
975 /* padd with zeros */
976 memset (&target->encoding[isize], 0, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - isize);
1145 return GNUNET_OK; 977 return GNUNET_OK;
1146} 978}
1147 979
@@ -1157,8 +989,8 @@ GNUNET_CRYPTO_ecc_encrypt (const void *block, size_t size,
1157 * @return the size of the decrypted block, -1 on error 989 * @return the size of the decrypted block, -1 on error
1158 */ 990 */
1159ssize_t 991ssize_t
1160GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey * key, 992GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey *key,
1161 const struct GNUNET_CRYPTO_EccEncryptedData * block, 993 const struct GNUNET_CRYPTO_EccEncryptedData *block,
1162 void *result, size_t max) 994 void *result, size_t max)
1163{ 995{
1164 gcry_sexp_t resultsexp; 996 gcry_sexp_t resultsexp;
@@ -1167,19 +999,15 @@ GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey * key,
1167 size_t size; 999 size_t size;
1168 gcry_mpi_t val; 1000 gcry_mpi_t val;
1169 unsigned char *endp; 1001 unsigned char *endp;
1170 unsigned char *tmp;
1171 1002
1172#if EXTRA_CHECKS 1003#if EXTRA_CHECKS
1173 GNUNET_assert (0 == gcry_pk_testkey (key->sexp)); 1004 GNUNET_assert (0 == gcry_pk_testkey (key->sexp));
1174#endif 1005#endif
1175 size = sizeof (struct GNUNET_CRYPTO_EccEncryptedData); 1006 size = ntohs (block->size);
1176 GNUNET_assert (0 ==
1177 gcry_mpi_scan (&val, GCRYMPI_FMT_USG, &block->encoding[0],
1178 size, &size));
1179 GNUNET_assert (0 == 1007 GNUNET_assert (0 ==
1180 gcry_sexp_build (&data, &erroff, "(enc-val(flags)(ecc(a %m)))", 1008 gcry_sexp_sscan (&data,
1181 val)); 1009 &erroff,
1182 gcry_mpi_release (val); 1010 block->encoding, size));
1183 GNUNET_assert (0 == gcry_pk_decrypt (&resultsexp, data, key->sexp)); 1011 GNUNET_assert (0 == gcry_pk_decrypt (&resultsexp, data, key->sexp));
1184 gcry_sexp_release (data); 1012 gcry_sexp_release (data);
1185 /* resultsexp has format "(value %m)" */ 1013 /* resultsexp has format "(value %m)" */
@@ -1187,19 +1015,54 @@ GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey * key,
1187 (val = gcry_sexp_nth_mpi (resultsexp, 1, GCRYMPI_FMT_USG))); 1015 (val = gcry_sexp_nth_mpi (resultsexp, 1, GCRYMPI_FMT_USG)));
1188 gcry_sexp_release (resultsexp); 1016 gcry_sexp_release (resultsexp);
1189 size = max + GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH * 2; 1017 size = max + GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH * 2;
1190 tmp = GNUNET_malloc (size); 1018 {
1191 GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG, tmp, size, &size, val)); 1019 unsigned char tmp[size];
1192 gcry_mpi_release (val); 1020
1193 endp = tmp; 1021 GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG, tmp, size, &size, val));
1194 endp += (size - max); 1022 gcry_mpi_release (val);
1195 size = max; 1023 endp = tmp;
1196 memcpy (result, endp, size); 1024 endp += (size - max);
1197 GNUNET_free (tmp); 1025 size = max;
1026 memcpy (result, endp, size);
1027 }
1198 return size; 1028 return size;
1199} 1029}
1200 1030
1201 1031
1202/** 1032/**
1033 * Convert the data specified in the given purpose argument to an
1034 * S-expression suitable for signature operations.
1035 *
1036 * @param purpose data to convert
1037 * @return converted s-expression
1038 */
1039static gcry_sexp_t
1040data_to_pkcs1 (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1041{
1042 struct GNUNET_HashCode hc;
1043 size_t bufSize;
1044 gcry_sexp_t data;
1045
1046 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1047#define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))"
1048 bufSize = strlen (FORMATSTRING) + 1;
1049 {
1050 char buff[bufSize];
1051
1052 memcpy (buff, FORMATSTRING, bufSize);
1053 memcpy (&buff
1054 [bufSize -
1055 strlen
1056 ("0123456789012345678901234567890123456789012345678901234567890123))")
1057 - 1], &hc, sizeof (struct GNUNET_HashCode));
1058 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1059 }
1060#undef FORMATSTRING
1061 return data;
1062}
1063
1064
1065/**
1203 * Sign a given block. 1066 * Sign a given block.
1204 * 1067 *
1205 * @param key private key to use for the signing 1068 * @param key private key to use for the signing
@@ -1215,33 +1078,23 @@ GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *key,
1215 gcry_sexp_t result; 1078 gcry_sexp_t result;
1216 gcry_sexp_t data; 1079 gcry_sexp_t data;
1217 size_t ssize; 1080 size_t ssize;
1218 gcry_mpi_t rval;
1219 struct GNUNET_HashCode hc;
1220 char *buff;
1221 int bufSize;
1222 1081
1223 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc); 1082 data = data_to_pkcs1 (purpose);
1224#define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))"
1225 bufSize = strlen (FORMATSTRING) + 1;
1226 buff = GNUNET_malloc (bufSize);
1227 memcpy (buff, FORMATSTRING, bufSize);
1228 memcpy (&buff
1229 [bufSize -
1230 strlen
1231 ("0123456789012345678901234567890123456789012345678901234567890123))")
1232 - 1], &hc, sizeof (struct GNUNET_HashCode));
1233 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1234 GNUNET_free (buff);
1235 GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp)); 1083 GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp));
1236 gcry_sexp_release (data); 1084 gcry_sexp_release (data);
1237 GNUNET_assert (0 == key_from_sexp (&rval, result, "ecc", "s")); 1085 ssize = gcry_sexp_sprint (result,
1086 GCRYSEXP_FMT_DEFAULT,
1087 sig->sexpr,
1088 GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH);
1089 if (0 == ssize)
1090 {
1091 GNUNET_break (0);
1092 return GNUNET_SYSERR;
1093 }
1094 sig->size = htons ((uint16_t) ssize);
1095 /* padd with zeros */
1096 memset (&sig->sexpr[ssize], 0, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - ssize);
1238 gcry_sexp_release (result); 1097 gcry_sexp_release (result);
1239 ssize = sizeof (struct GNUNET_CRYPTO_EccSignature);
1240 GNUNET_assert (0 ==
1241 gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) sig, ssize,
1242 &ssize, rval));
1243 gcry_mpi_release (rval);
1244 adjust (sig->sig, ssize, sizeof (struct GNUNET_CRYPTO_EccSignature));
1245 return GNUNET_OK; 1098 return GNUNET_OK;
1246} 1099}
1247 1100
@@ -1266,35 +1119,18 @@ GNUNET_CRYPTO_ecc_verify (uint32_t purpose,
1266 gcry_sexp_t data; 1119 gcry_sexp_t data;
1267 gcry_sexp_t sigdata; 1120 gcry_sexp_t sigdata;
1268 size_t size; 1121 size_t size;
1269 gcry_mpi_t val;
1270 gcry_sexp_t psexp; 1122 gcry_sexp_t psexp;
1271 struct GNUNET_HashCode hc;
1272 char *buff;
1273 int bufSize;
1274 size_t erroff; 1123 size_t erroff;
1275 int rc; 1124 int rc;
1276 1125
1277 if (purpose != ntohl (validate->purpose)) 1126 if (purpose != ntohl (validate->purpose))
1278 return GNUNET_SYSERR; /* purpose mismatch */ 1127 return GNUNET_SYSERR; /* purpose mismatch */
1279 GNUNET_CRYPTO_hash (validate, ntohl (validate->size), &hc); 1128 size = ntohs (sig->size);
1280 size = sizeof (struct GNUNET_CRYPTO_EccSignature); 1129 if (size > GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - sizeof (uint16_t))
1130 return GNUNET_SYSERR; /* size out of range */
1131 data = data_to_pkcs1 (validate);
1281 GNUNET_assert (0 == 1132 GNUNET_assert (0 ==
1282 gcry_mpi_scan (&val, GCRYMPI_FMT_USG, 1133 gcry_sexp_sscan (&sigdata, &erroff, sig->sexpr, size));
1283 (const unsigned char *) sig, size, &size));
1284 GNUNET_assert (0 ==
1285 gcry_sexp_build (&sigdata, &erroff, "(sig-val(ecc(s %m)))",
1286 val));
1287 gcry_mpi_release (val);
1288 bufSize = strlen (FORMATSTRING) + 1;
1289 buff = GNUNET_malloc (bufSize);
1290 memcpy (buff, FORMATSTRING, bufSize);
1291 memcpy (&buff
1292 [strlen (FORMATSTRING) -
1293 strlen
1294 ("0123456789012345678901234567890123456789012345678901234567890123))")],
1295 &hc, sizeof (struct GNUNET_HashCode));
1296 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1297 GNUNET_free (buff);
1298 if (! (psexp = decode_public_key (publicKey))) 1134 if (! (psexp = decode_public_key (publicKey)))
1299 { 1135 {
1300 gcry_sexp_release (data); 1136 gcry_sexp_release (data);
@@ -1305,7 +1141,7 @@ GNUNET_CRYPTO_ecc_verify (uint32_t purpose,
1305 gcry_sexp_release (psexp); 1141 gcry_sexp_release (psexp);
1306 gcry_sexp_release (data); 1142 gcry_sexp_release (data);
1307 gcry_sexp_release (sigdata); 1143 gcry_sexp_release (sigdata);
1308 if (rc) 1144 if (0 != rc)
1309 { 1145 {
1310 LOG (GNUNET_ERROR_TYPE_WARNING, 1146 LOG (GNUNET_ERROR_TYPE_WARNING,
1311 _("ECC signature verification failed at %s:%d: %s\n"), __FILE__, 1147 _("ECC signature verification failed at %s:%d: %s\n"), __FILE__,
diff --git a/src/util/gnunet-ecc.c b/src/util/gnunet-ecc.c
new file mode 100644
index 000000000..f966763a8
--- /dev/null
+++ b/src/util/gnunet-ecc.c
@@ -0,0 +1,246 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file util/gnunet-ecc.c
23 * @brief tool to manipulate ECC key files
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib-new.h"
29#include <gcrypt.h>
30
31
32/**
33 * Flag for printing public key.
34 */
35static int print_public_key;
36
37/**
38 * Flag for printing hash of public key.
39 */
40static int print_peer_identity;
41
42/**
43 * Flag for printing short hash of public key.
44 */
45static int print_short_identity;
46
47/**
48 * Use weak random number generator for key generation.
49 */
50static int weak_random;
51
52/**
53 * Option set to create a bunch of keys at once.
54 */
55static unsigned int make_keys;
56
57/**
58 * The private information of an ECC key pair.
59 * NOTE: this must match the definition in crypto_ksk.c and crypto_ecc.c!
60 */
61struct GNUNET_CRYPTO_EccPrivateKey
62{
63 gcry_sexp_t sexp;
64};
65
66
67/**
68 * Create a new private key. Caller must free return value.
69 *
70 * @return fresh private key
71 */
72static struct GNUNET_CRYPTO_EccPrivateKey *
73ecc_key_create ()
74{
75 struct GNUNET_CRYPTO_EccPrivateKey *ret;
76 gcry_sexp_t s_key;
77 gcry_sexp_t s_keyparam;
78
79 GNUNET_assert (0 ==
80 gcry_sexp_build (&s_keyparam, NULL,
81 "(genkey(ecc(nbits %d)(ecc-use-e 3:257)))",
82 2048));
83 GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam));
84 gcry_sexp_release (s_keyparam);
85#if EXTRA_CHECKS
86 GNUNET_assert (0 == gcry_pk_testkey (s_key));
87#endif
88 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey));
89 ret->sexp = s_key;
90 return ret;
91}
92
93
94/**
95 * Create a flat file with a large number of key pairs for testing.
96 */
97static void
98create_keys (const char *fn)
99{
100 FILE *f;
101 struct GNUNET_CRYPTO_EccPrivateKey *pk;
102 struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc;
103
104 if (NULL == (f = fopen (fn, "w+")))
105 {
106 fprintf (stderr,
107 _("Failed to open `%s': %s\n"),
108 fn,
109 STRERROR (errno));
110 return;
111 }
112 fprintf (stderr,
113 _("Generating %u keys, please wait"),
114 make_keys);
115 while (0 < make_keys--)
116 {
117 fprintf (stderr,
118 ".");
119 if (NULL == (pk = ecc_key_create ()))
120 {
121 GNUNET_break (0);
122 break;
123 }
124 enc = GNUNET_CRYPTO_ecc_encode_key (pk);
125 if (htons (enc->size) != fwrite (enc, 1, htons (enc->size), f))
126 {
127 fprintf (stderr,
128 _("\nFailed to write to `%s': %s\n"),
129 fn,
130 STRERROR (errno));
131 GNUNET_CRYPTO_ecc_key_free (pk);
132 GNUNET_free (enc);
133 break;
134 }
135 GNUNET_CRYPTO_ecc_key_free (pk);
136 GNUNET_free (enc);
137 }
138 if (0 == make_keys)
139 fprintf (stderr,
140 _("Finished!\n"));
141 fclose (f);
142}
143
144
145/**
146 * Main function that will be run by the scheduler.
147 *
148 * @param cls closure
149 * @param args remaining command-line arguments
150 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
151 * @param cfg configuration
152 */
153static void
154run (void *cls, char *const *args, const char *cfgfile,
155 const struct GNUNET_CONFIGURATION_Handle *cfg)
156{
157 struct GNUNET_CRYPTO_EccPrivateKey *pk;
158 struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub;
159 struct GNUNET_PeerIdentity pid;
160
161 if (NULL == args[0])
162 {
163 fprintf (stderr, _("No hostkey file specified on command line\n"));
164 return;
165 }
166 if (0 != weak_random)
167 GNUNET_CRYPTO_random_disable_entropy_gathering ();
168 if (make_keys > 0)
169 {
170 create_keys (args[0]);
171 return;
172 }
173 pk = GNUNET_CRYPTO_ecc_key_create_from_file (args[0]);
174 if (NULL == pk)
175 return;
176 if (print_public_key)
177 {
178 char *s;
179
180 GNUNET_CRYPTO_ecc_key_get_public (pk, &pub);
181 s = GNUNET_CRYPTO_ecc_public_key_to_string (&pub);
182 fprintf (stdout, "%s\n", s);
183 GNUNET_free (s);
184 }
185 if (print_peer_identity)
186 {
187 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
188
189 GNUNET_CRYPTO_ecc_key_get_public (pk, &pub);
190 GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
191 GNUNET_CRYPTO_hash_to_enc (&pid.hashPubKey, &enc);
192 fprintf (stdout, "%s\n", enc.encoding);
193 }
194 if (print_short_identity)
195 {
196 struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
197 struct GNUNET_CRYPTO_ShortHashCode sh;
198
199 GNUNET_CRYPTO_ecc_key_get_public (pk, &pub);
200 GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &sh);
201 GNUNET_CRYPTO_short_hash_to_enc (&sh, &enc);
202 fprintf (stdout, "%s\n", enc.short_encoding);
203 }
204 GNUNET_CRYPTO_ecc_key_free (pk);
205}
206
207
208/**
209 * Program to manipulate ECC key files.
210 *
211 * @param argc number of arguments from the command line
212 * @param argv command line arguments
213 * @return 0 ok, 1 on error
214 */
215int
216main (int argc, char *const *argv)
217{
218 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
219 { 'g', "generate-keys", "COUNT",
220 gettext_noop ("create COUNT public-private key pairs (for testing)"),
221 1, &GNUNET_GETOPT_set_uint, &make_keys },
222 { 'p', "print-public-key", NULL,
223 gettext_noop ("print the public key in ASCII format"),
224 0, &GNUNET_GETOPT_set_one, &print_public_key },
225 { 'P', "print-peer-identity", NULL,
226 gettext_noop ("print the hash of the public key in ASCII format"),
227 0, &GNUNET_GETOPT_set_one, &print_peer_identity },
228 { 's', "print-short-identity", NULL,
229 gettext_noop ("print the short hash of the public key in ASCII format"),
230 0, &GNUNET_GETOPT_set_one, &print_short_identity },
231 { 'w', "weak-random", NULL,
232 gettext_noop ("use insecure, weak random number generator for key generation (for testing only)"),
233 0, &GNUNET_GETOPT_set_one, &weak_random },
234 GNUNET_GETOPT_OPTION_END
235 };
236
237 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
238 return 2;
239
240 return (GNUNET_OK ==
241 GNUNET_PROGRAM_run (argc, argv, "gnunet-ecc [OPTIONS] keyfile",
242 gettext_noop ("Manipulate GNUnet private ECC key files"),
243 options, &run, NULL)) ? 0 : 1;
244}
245
246/* end of gnunet-ecc.c */
diff --git a/src/util/util.conf b/src/util/util.conf
index f3d301e48..ea8ddc071 100644
--- a/src/util/util.conf
+++ b/src/util/util.conf
@@ -9,6 +9,9 @@ SERVICEHOME = ~/.gnunet/
9[gnunetd] 9[gnunetd]
10HOSTKEY = $SERVICEHOME/.hostkey 10HOSTKEY = $SERVICEHOME/.hostkey
11 11
12[PEER]
13PRIVATE_KEY = $SERVICEHOME/private.ecc
14
12[client] 15[client]
13HOME = $SERVICEHOME 16HOME = $SERVICEHOME
14 17