/**
* Extract the public key of the host.
- * @param hostkey the hostkey to extract into the result.
- * @param result where to write the result.
+ * @param priv the private key
+ * @param pub where to write the public key
*/
void
GNUNET_CRYPTO_rsa_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey
- *hostkey,
+ *priv,
struct
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
- *result)
+ *pub)
{
gcry_mpi_t skey[2];
size_t size;
int rc;
- rc = key_from_sexp (skey, hostkey->sexp, "public-key", "ne");
+ rc = key_from_sexp (skey, priv->sexp, "public-key", "ne");
if (rc)
- rc = key_from_sexp (skey, hostkey->sexp, "private-key", "ne");
+ rc = key_from_sexp (skey, priv->sexp, "private-key", "ne");
if (rc)
- rc = key_from_sexp (skey, hostkey->sexp, "rsa", "ne");
+ rc = key_from_sexp (skey, priv->sexp, "rsa", "ne");
GNUNET_assert (0 == rc);
- result->len =
+ pub->len =
htons (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) -
- sizeof (result->padding));
- result->sizen = htons (GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH);
- result->padding = 0;
+ sizeof (pub->padding));
+ pub->sizen = htons (GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH);
+ pub->padding = 0;
size = GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH;
GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
- &result->key[0], size, &size, skey[0]));
- adjust (&result->key[0], size, GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH);
+ &pub->key[0], size, &size, skey[0]));
+ adjust (&pub->key[0], size, GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH);
size =
GNUNET_CRYPTO_RSA_KEY_LENGTH - GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH;
GNUNET_assert (0 ==
gcry_mpi_print (GCRYMPI_FMT_USG,
- &result->key
+ &pub->key
[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH],
size, &size, skey[1]));
- adjust (&result->key[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH], size,
+ adjust (&pub->key[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH], size,
GNUNET_CRYPTO_RSA_KEY_LENGTH -
GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH);
gcry_mpi_release (skey[0]);
/**
* 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'
*/
-static struct GNUNET_CRYPTO_RsaPrivateKey *
-rsa_decode_key (const struct RsaPrivateKeyBinaryEncoded *encoding)
+struct GNUNET_CRYPTO_RsaPrivateKey *
+GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len)
{
struct GNUNET_CRYPTO_RsaPrivateKey *ret;
+ const struct RsaPrivateKeyBinaryEncoded *encoding = (const struct RsaPrivateKeyBinaryEncoded *)buf;
gcry_sexp_t res;
gcry_mpi_t n, e, d, p, q, u;
int rc;
size_t size;
int pos;
+ uint16_t enc_len;
+
+ enc_len = ntohs(encoding->len);
+ if (len != enc_len)
+ return NULL;
pos = 0;
size = ntohs (encoding->sizen);
* 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. The
- * caller must somehow know that the file either already exists
- * with a valid key OR be sure that no other process is calling
- * this function at the same time. If the contents of the file
+ * 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.
*
struct GNUNET_CRYPTO_RsaPrivateKey *
GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
{
- struct flock fl;
struct GNUNET_CRYPTO_RsaPrivateKey *ret;
struct RsaPrivateKeyBinaryEncoded *enc;
- struct stat sbuf;
uint16_t len;
- int fd;
+ struct GNUNET_DISK_FileHandle *fd;
unsigned int cnt;
int ec;
+ uint64_t fs;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
+ struct GNUNET_PeerIdentity pid;
if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
return NULL;
- while (0 != STAT (filename, &sbuf))
+ while (GNUNET_YES != GNUNET_DISK_file_test (filename))
{
- fd = open (filename, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
- if (-1 == fd)
+ fd = GNUNET_DISK_file_open (filename,
+ GNUNET_DISK_OPEN_WRITE |
+ GNUNET_DISK_OPEN_CREATE |
+ GNUNET_DISK_OPEN_FAILIFEXISTS,
+ GNUNET_DISK_PERM_USER_READ |
+ GNUNET_DISK_PERM_USER_WRITE);
+ if (NULL == fd)
{
if (errno == EEXIST)
- continue;
+ {
+ if (GNUNET_YES != GNUNET_DISK_file_test (filename))
+ {
+ /* must exist but not be accessible, fail for good! */
+ if (0 != ACCESS (filename, R_OK))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "access", filename);
+ else
+ GNUNET_break (0); /* what is going on!? */
+ return NULL;
+ }
+ continue;
+ }
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
"open", filename);
return NULL;
}
- memset (&fl, 0, sizeof (struct flock));
- fl.l_type = F_WRLCK;
- fl.l_whence = SEEK_SET;
- fl.l_len = sizeof (struct RsaPrivateKeyBinaryEncoded);
cnt = 0;
- while (0 != fcntl (fd, F_SETLK, &fl))
+
+ while (GNUNET_YES !=
+ GNUNET_DISK_file_lock (fd, 0,
+ sizeof (struct
+ RsaPrivateKeyBinaryEncoded),
+ GNUNET_YES))
{
sleep (1);
if (0 == ++cnt % 10)
{
ec = errno;
- fl.l_type = F_GETLK;
- fcntl (fd, F_GETLK, &fl);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_
- ("Could not aquire lock on file `%s' due to process %u: %s...\n"),
- filename, fl.l_pid, STRERROR (errno));
+ ("Could not aquire lock on file `%s': %s...\n"),
+ filename, STRERROR (ec));
}
- memset (&fl, 0, sizeof (struct flock));
- fl.l_type = F_WRLCK;
- fl.l_whence = SEEK_SET;
- fl.l_len = sizeof (struct RsaPrivateKeyBinaryEncoded);
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
_("Creating a new private key. This may take a while.\n"));
GNUNET_assert (ret != NULL);
enc = rsa_encode_key (ret);
GNUNET_assert (enc != NULL);
- GNUNET_assert (ntohs (enc->len) == WRITE (fd, enc, ntohs (enc->len)));
+ GNUNET_assert (ntohs (enc->len) ==
+ GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
GNUNET_free (enc);
- fdatasync (fd);
- memset (&fl, 0, sizeof (struct flock));
- fl.l_type = F_UNLCK;
- fl.l_whence = SEEK_SET;
- fl.l_len = sizeof (struct RsaPrivateKeyBinaryEncoded);
- cnt = 0;
- if (0 != fcntl (fd, F_SETLK, &fl))
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "fcntl", filename);
- GNUNET_assert (0 == CLOSE (fd));
+
+ GNUNET_DISK_file_sync (fd);
+ if (GNUNET_YES !=
+ GNUNET_DISK_file_unlock (fd, 0,
+ sizeof (struct
+ RsaPrivateKeyBinaryEncoded)))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fcntl",
+ filename);
+ GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
+ GNUNET_CRYPTO_rsa_key_get_public (ret, &pub);
+ GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Stored new private key in `%s'.\n"), filename);
+ _("I am host `%s'. Stored new private key in `%s'.\n"),
+ GNUNET_i2s (&pid),
+ filename);
return ret;
}
/* hostkey file exists already, read it! */
- fd = open (filename, O_RDONLY);
- if (-1 == fd)
+ fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE);
+ if (NULL == fd)
{
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename);
return NULL;
cnt = 0;
while (1)
{
- memset (&fl, 0, sizeof (struct flock));
- fl.l_type = F_RDLCK;
- fl.l_whence = SEEK_SET;
- fl.l_len = sizeof (struct RsaPrivateKeyBinaryEncoded);
- if (0 != fcntl (fd, F_SETLK, &fl))
+ if (GNUNET_YES !=
+ GNUNET_DISK_file_lock (fd, 0,
+ sizeof (struct RsaPrivateKeyBinaryEncoded),
+ GNUNET_NO))
{
- if (0 == ++cnt % 10)
+ if (0 == ++cnt % 60)
{
ec = errno;
- fl.l_type = F_GETLK;
- fcntl (fd, F_GETLK, &fl);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _
- ("Could not aquire lock on file `%s' due to process %u: %s...\n"),
- filename, fl.l_pid, STRERROR (errno));
+ _("Could not aquire lock on file `%s': %s...\n"),
+ filename, STRERROR (ec));
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_
("This may be ok if someone is currently generating a hostkey.\n"));
sleep (1);
continue;
}
- if (0 != STAT (filename, &sbuf))
+ if (GNUNET_YES != GNUNET_DISK_file_test (filename))
{
/* eh, what!? File we opened is now gone!? */
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
"stat", filename);
- memset (&fl, 0, sizeof (struct flock));
- fl.l_type = F_UNLCK;
- fl.l_whence = SEEK_SET;
- fl.l_len = sizeof (struct RsaPrivateKeyBinaryEncoded);
- if (0 != fcntl (fd, F_SETLK, &fl))
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "fcntl", filename);
- GNUNET_assert (0 == CLOSE (fd));
+ if (GNUNET_YES !=
+ GNUNET_DISK_file_unlock (fd, 0,
+ sizeof (struct
+ RsaPrivateKeyBinaryEncoded)))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fcntl",
+ filename);
+ GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
+
return NULL;
}
- if (sbuf.st_size < sizeof (struct RsaPrivateKeyBinaryEncoded))
+ if (GNUNET_YES != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES))
+ fs = 0;
+ if (fs < sizeof (struct RsaPrivateKeyBinaryEncoded))
{
/* maybe we got the read lock before the hostkey generating
process had a chance to get the write lock; give it up! */
- memset (&fl, 0, sizeof (struct flock));
- fl.l_type = F_UNLCK;
- fl.l_whence = SEEK_SET;
- fl.l_len = sizeof (struct RsaPrivateKeyBinaryEncoded);
- if (0 != fcntl (fd, F_SETLK, &fl))
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "fcntl", filename);
+ if (GNUNET_YES !=
+ GNUNET_DISK_file_unlock (fd, 0,
+ sizeof (struct
+ RsaPrivateKeyBinaryEncoded)))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fcntl",
+ filename);
if (0 == ++cnt % 10)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_
("When trying to read hostkey file `%s' I found %u bytes but I need at least %u.\n"),
- filename, (unsigned int) sbuf.st_size,
+ filename, (unsigned int) fs,
(unsigned int) sizeof (struct
RsaPrivateKeyBinaryEncoded));
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
}
break;
}
- enc = GNUNET_malloc (sbuf.st_size);
- GNUNET_assert (sbuf.st_size == READ (fd, enc, sbuf.st_size));
+ enc = GNUNET_malloc (fs);
+ GNUNET_assert (fs == GNUNET_DISK_file_read (fd, enc, fs));
len = ntohs (enc->len);
ret = NULL;
- if ((len != sbuf.st_size) || (NULL == (ret = rsa_decode_key (enc))))
+ if ((len != fs) || (NULL == (ret = GNUNET_CRYPTO_rsa_decode_key ((char *)enc, len))))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_
- ("File `%s' does not contain a valid private key. You should delete it.\n"),
+ ("File `%s' does not contain a valid private key. Deleting it.\n"),
filename);
- GNUNET_free (enc);
+ if (0 != UNLINK (filename))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "unlink",
+ filename);
+ }
}
- memset (&fl, 0, sizeof (struct flock));
- fl.l_type = F_UNLCK;
- fl.l_whence = SEEK_SET;
- fl.l_len = sizeof (struct RsaPrivateKeyBinaryEncoded);
- if (0 != fcntl (fd, F_SETLK, &fl))
+ GNUNET_free (enc);
+ if (GNUNET_YES !=
+ GNUNET_DISK_file_unlock (fd, 0,
+ sizeof (struct RsaPrivateKeyBinaryEncoded)))
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
- GNUNET_assert (0 == CLOSE (fd));
+ GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
+ if (ret != NULL)
+ {
+ GNUNET_CRYPTO_rsa_key_get_public (ret, &pub);
+ GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("I am host `%s'. Read private key from `%s'.\n"),
+ GNUNET_i2s (&pid),
+ filename);
+ }
return ret;
}
*/
int
GNUNET_CRYPTO_rsa_encrypt (const void *block,
- uint16_t size,
+ size_t size,
const struct
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey,
struct GNUNET_CRYPTO_RsaEncryptedData *target)
GNUNET_assert (size <= sizeof (GNUNET_HashCode));
pubkey = public2PrivateKey (publicKey);
+ if (pubkey == NULL)
+ return GNUNET_SYSERR;
isize = size;
GNUNET_assert (0 ==
gcry_mpi_scan (&val, GCRYMPI_FMT_USG, block, isize, &isize));
/**
* Decrypt a given block with the hostkey.
*
- * @param hostkey the hostkey with which to decrypt this block
+ * @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
- * @returns the size of the decrypted block, -1 on error
+ * @return the size of the decrypted block, -1 on error
*/
-int
-GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey,
- const struct GNUNET_CRYPTO_RsaEncryptedData *block,
- void *result, uint16_t max)
+ssize_t
+GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey * key,
+ const struct GNUNET_CRYPTO_RsaEncryptedData *
+ block, void *result, size_t max)
{
gcry_sexp_t resultsexp;
gcry_sexp_t data;
unsigned char *tmp;
#if EXTRA_CHECKS
- GNUNET_assert (0 == gcry_pk_testkey (hostkey->sexp));
+ GNUNET_assert (0 == gcry_pk_testkey (key->sexp));
#endif
size = sizeof (struct GNUNET_CRYPTO_RsaEncryptedData);
GNUNET_assert (0 == gcry_mpi_scan (&val,
gcry_sexp_build (&data, &erroff,
"(enc-val(flags)(rsa(a %m)))", val));
gcry_mpi_release (val);
- GNUNET_assert (0 == gcry_pk_decrypt (&resultsexp, data, hostkey->sexp));
+ GNUNET_assert (0 == gcry_pk_decrypt (&resultsexp, data, key->sexp));
gcry_sexp_release (data);
/* resultsexp has format "(value %m)" */
GNUNET_assert (NULL !=
/**
* Sign a given block.
*
- * @param hostkey private key to use for the signing
+ * @param key private key to use for the signing
* @param purpose what to sign (size, purpose)
- * @param result where to write the signature
+ * @param sig where to write the signature
* @return GNUNET_SYSERR on error, GNUNET_OK on success
*/
int
-GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey,
+GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
const struct GNUNET_CRYPTO_RsaSignaturePurpose
*purpose, struct GNUNET_CRYPTO_RsaSignature *sig)
{
- 1], &hc, sizeof (GNUNET_HashCode));
GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
GNUNET_free (buff);
- GNUNET_assert (0 == gcry_pk_sign (&result, data, hostkey->sexp));
+ GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp));
gcry_sexp_release (data);
GNUNET_assert (0 == key_from_sexp (&rval, result, "rsa", "s"));
gcry_sexp_release (result);