#include "gnunet_common.h"
#include "gnunet_util_lib.h"
-#define EXTRA_CHECKS ALLOW_EXTRA_CHECKS || 1
+#define EXTRA_CHECKS ALLOW_EXTRA_CHECKS
-#define CURVE "NIST P-521"
+#define CURVE "NIST P-256"
#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
* @return string representing 'pub'
*/
char *
-GNUNET_CRYPTO_ecc_public_key_to_string (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub)
+GNUNET_CRYPTO_ecc_public_key_to_string (const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub)
{
char *pubkeybuf;
size_t keylen = (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)) * 8;
*
* @param buf the buffer where the private key data is stored
* @param len the length of the data in 'buffer'
+ * @param validate GNUNET_YES to validate that the key is well-formed,
+ * GNUNET_NO if the key comes from a totally trusted source
+ * and validation is considered too expensive
* @return NULL on error
*/
struct GNUNET_CRYPTO_EccPrivateKey *
GNUNET_CRYPTO_ecc_decode_key (const char *buf,
- size_t len)
+ size_t len,
+ int validate)
{
struct GNUNET_CRYPTO_EccPrivateKey *ret;
uint16_t be;
if (len < sizeof (uint16_t))
return NULL;
memcpy (&be, buf, sizeof (be));
- if (len != ntohs (be))
+ if (len < ntohs (be))
return NULL;
+ len = ntohs (be);
if (0 != (rc = gcry_sexp_sscan (&sexp,
&erroff,
&buf[2],
{
LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_scan", rc);
return NULL;
- }
- if (0 != (rc = gcry_pk_testkey (sexp)))
+ }
+ if ( (GNUNET_YES == validate) &&
+ (0 != (rc = gcry_pk_testkey (sexp))) )
{
LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
return NULL;
char enc[fs];
GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
- if (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, fs)))
+ if (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, fs, GNUNET_YES)))
{
LOG (GNUNET_ERROR_TYPE_ERROR,
_("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"),
GNUNET_assert (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))))
+ if ((len > fs) ||
+ (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, len, GNUNET_YES))))
{
LOG (GNUNET_ERROR_TYPE_ERROR,
_("File `%s' does not contain a valid private key. Deleting it.\n"),
{
struct GNUNET_CRYPTO_EccKeyGenerationContext *gc;
struct GNUNET_CRYPTO_EccPrivateKey *pk;
- const char *weak_random;
if (NULL != (pk = try_read_key (filename)))
{
GNUNET_free (gc);
return NULL;
}
- weak_random = NULL;
- if (GNUNET_YES ==
- GNUNET_CRYPTO_random_is_weak ())
- weak_random = "-w";
gc->gnunet_ecc = GNUNET_OS_start_process (GNUNET_NO,
GNUNET_OS_INHERIT_STD_ERR,
NULL,
"gnunet-ecc",
"gnunet-ecc",
gc->filename,
- weak_random,
NULL);
if (NULL == gc->gnunet_ecc)
{
GNUNET_CRYPTO_short_hash (purpose, ntohl (purpose->size), &hc);
#define FORMATSTRING "(4:data(5:flags3:raw)(5:value32:01234567890123456789012345678901))"
-#define FORMATSTRING2 "(4:data(4:hash6:sha25632:01234567890123456789012345678901))"
bufSize = strlen (FORMATSTRING) + 1;
{
char buff[bufSize];
LOG (GNUNET_ERROR_TYPE_WARNING,
_("ECC signing failed at %s:%d: %s\n"), __FILE__,
__LINE__, gcry_strerror (rc));
+ gcry_sexp_release (data);
+ return GNUNET_SYSERR;
}
gcry_sexp_release (data);
ssize = gcry_sexp_sprint (result,
const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub,
struct GNUNET_HashCode *key_material)
{
- gcry_sexp_t psexp;
+ size_t size;
+ size_t slen;
+ int rc;
+ gcry_sexp_t data;
+ unsigned char sdata_buf[2048]; /* big enough to print 'sdata' and 'r_sig' */
- if (! (psexp = decode_public_key (pub)))
- return GNUNET_SYSERR;
-
+ /* first, extract the q value from the public key */
+ {
+ gcry_sexp_t psexp;
+ gcry_mpi_t sdata;
+
+ if (! (psexp = decode_public_key (pub)))
+ return GNUNET_SYSERR;
+ rc = key_from_sexp (&sdata, psexp, "public-key", "q");
+ if (rc)
+ rc = key_from_sexp (&sdata, psexp, "ecc", "q");
+ GNUNET_assert (0 == rc);
+ gcry_sexp_release (psexp);
+ size = sizeof (sdata_buf);
+ GNUNET_assert (0 ==
+ gcry_mpi_print (GCRYMPI_FMT_USG, sdata_buf, size, &size,
+ sdata));
+ gcry_mpi_release (sdata);
+ }
+ /* convert q value into an S-expression -- whatever format libgcrypt wants,
+ re-using format from sign operation for now... */
+ {
+ char *sexp_string;
+
+#define FORMATPREFIX "(4:data(5:flags3:raw)(5:value%u:"
+#define FORMATPOSTFIX "))"
+ sexp_string = GNUNET_malloc (strlen (FORMATPREFIX) + size + 12 +
+ strlen (FORMATPOSTFIX) + 1);
+ GNUNET_snprintf (sexp_string,
+ strlen (FORMATPREFIX) + 12,
+ FORMATPREFIX,
+ size);
+ slen = strlen (sexp_string);
+ memcpy (&sexp_string[slen],
+ sdata_buf,
+ size);
+ memcpy (&sexp_string[slen + size],
+ FORMATPOSTFIX,
+ strlen (FORMATPOSTFIX) + 1);
+ GNUNET_assert (0 == gcry_sexp_new (&data,
+ sexp_string,
+ slen + size + strlen (FORMATPOSTFIX),
+ 0));
+ GNUNET_free (sexp_string);
+ }
+ /* then call the 'multiply' function, hoping it simply multiplies the points;
+ here we need essentially a WRAPPER around _gcry_mpi_ex_mul_point! - FIXME-WK!*/
+#if WK
+ {
+ gcry_sexp_t result;
+
+ rc = gcry_ecc_mul_point (&result, data /* scalar */, key->sexp /* point and ctx */);
+ GNUNET_assert (0 == rc);
+ slen = gcry_sexp_sprint (result, GCRYSEXP_FMT_DEFAULT, sdata_buf, sizeof (sdata_buf));
+ GNUNET_assert (0 != slen);
+ }
+#else
+ /* use broken version, insecure! */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("To be implemented: not secure at the moment, please read README\n"));
+ slen = sprintf ((char*) sdata_buf, "FIXME-this is not key material");
+#endif
+ gcry_sexp_release (data);
- gcry_sexp_release (psexp);
- GNUNET_break (0); // not implemented
- /* FIXME: this totally breaks security ... */
- memset (key_material, 42, sizeof (struct GNUNET_HashCode));
+ /* finally, get a string of the resulting S-expression and hash it to generate the key material */
+ GNUNET_CRYPTO_hash (sdata_buf, slen, key_material);
return GNUNET_OK;
}