X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcrypto_rsa.c;h=5820065301f0a20b541600b151bc74ab91dd6ec8;hb=d47f834c1f2de41c9fba74a4b6928e7c8e0679e0;hp=19b1f8796a8a73c7853aa3d77e3195349f17764a;hpb=a0a43604cbbbef1dfeb625f2faec55c87f81459d;p=oweals%2Fgnunet.git diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c index 19b1f8796..582006530 100644 --- a/src/util/crypto_rsa.c +++ b/src/util/crypto_rsa.c @@ -186,43 +186,43 @@ key_from_sexp (gcry_mpi_t * array, /** * 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]); @@ -566,23 +566,46 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) 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 (GNUNET_YES == GNUNET_DISK_file_test (filename)) + while (GNUNET_YES != GNUNET_DISK_file_test (filename)) { - fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS); + 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; } cnt = 0; - while (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct RsaPrivateKeyBinaryEncoded), GNUNET_YES)) + while (GNUNET_YES != + GNUNET_DISK_file_lock (fd, 0, + sizeof (struct + RsaPrivateKeyBinaryEncoded), + GNUNET_YES)) { sleep (1); if (0 == ++cnt % 10) @@ -600,22 +623,29 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) 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); -#ifndef MINGW 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); -#endif - GNUNET_assert (GNUNET_YES != GNUNET_DISK_file_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_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 = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ); + 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); @@ -624,9 +654,12 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) cnt = 0; while (1) { - if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct RsaPrivateKeyBinaryEncoded), GNUNET_NO)) + if (GNUNET_YES != + GNUNET_DISK_file_lock (fd, 0, + sizeof (struct RsaPrivateKeyBinaryEncoded), + GNUNET_NO)) { - if (0 == ++cnt % 10) + if (0 == ++cnt % 60) { ec = errno; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -642,12 +675,15 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) 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); - 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 == GNUNET_DISK_file_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; } @@ -657,9 +693,12 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) { /* maybe we got the read lock before the hostkey generating process had a chance to get the write lock; give it up! */ - if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct RsaPrivateKeyBinaryEncoded))) - 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, @@ -678,22 +717,37 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) break; } enc = GNUNET_malloc (fs); - GNUNET_assert (fs == READ (fd, enc, fs)); + GNUNET_assert (fs == GNUNET_DISK_file_read (fd, enc, fs)); len = ntohs (enc->len); ret = NULL; if ((len != fs) || (NULL == (ret = rsa_decode_key (enc)))) { 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); + if (0 != UNLINK (filename)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "unlink", + filename); + } } GNUNET_free (enc); -#ifndef MINGW - if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct RsaPrivateKeyBinaryEncoded))) + if (GNUNET_YES != + GNUNET_DISK_file_unlock (fd, 0, + sizeof (struct RsaPrivateKeyBinaryEncoded))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); -#endif - GNUNET_assert (0 == GNUNET_DISK_file_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; } @@ -725,6 +779,8 @@ GNUNET_CRYPTO_rsa_encrypt (const void *block, 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)); @@ -751,18 +807,17 @@ GNUNET_CRYPTO_rsa_encrypt (const void *block, /** * 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 */ ssize_t -GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey, - const struct GNUNET_CRYPTO_RsaEncryptedData *block, - void *result, - size_t max) +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; @@ -773,7 +828,7 @@ GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey, 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, @@ -783,7 +838,7 @@ GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey, 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 != @@ -806,13 +861,13 @@ GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey, /** * 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) { @@ -836,7 +891,7 @@ GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey, - 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);