gnunet-svn
[Top][All Lists]
Advanced

[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
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]