[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r24381 - in gnunet/src: include util
From: |
gnunet |
Subject: |
[GNUnet-SVN] r24381 - in gnunet/src: include util |
Date: |
Wed, 17 Oct 2012 21:35:13 +0200 |
Author: grothoff
Date: 2012-10-17 21:35:13 +0200 (Wed, 17 Oct 2012)
New Revision: 24381
Added:
gnunet/src/util/gnunet-ecc.c
Modified:
gnunet/src/include/gnunet_crypto_lib.h
gnunet/src/util/Makefile.am
gnunet/src/util/crypto_ecc.c
gnunet/src/util/util.conf
Log:
-fixing obvious ecc issues, adding gnunet-ecc based on gnunet-rsa
Modified: gnunet/src/include/gnunet_crypto_lib.h
===================================================================
--- gnunet/src/include/gnunet_crypto_lib.h 2012-10-17 19:28:54 UTC (rev
24380)
+++ gnunet/src/include/gnunet_crypto_lib.h 2012-10-17 19:35:13 UTC (rev
24381)
@@ -96,11 +96,31 @@
*/
#define GNUNET_CRYPTO_HASH_LENGTH 512/8
+
/**
+ * FIXME: what is an acceptable value here?
+ * Note: round to multiple of 8 minus 2.
+ */
+#define GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH 510
+
+/**
+ * FIXME: what is an acceptable value here?
+ * Maximum length of the public key (q-point, Q = dP) when encoded.
+ */
+#define GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH 254
+
+
+/**
* The private information of an RSA key pair.
*/
struct GNUNET_CRYPTO_RsaPrivateKey;
+/**
+ * The private information of an ECC private key.
+ */
+struct GNUNET_CRYPTO_EccPrivateKey;
+
+
GNUNET_NETWORK_STRUCT_BEGIN
/**
@@ -220,6 +240,102 @@
/**
+ * @brief header of what an ECC signature signs
+ * this must be followed by "size - 8" bytes of
+ * the actual signed data
+ */
+struct GNUNET_CRYPTO_EccSignaturePurpose
+{
+ /**
+ * How many bytes does this signature sign?
+ * (including this purpose header); in network
+ * byte order (!).
+ */
+ uint32_t size GNUNET_PACKED;
+
+ /**
+ * What does this signature vouch for? This
+ * must contain a GNUNET_SIGNATURE_PURPOSE_XXX
+ * constant (from gnunet_signatures.h). In
+ * network byte order!
+ */
+ uint32_t purpose GNUNET_PACKED;
+
+};
+
+
+/**
+ * @brief an ECC signature
+ */
+struct GNUNET_CRYPTO_EccSignature
+{
+ /**
+ * Overall size of the encrypted data.
+ */
+ uint16_t size;
+
+ /**
+ * S-expression, padded with zeros.
+ */
+ char sexpr[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
+};
+
+
+/**
+ * Public ECC key (always for NIST P-521) encoded in a format suitable
+ * for network transmission as created using 'gcry_sexp_sprint'.
+ */
+struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
+{
+ /**
+ * Size of the encoding, in network byte order.
+ */
+ uint16_t size;
+
+ /**
+ * Actual length of the q-point binary encoding.
+ */
+ uint16_t len;
+
+ /**
+ * 0-padded q-point in binary encoding (GCRYPT_MPI_FMT_USG).
+ */
+ unsigned char key[GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH];
+};
+
+
+struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded
+{
+ /**
+ * Overall size of the private key.
+ */
+ uint16_t size;
+
+ /* followd by S-expression, opaque to applications */
+
+ /* FIXME: consider defining padding to make this a fixed-size struct */
+
+};
+
+
+/**
+ * ECC Encrypted data.
+ */
+struct GNUNET_CRYPTO_EccEncryptedData
+{
+ /**
+ * Overall size of the encrypted data.
+ */
+ uint16_t size;
+
+ /**
+ * S-expression, padded with zeros.
+ */
+ char encoding[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
+};
+
+
+/**
* @brief type for session keys
*/
struct GNUNET_CRYPTO_AesSessionKey
@@ -1068,6 +1184,212 @@
/**
+ * Function called upon completion of 'GNUNET_CRYPTO_ecc_key_create_async'.
+ *
+ * @param cls closure
+ * @param pk NULL on error, otherwise the private key (which must be free'd by
the callee)
+ * @param emsg NULL on success, otherwise an error message
+ */
+typedef void (*GNUNET_CRYPTO_EccKeyCallback)(void *cls,
+ struct GNUNET_CRYPTO_EccPrivateKey
*pk,
+ const char *emsg);
+
+
+/**
+ * Free memory occupied by ECC key
+ *
+ * @param privatekey pointer to the memory to free
+ */
+void
+GNUNET_CRYPTO_ecc_key_free (struct GNUNET_CRYPTO_EccPrivateKey *privatekey);
+
+
+/**
+ * Extract the public key for the given private key.
+ *
+ * @param priv the private key
+ * @param pub where to write the public key
+ */
+void
+GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey
*priv,
+ struct
GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub);
+
+/**
+ * Convert a public key to a string.
+ *
+ * @param pub key to convert
+ * @return string representing 'pub'
+ */
+char *
+GNUNET_CRYPTO_ecc_public_key_to_string (struct
GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub);
+
+
+/**
+ * Convert a string representing a public key to a public key.
+ *
+ * @param enc encoded public key
+ * @param enclen number of bytes in enc (without 0-terminator)
+ * @param pub where to store the public key
+ * @return GNUNET_OK on success
+ */
+int
+GNUNET_CRYPTO_ecc_public_key_from_string (const char *enc,
+ size_t enclen,
+ struct
GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub);
+
+
+/**
+ * Encode the private key in a format suitable for
+ * storing it into a file.
+ *
+ * @param key key to encode
+ * @return encoding of the private key.
+ * The first 4 bytes give the size of the array, as usual.
+ */
+struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *
+GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *key);
+
+
+/**
+ * Decode the private key from the file-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the private key data is stored
+ * @param len the length of the data in 'buffer'
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_EccPrivateKey *
+GNUNET_CRYPTO_ecc_decode_key (const char *buf,
+ size_t len);
+
+
+/**
+ * Create a new private key by reading it from a file. If the
+ * files does not exist, create a new key and write it to the
+ * file. Caller must free return value. Note that this function
+ * can not guarantee that another process might not be trying
+ * the same operation on the same file at the same time.
+ * If the contents of the file
+ * are invalid the old file is deleted and a fresh key is
+ * created.
+ *
+ * @return new private key, NULL on error (for example,
+ * permission denied)
+ */
+struct GNUNET_CRYPTO_EccPrivateKey *
+GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename);
+
+
+/**
+ * Handle to cancel private key generation and state for the
+ * key generation operation.
+ */
+struct GNUNET_CRYPTO_EccKeyGenerationContext;
+
+
+/**
+ * Create a new private key by reading it from a file. If the files
+ * does not exist, create a new key and write it to the file. If the
+ * contents of the file are invalid the old file is deleted and a
+ * fresh key is created.
+ *
+ * @param filename name of file to use for storage
+ * @param cont function to call when done (or on errors)
+ * @param cont_cls closure for 'cont'
+ * @return handle to abort operation, NULL on fatal errors (cont will not be
called if NULL is returned)
+ */
+struct GNUNET_CRYPTO_EccKeyGenerationContext *
+GNUNET_CRYPTO_ecc_key_create_start (const char *filename,
+ GNUNET_CRYPTO_EccKeyCallback cont,
+ void *cont_cls);
+
+
+/**
+ * Abort ECC key generation.
+ *
+ * @param gc key generation context to abort
+ */
+void
+GNUNET_CRYPTO_ecc_key_create_stop (struct
GNUNET_CRYPTO_EccKeyGenerationContext *gc);
+
+/**
+ * Setup a hostkey file for a peer given the name of the
+ * configuration file (!). This function is used so that
+ * at a later point code can be certain that reading a
+ * hostkey is fast (for example in time-dependent testcases).
+ *
+ * @param cfg_name name of the configuration file to use
+ */
+void
+GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name);
+
+
+/**
+ * Encrypt a block with the public key of another host that uses the
+ * same cipher.
+ *
+ * @param block the block to encrypt
+ * @param size the size of block
+ * @param publicKey the encoded public key used to encrypt
+ * @param target where to store the encrypted block
+ * @returns GNUNET_SYSERR on error, GNUNET_OK if ok
+ */
+int
+GNUNET_CRYPTO_ecc_encrypt (const void *block, size_t size,
+ const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
+ *publicKey,
+ struct GNUNET_CRYPTO_EccEncryptedData *target);
+
+
+/**
+ * Decrypt a given block with the hostkey.
+ *
+ * @param key the key with which to decrypt this block
+ * @param block the data to decrypt, encoded as returned by encrypt
+ * @param result pointer to a location where the result can be stored
+ * @param max the maximum number of bits to store for the result, if
+ * the decrypted block is bigger, an error is returned
+ * @return the size of the decrypted block, -1 on error
+ */
+ssize_t
+GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey *key,
+ const struct GNUNET_CRYPTO_EccEncryptedData *block,
+ void *result, size_t max);
+
+
+/**
+ * Sign a given block.
+ *
+ * @param key private key to use for the signing
+ * @param purpose what to sign (size, purpose)
+ * @param sig where to write the signature
+ * @return GNUNET_SYSERR on error, GNUNET_OK on success
+ */
+int
+GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *key,
+ const struct GNUNET_CRYPTO_EccSignaturePurpose
*purpose,
+ struct GNUNET_CRYPTO_EccSignature *sig);
+
+
+/**
+ * Verify signature.
+ *
+ * @param purpose what is the purpose that the signature should have?
+ * @param validate block to validate (size, purpose, data)
+ * @param sig signature that is being validated
+ * @param publicKey public key of the signer
+ * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
+ */
+int
+GNUNET_CRYPTO_ecc_verify (uint32_t purpose,
+ const struct GNUNET_CRYPTO_EccSignaturePurpose
+ *validate,
+ const struct GNUNET_CRYPTO_EccSignature *sig,
+ const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
+ *publicKey);
+
+
+/**
* This function should only be called in testcases
* where strong entropy gathering is not desired
* (for example, for hostkey generation).
Modified: gnunet/src/util/Makefile.am
===================================================================
--- gnunet/src/util/Makefile.am 2012-10-17 19:28:54 UTC (rev 24380)
+++ gnunet/src/util/Makefile.am 2012-10-17 19:35:13 UTC (rev 24381)
@@ -124,6 +124,7 @@
gnunet-service-resolver \
gnunet-resolver \
gnunet-config \
+ gnunet-ecc \
gnunet-rsa \
gnunet-uri
@@ -155,6 +156,15 @@
libgnunetutil.la
+gnunet_ecc_SOURCES = \
+ gnunet-ecc.c
+gnunet_ecc_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL) -lgcrypt
+gnunet_ecc_DEPENDENCIES = \
+ libgnunetutil.la
+
+
gnunet_config_SOURCES = \
gnunet-config.c
gnunet_config_LDADD = \
Modified: gnunet/src/util/crypto_ecc.c
===================================================================
--- gnunet/src/util/crypto_ecc.c 2012-10-17 19:28:54 UTC (rev 24380)
+++ gnunet/src/util/crypto_ecc.c 2012-10-17 19:35:13 UTC (rev 24381)
@@ -46,106 +46,15 @@
#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file
(kind, "util", syscall, filename)
-
/**
- * FIXME: what is an acceptable value here?
+ * Log an error message at log-level 'level' that indicates
+ * a failure of the command 'cmd' with the message given
+ * by gcry_strerror(rc).
*/
-#define GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH 64
+#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);
-/**
- * Length of the q-point (Q = dP) in the public key.
- * FIXME: double-check that this is right.
- */
-#define GNUNET_CRYPTO_ECC_PUBLIC_KEY_LENGTH 64
-
/**
- * @brief an ECC signature
- */
-struct GNUNET_CRYPTO_EccSignature
-{
- unsigned char sig[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
-};
-
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * @brief header of what an ECC signature signs
- * this must be followed by "size - 8" bytes of
- * the actual signed data
- */
-struct GNUNET_CRYPTO_EccSignaturePurpose
-{
- /**
- * How many bytes does this signature sign?
- * (including this purpose header); in network
- * byte order (!).
- */
- uint32_t size GNUNET_PACKED;
-
- /**
- * What does this signature vouch for? This
- * must contain a GNUNET_SIGNATURE_PURPOSE_XXX
- * constant (from gnunet_signatures.h). In
- * network byte order!
- */
- uint32_t purpose GNUNET_PACKED;
-
-};
-
-
-/**
- * Public ECC key (always for NIST P-521) encoded in a format suitable
- * for network transmission.
- */
-struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
-{
- /**
- * Size of the encoding, in network byte order.
- */
- uint16_t size;
-
- /**
- * Actual length of the q-point binary encoding.
- */
- uint16_t len;
-
- /**
- * 0-padded q-point in binary encoding (GCRYPT_MPI_FMT_USG).
- */
- unsigned char key[GNUNET_CRYPTO_ECC_PUBLIC_KEY_LENGTH];
-};
-
-
-struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded
-{
- /**
- * Overall size of the private key.
- */
- uint16_t size;
-
- /**
- * Size of the q and d components of the private key.
- * Note that the other parameters are from NIST P-521.
- */
- uint16_t sizes[2];
-};
-
-
-/**
- * ECC Encrypted data.
- */
-struct GNUNET_CRYPTO_EccEncryptedData
-{
- unsigned char encoding[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
-};
-
-GNUNET_NETWORK_STRUCT_END
-
-
-
-/**
* The private information of an ECC private key.
*/
struct GNUNET_CRYPTO_EccPrivateKey
@@ -159,27 +68,6 @@
/**
- * Function called upon completion of 'GNUNET_CRYPTO_ecc_key_create_async'.
- *
- * @param cls closure
- * @param pk NULL on error, otherwise the private key (which must be free'd by
the callee)
- * @param emsg NULL on success, otherwise an error message
- */
-typedef void (*GNUNET_CRYPTO_EccKeyCallback)(void *cls,
- struct GNUNET_CRYPTO_EccPrivateKey
*pk,
- const char *emsg);
-
-
-
-/**
- * Log an error message at log-level 'level' that indicates
- * a failure of the command 'cmd' with the message given
- * by gcry_strerror(rc).
- */
-#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);
-
-
-/**
* If target != size, move target bytes to the
* end of the size-sized buffer and zero out the
* first target-size bytes.
@@ -200,7 +88,8 @@
/**
- * Free memory occupied by hostkey
+ * Free memory occupied by ECC key
+ *
* @param privatekey pointer to the memory to free
*/
void
@@ -292,12 +181,12 @@
rc = key_from_sexp (&skey, priv->sexp, "ecc", "q");
GNUNET_assert (0 == rc);
pub->size = htons (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
- size = GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH;
+ size = GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH;
GNUNET_assert (0 ==
gcry_mpi_print (GCRYMPI_FMT_USG, pub->key, size, &size,
skey));
pub->len = htons (size);
- adjust (&pub->key[0], size, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH);
+ adjust (&pub->key[0], size, GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH);
gcry_mpi_release (skey);
}
@@ -407,19 +296,16 @@
* Encode the private key in a format suitable for
* storing it into a file.
*
- * @returns encoding of the private key.
+ * @param key key to encode
+ * @return encoding of the private key.
* The first 4 bytes give the size of the array, as usual.
*/
struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *
-GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey
*hostkey)
+GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *key)
{
struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *retval;
- gcry_mpi_t pkv[2];
- void *pbu[2];
- size_t sizes[2];
- size_t off;
- int rc;
- unsigned int i;
+ char buf[65536];
+ uint16_t be;
size_t size;
#if EXTRA_CHECKS
@@ -429,43 +315,20 @@
return NULL;
}
#endif
-
- memset (pkv, 0, sizeof (gcry_mpi_t) * 2);
- rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "qd");
- if (rc)
- rc = key_from_sexp (pkv, hostkey->sexp, "ecc", "qd");
- GNUNET_assert (0 == rc);
- size = sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded);
- for (i=0;i<2;i++)
+ size = gcry_sexp_sprint (key->sexp,
+ GCRYSEXP_FMT_DEFAULT,
+ &buf[2], sizeof (buf) - sizeof (uint16_t));
+ if (0 == size)
{
- if (NULL != pkv[i])
- {
- GNUNET_assert (0 ==
- gcry_mpi_aprint (GCRYMPI_FMT_USG,
- (unsigned char **) &pbu[i], &sizes[i],
- pkv[i]));
- size += sizes[i];
- }
- else
- {
- pbu[i] = NULL;
- sizes[i] = 0;
- }
+ GNUNET_break (0);
+ return NULL;
}
- GNUNET_assert (size < 65536);
+ GNUNET_assert (size < 65536 - sizeof (uint16_t));
+ be = htons ((uint16_t) size);
+ memcpy (buf, &be, sizeof (be));
+ size += sizeof (be);
retval = GNUNET_malloc (size);
- retval->size = htons (size);
- off = 0;
- for (i=0;i<2;i++)
- {
- retval->sizes[i] = htons (sizes[0]);
- memcpy (&((char *) (&retval[1]))[off], pbu[i], sizes[i]);
- off += sizes[i];
- if (NULL != pkv[i])
- gcry_mpi_release (pkv[i]);
- if (NULL != pbu[i])
- free (pbu[i]);
- }
+ memcpy (retval, buf, size);
return retval;
}
@@ -479,61 +342,35 @@
* @return NULL on error
*/
struct GNUNET_CRYPTO_EccPrivateKey *
-GNUNET_CRYPTO_ecc_decode_key (const char *buf, uint16_t len)
+GNUNET_CRYPTO_ecc_decode_key (const char *buf,
+ size_t len)
{
struct GNUNET_CRYPTO_EccPrivateKey *ret;
- const struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *encoding =
- (const struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *) buf;
- gcry_sexp_t res;
- gcry_mpi_t q;
- gcry_mpi_t d;
+ uint16_t be;
+ gcry_sexp_t sexp;
int rc;
- size_t size;
- size_t pos;
- uint16_t enc_len;
size_t erroff;
- enc_len = ntohs (encoding->size);
- if (len != enc_len)
+ if (len < sizeof (uint16_t))
return NULL;
- pos = 0;
- size = ntohs (encoding->sizes[0]);
- rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG,
- &((const unsigned char *) (&encoding[1]))[pos], size,
- &size);
- pos += ntohs (encoding->sizes[0]);
- if (0 != rc)
- {
- LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
+ memcpy (&be, buf, sizeof (be));
+ if (len != ntohs (be))
return NULL;
- }
- size = ntohs (encoding->sizes[1]);
- rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG,
- &((const unsigned char *) (&encoding[1]))[pos], size,
- &size);
- pos += ntohs (encoding->sizes[1]);
- if (0 != rc)
+ if (0 != (rc = gcry_sexp_sscan (&sexp,
+ &erroff,
+ &buf[2],
+ len - sizeof (uint16_t))))
{
- LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
- gcry_mpi_release (d);
+ LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_scan", rc);
return NULL;
}
- rc = gcry_sexp_build (&res, &erroff,
- "(private-key(ecc(q %m)(d %m)(curve \"" CURVE "\")))",
- q, d);
- gcry_mpi_release (q);
- gcry_mpi_release (d);
- if (0 != rc)
- LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
-#if EXTRA_CHECKS
- if (0 != (rc = gcry_pk_testkey (res)))
+ if (0 != (rc = gcry_pk_testkey (sexp)))
{
LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
return NULL;
}
-#endif
ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey));
- ret->sexp = res;
+ ret->sexp = sexp;
return ret;
}
@@ -574,10 +411,8 @@
try_read_key (const char *filename)
{
struct GNUNET_CRYPTO_EccPrivateKey *ret;
- struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc;
struct GNUNET_DISK_FileHandle *fd;
OFF_T fs;
- uint16_t len;
if (GNUNET_YES != GNUNET_DISK_file_test (filename))
return NULL;
@@ -611,26 +446,22 @@
LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
return NULL;
}
+ {
+ char enc[fs];
- enc = GNUNET_malloc (fs);
- GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
- len = ntohs (enc->size);
- ret = NULL;
- if ((len != fs) ||
- (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, len))))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("File `%s' does not contain a valid private key (failed decode,
%llu bytes). Deleting it.\n"),
- filename,
- (unsigned long long) fs);
- GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
- if (0 != UNLINK (filename))
- LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
- GNUNET_free (enc);
- return NULL;
+ GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
+ if (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, fs)))
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("File `%s' does not contain a valid private key (failed decode,
%llu bytes). Deleting it.\n"),
+ filename,
+ (unsigned long long) fs);
+ GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
+ if (0 != UNLINK (filename))
+ LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
+ return NULL;
+ }
}
- GNUNET_free (enc);
-
GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
return ret;
}
@@ -1084,7 +915,7 @@
cfg = GNUNET_CONFIGURATION_create ();
(void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
if (GNUNET_OK ==
- GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", &fn))
+ GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY",
&fn))
{
pk = GNUNET_CRYPTO_ecc_key_create_from_file (fn);
if (NULL != pk)
@@ -1115,7 +946,6 @@
gcry_sexp_t data;
gcry_sexp_t psexp;
gcry_mpi_t val;
- gcry_mpi_t rval;
size_t isize;
size_t erroff;
@@ -1132,16 +962,18 @@
GNUNET_assert (0 == gcry_pk_encrypt (&result, data, psexp));
gcry_sexp_release (data);
gcry_sexp_release (psexp);
-
- GNUNET_assert (0 == key_from_sexp (&rval, result, "ecc", "a"));
- gcry_sexp_release (result);
- isize = sizeof (struct GNUNET_CRYPTO_EccEncryptedData);
- GNUNET_assert (0 ==
- gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) target,
- isize, &isize, rval));
- gcry_mpi_release (rval);
- adjust (&target->encoding[0], isize,
- sizeof (struct GNUNET_CRYPTO_EccEncryptedData));
+ isize = gcry_sexp_sprint (result,
+ GCRYSEXP_FMT_DEFAULT,
+ target->encoding,
+ GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH);
+ if (0 == isize)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ target->size = htons ((uint16_t) isize);
+ /* padd with zeros */
+ memset (&target->encoding[isize], 0, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH
- isize);
return GNUNET_OK;
}
@@ -1157,8 +989,8 @@
* @return the size of the decrypted block, -1 on error
*/
ssize_t
-GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey * key,
- const struct GNUNET_CRYPTO_EccEncryptedData * block,
+GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey *key,
+ const struct GNUNET_CRYPTO_EccEncryptedData *block,
void *result, size_t max)
{
gcry_sexp_t resultsexp;
@@ -1167,19 +999,15 @@
size_t size;
gcry_mpi_t val;
unsigned char *endp;
- unsigned char *tmp;
#if EXTRA_CHECKS
GNUNET_assert (0 == gcry_pk_testkey (key->sexp));
#endif
- size = sizeof (struct GNUNET_CRYPTO_EccEncryptedData);
+ size = ntohs (block->size);
GNUNET_assert (0 ==
- gcry_mpi_scan (&val, GCRYMPI_FMT_USG, &block->encoding[0],
- size, &size));
- GNUNET_assert (0 ==
- gcry_sexp_build (&data, &erroff, "(enc-val(flags)(ecc(a
%m)))",
- val));
- gcry_mpi_release (val);
+ gcry_sexp_sscan (&data,
+ &erroff,
+ block->encoding, size));
GNUNET_assert (0 == gcry_pk_decrypt (&resultsexp, data, key->sexp));
gcry_sexp_release (data);
/* resultsexp has format "(value %m)" */
@@ -1187,19 +1015,54 @@
(val = gcry_sexp_nth_mpi (resultsexp, 1, GCRYMPI_FMT_USG)));
gcry_sexp_release (resultsexp);
size = max + GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH * 2;
- tmp = GNUNET_malloc (size);
- GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG, tmp, size, &size, val));
- gcry_mpi_release (val);
- endp = tmp;
- endp += (size - max);
- size = max;
- memcpy (result, endp, size);
- GNUNET_free (tmp);
+ {
+ unsigned char tmp[size];
+
+ GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG, tmp, size, &size,
val));
+ gcry_mpi_release (val);
+ endp = tmp;
+ endp += (size - max);
+ size = max;
+ memcpy (result, endp, size);
+ }
return size;
}
/**
+ * Convert the data specified in the given purpose argument to an
+ * S-expression suitable for signature operations.
+ *
+ * @param purpose data to convert
+ * @return converted s-expression
+ */
+static gcry_sexp_t
+data_to_pkcs1 (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
+{
+ struct GNUNET_HashCode hc;
+ size_t bufSize;
+ gcry_sexp_t data;
+
+ GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
+#define FORMATSTRING
"(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))"
+ bufSize = strlen (FORMATSTRING) + 1;
+ {
+ char buff[bufSize];
+
+ memcpy (buff, FORMATSTRING, bufSize);
+ memcpy (&buff
+ [bufSize -
+ strlen
+
("0123456789012345678901234567890123456789012345678901234567890123))")
+ - 1], &hc, sizeof (struct GNUNET_HashCode));
+ GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
+ }
+#undef FORMATSTRING
+ return data;
+}
+
+
+/**
* Sign a given block.
*
* @param key private key to use for the signing
@@ -1215,33 +1078,23 @@
gcry_sexp_t result;
gcry_sexp_t data;
size_t ssize;
- gcry_mpi_t rval;
- struct GNUNET_HashCode hc;
- char *buff;
- int bufSize;
- GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
-#define FORMATSTRING
"(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))"
- bufSize = strlen (FORMATSTRING) + 1;
- buff = GNUNET_malloc (bufSize);
- memcpy (buff, FORMATSTRING, bufSize);
- memcpy (&buff
- [bufSize -
- strlen
-
("0123456789012345678901234567890123456789012345678901234567890123))")
- - 1], &hc, sizeof (struct GNUNET_HashCode));
- GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
- GNUNET_free (buff);
+ data = data_to_pkcs1 (purpose);
GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp));
gcry_sexp_release (data);
- GNUNET_assert (0 == key_from_sexp (&rval, result, "ecc", "s"));
+ ssize = gcry_sexp_sprint (result,
+ GCRYSEXP_FMT_DEFAULT,
+ sig->sexpr,
+ GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH);
+ if (0 == ssize)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ sig->size = htons ((uint16_t) ssize);
+ /* padd with zeros */
+ memset (&sig->sexpr[ssize], 0, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH -
ssize);
gcry_sexp_release (result);
- ssize = sizeof (struct GNUNET_CRYPTO_EccSignature);
- GNUNET_assert (0 ==
- gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) sig, ssize,
- &ssize, rval));
- gcry_mpi_release (rval);
- adjust (sig->sig, ssize, sizeof (struct GNUNET_CRYPTO_EccSignature));
return GNUNET_OK;
}
@@ -1266,35 +1119,18 @@
gcry_sexp_t data;
gcry_sexp_t sigdata;
size_t size;
- gcry_mpi_t val;
gcry_sexp_t psexp;
- struct GNUNET_HashCode hc;
- char *buff;
- int bufSize;
size_t erroff;
int rc;
if (purpose != ntohl (validate->purpose))
return GNUNET_SYSERR; /* purpose mismatch */
- GNUNET_CRYPTO_hash (validate, ntohl (validate->size), &hc);
- size = sizeof (struct GNUNET_CRYPTO_EccSignature);
+ size = ntohs (sig->size);
+ if (size > GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - sizeof (uint16_t))
+ return GNUNET_SYSERR; /* size out of range */
+ data = data_to_pkcs1 (validate);
GNUNET_assert (0 ==
- gcry_mpi_scan (&val, GCRYMPI_FMT_USG,
- (const unsigned char *) sig, size, &size));
- GNUNET_assert (0 ==
- gcry_sexp_build (&sigdata, &erroff, "(sig-val(ecc(s %m)))",
- val));
- gcry_mpi_release (val);
- bufSize = strlen (FORMATSTRING) + 1;
- buff = GNUNET_malloc (bufSize);
- memcpy (buff, FORMATSTRING, bufSize);
- memcpy (&buff
- [strlen (FORMATSTRING) -
- strlen
-
("0123456789012345678901234567890123456789012345678901234567890123))")],
- &hc, sizeof (struct GNUNET_HashCode));
- GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
- GNUNET_free (buff);
+ gcry_sexp_sscan (&sigdata, &erroff, sig->sexpr, size));
if (! (psexp = decode_public_key (publicKey)))
{
gcry_sexp_release (data);
@@ -1305,7 +1141,7 @@
gcry_sexp_release (psexp);
gcry_sexp_release (data);
gcry_sexp_release (sigdata);
- if (rc)
+ if (0 != rc)
{
LOG (GNUNET_ERROR_TYPE_WARNING,
_("ECC signature verification failed at %s:%d: %s\n"), __FILE__,
Added: gnunet/src/util/gnunet-ecc.c
===================================================================
--- gnunet/src/util/gnunet-ecc.c (rev 0)
+++ gnunet/src/util/gnunet-ecc.c 2012-10-17 19:35:13 UTC (rev 24381)
@@ -0,0 +1,246 @@
+/*
+ This file is part of GNUnet.
+ (C) 2012 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/gnunet-ecc.c
+ * @brief tool to manipulate ECC key files
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_lib-new.h"
+#include <gcrypt.h>
+
+
+/**
+ * Flag for printing public key.
+ */
+static int print_public_key;
+
+/**
+ * Flag for printing hash of public key.
+ */
+static int print_peer_identity;
+
+/**
+ * Flag for printing short hash of public key.
+ */
+static int print_short_identity;
+
+/**
+ * Use weak random number generator for key generation.
+ */
+static int weak_random;
+
+/**
+ * Option set to create a bunch of keys at once.
+ */
+static unsigned int make_keys;
+
+/**
+ * The private information of an ECC key pair.
+ * NOTE: this must match the definition in crypto_ksk.c and crypto_ecc.c!
+ */
+struct GNUNET_CRYPTO_EccPrivateKey
+{
+ gcry_sexp_t sexp;
+};
+
+
+/**
+ * Create a new private key. Caller must free return value.
+ *
+ * @return fresh private key
+ */
+static struct GNUNET_CRYPTO_EccPrivateKey *
+ecc_key_create ()
+{
+ struct GNUNET_CRYPTO_EccPrivateKey *ret;
+ gcry_sexp_t s_key;
+ gcry_sexp_t s_keyparam;
+
+ GNUNET_assert (0 ==
+ gcry_sexp_build (&s_keyparam, NULL,
+ "(genkey(ecc(nbits %d)(ecc-use-e 3:257)))",
+ 2048));
+ GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam));
+ gcry_sexp_release (s_keyparam);
+#if EXTRA_CHECKS
+ GNUNET_assert (0 == gcry_pk_testkey (s_key));
+#endif
+ ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey));
+ ret->sexp = s_key;
+ return ret;
+}
+
+
+/**
+ * Create a flat file with a large number of key pairs for testing.
+ */
+static void
+create_keys (const char *fn)
+{
+ FILE *f;
+ struct GNUNET_CRYPTO_EccPrivateKey *pk;
+ struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc;
+
+ if (NULL == (f = fopen (fn, "w+")))
+ {
+ fprintf (stderr,
+ _("Failed to open `%s': %s\n"),
+ fn,
+ STRERROR (errno));
+ return;
+ }
+ fprintf (stderr,
+ _("Generating %u keys, please wait"),
+ make_keys);
+ while (0 < make_keys--)
+ {
+ fprintf (stderr,
+ ".");
+ if (NULL == (pk = ecc_key_create ()))
+ {
+ GNUNET_break (0);
+ break;
+ }
+ enc = GNUNET_CRYPTO_ecc_encode_key (pk);
+ if (htons (enc->size) != fwrite (enc, 1, htons (enc->size), f))
+ {
+ fprintf (stderr,
+ _("\nFailed to write to `%s': %s\n"),
+ fn,
+ STRERROR (errno));
+ GNUNET_CRYPTO_ecc_key_free (pk);
+ GNUNET_free (enc);
+ break;
+ }
+ GNUNET_CRYPTO_ecc_key_free (pk);
+ GNUNET_free (enc);
+ }
+ if (0 == make_keys)
+ fprintf (stderr,
+ _("Finished!\n"));
+ fclose (f);
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be
NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_CRYPTO_EccPrivateKey *pk;
+ struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub;
+ struct GNUNET_PeerIdentity pid;
+
+ if (NULL == args[0])
+ {
+ fprintf (stderr, _("No hostkey file specified on command line\n"));
+ return;
+ }
+ if (0 != weak_random)
+ GNUNET_CRYPTO_random_disable_entropy_gathering ();
+ if (make_keys > 0)
+ {
+ create_keys (args[0]);
+ return;
+ }
+ pk = GNUNET_CRYPTO_ecc_key_create_from_file (args[0]);
+ if (NULL == pk)
+ return;
+ if (print_public_key)
+ {
+ char *s;
+
+ GNUNET_CRYPTO_ecc_key_get_public (pk, &pub);
+ s = GNUNET_CRYPTO_ecc_public_key_to_string (&pub);
+ fprintf (stdout, "%s\n", s);
+ GNUNET_free (s);
+ }
+ if (print_peer_identity)
+ {
+ struct GNUNET_CRYPTO_HashAsciiEncoded enc;
+
+ GNUNET_CRYPTO_ecc_key_get_public (pk, &pub);
+ GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
+ GNUNET_CRYPTO_hash_to_enc (&pid.hashPubKey, &enc);
+ fprintf (stdout, "%s\n", enc.encoding);
+ }
+ if (print_short_identity)
+ {
+ struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
+ struct GNUNET_CRYPTO_ShortHashCode sh;
+
+ GNUNET_CRYPTO_ecc_key_get_public (pk, &pub);
+ GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &sh);
+ GNUNET_CRYPTO_short_hash_to_enc (&sh, &enc);
+ fprintf (stdout, "%s\n", enc.short_encoding);
+ }
+ GNUNET_CRYPTO_ecc_key_free (pk);
+}
+
+
+/**
+ * Program to manipulate ECC key files.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+ static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ { 'g', "generate-keys", "COUNT",
+ gettext_noop ("create COUNT public-private key pairs (for testing)"),
+ 1, &GNUNET_GETOPT_set_uint, &make_keys },
+ { 'p', "print-public-key", NULL,
+ gettext_noop ("print the public key in ASCII format"),
+ 0, &GNUNET_GETOPT_set_one, &print_public_key },
+ { 'P', "print-peer-identity", NULL,
+ gettext_noop ("print the hash of the public key in ASCII format"),
+ 0, &GNUNET_GETOPT_set_one, &print_peer_identity },
+ { 's', "print-short-identity", NULL,
+ gettext_noop ("print the short hash of the public key in ASCII format"),
+ 0, &GNUNET_GETOPT_set_one, &print_short_identity },
+ { 'w', "weak-random", NULL,
+ gettext_noop ("use insecure, weak random number generator for key
generation (for testing only)"),
+ 0, &GNUNET_GETOPT_set_one, &weak_random },
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+ return 2;
+
+ return (GNUNET_OK ==
+ GNUNET_PROGRAM_run (argc, argv, "gnunet-ecc [OPTIONS] keyfile",
+ gettext_noop ("Manipulate GNUnet private ECC key
files"),
+ options, &run, NULL)) ? 0 : 1;
+}
+
+/* end of gnunet-ecc.c */
Modified: gnunet/src/util/util.conf
===================================================================
--- gnunet/src/util/util.conf 2012-10-17 19:28:54 UTC (rev 24380)
+++ gnunet/src/util/util.conf 2012-10-17 19:35:13 UTC (rev 24381)
@@ -9,6 +9,9 @@
[gnunetd]
HOSTKEY = $SERVICEHOME/.hostkey
+[PEER]
+PRIVATE_KEY = $SERVICEHOME/private.ecc
+
[client]
HOME = $SERVICEHOME
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r24381 - in gnunet/src: include util,
gnunet <=