⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hostkey_gcrypt.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/*     This file is part of GNUnet.     (C) 2001, 2002, 2003, 2004, 2005, 2006 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 2, 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/hostkey_gcrypt.c * @brief public key cryptography (RSA) with libgcrypt * @author Christian Grothoff * * Note that the code locks often needlessly on the gcrypt-locking api. * One would think that simple MPI operations should not require locking * (since only global operations on the random pool must be locked, * strictly speaking).  But libgcrypt does sometimes require locking in * unexpected places, so the safe solution is to always lock even if it * is not required.  The performance impact is minimal anyway. */#include "platform.h"#include <gcrypt.h>#include "gnunet_util.h"#include "gnunet_util_crypto.h"#include "locking_gcrypt.h"/** * Use LOG_ERROR for anything that should never happen * (indicates a bug). */#define LOG_ERROR (GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_DEVELOPER | GNUNET_GE_BULK)/** * The private information of an RSA key pair. */struct GNUNET_RSA_PrivateKey{  gcry_sexp_t sexp;};#define HOSTKEY_LEN 2048#define EXTRA_CHECKS ALLOW_EXTRA_CHECKS/** * 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(ectx, level, cmd, rc) do { GNUNET_GE_LOG(ectx, level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0);/** * Die with an error message that indicates * a failure of the command 'cmd' with the message given * by gcry_strerror(rc). */#define DIE_GCRY(ectx, cmd, rc) do { GNUNET_GE_LOG(ectx, GNUNET_GE_FATAL | GNUNET_GE_USER | GNUNET_GE_DEVELOPER | GNUNET_GE_IMMEDIATE, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); abort(); } while(0);/** * If target != size, move target bytes to the * end of the size-sized buffer and zero out the * first target-size bytes. */static voidadjust (unsigned char *buf, size_t size, size_t target){  if (size < target)    {      memmove (&buf[target - size], buf, size);      memset (buf, 0, target - size);    }}/** * This HostKey implementation uses RSA. */struct GNUNET_RSA_PrivateKey *GNUNET_RSA_create_key (){  struct GNUNET_RSA_PrivateKey *ret;  gcry_sexp_t s_key;  gcry_sexp_t s_keyparam;  int rc;  GNUNET_lock_gcrypt_ ();  rc = gcry_sexp_build (&s_keyparam,                        NULL,                        "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))",                        HOSTKEY_LEN);  if (rc)    {      LOG_GCRY (NULL, LOG_ERROR, "gcry_sexp_build", rc);      GNUNET_unlock_gcrypt_ ();      return NULL;    }  rc = gcry_pk_genkey (&s_key, s_keyparam);  gcry_sexp_release (s_keyparam);  if (rc)    {      LOG_GCRY (NULL, LOG_ERROR, "gcry_pk_genkey", rc);      GNUNET_unlock_gcrypt_ ();      return NULL;    }#if EXTRA_CHECKS  if ((rc = gcry_pk_testkey (s_key)))    {      LOG_GCRY (NULL, LOG_ERROR, "gcry_pk_testkey", rc);      GNUNET_unlock_gcrypt_ ();      return NULL;    }#endif  GNUNET_unlock_gcrypt_ ();  ret = GNUNET_malloc (sizeof (struct GNUNET_RSA_PrivateKey));  ret->sexp = s_key;  return ret;}/** * Free memory occupied by hostkey */voidGNUNET_RSA_free_key (struct GNUNET_RSA_PrivateKey *hostkey){  GNUNET_lock_gcrypt_ ();  gcry_sexp_release (hostkey->sexp);  GNUNET_unlock_gcrypt_ ();  GNUNET_free (hostkey);}static intkey_from_sexp (gcry_mpi_t * array,               gcry_sexp_t sexp, const char *topname, const char *elems){  gcry_sexp_t list, l2;  const char *s;  int i, idx;  GNUNET_lock_gcrypt_ ();  list = gcry_sexp_find_token (sexp, topname, 0);  if (!list)    {      GNUNET_unlock_gcrypt_ ();      return 1;    }  l2 = gcry_sexp_cadr (list);  gcry_sexp_release (list);  list = l2;  if (!list)    {      GNUNET_unlock_gcrypt_ ();      return 2;    }  idx = 0;  for (s = elems; *s; s++, idx++)    {      l2 = gcry_sexp_find_token (list, s, 1);      if (!l2)        {          for (i = 0; i < idx; i++)            {              gcry_free (array[i]);              array[i] = NULL;            }          gcry_sexp_release (list);          GNUNET_unlock_gcrypt_ ();          return 3;             /* required parameter not found */        }      array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);      gcry_sexp_release (l2);      if (!array[idx])        {          for (i = 0; i < idx; i++)            {              gcry_free (array[i]);              array[i] = NULL;            }          gcry_sexp_release (list);          GNUNET_unlock_gcrypt_ ();          return 4;             /* required parameter is invalid */        }    }  gcry_sexp_release (list);  GNUNET_unlock_gcrypt_ ();  return 0;}/** * Extract the public key of the host. * @param hostkey the hostkey to extract into the result. * @param result where to write the result. */voidGNUNET_RSA_get_public_key (const struct GNUNET_RSA_PrivateKey *hostkey,                           GNUNET_RSA_PublicKey * result){  gcry_mpi_t skey[2];  size_t size;  int rc;  GNUNET_lock_gcrypt_ ();  rc = key_from_sexp (skey, hostkey->sexp, "public-key", "ne");  if (rc)    rc = key_from_sexp (skey, hostkey->sexp, "private-key", "ne");  if (rc)    rc = key_from_sexp (skey, hostkey->sexp, "rsa", "ne");  if (rc)    DIE_GCRY (NULL, "key_from_sexp", rc);  result->len =    htons (sizeof (GNUNET_RSA_PublicKey) - sizeof (result->padding));  result->sizen = htons (GNUNET_RSA_DATA_ENCODING_LEN);  result->padding = 0;  size = GNUNET_RSA_DATA_ENCODING_LEN;  rc = gcry_mpi_print (GCRYMPI_FMT_USG,                       &result->key[0], size, &size, skey[0]);  if (rc)    DIE_GCRY (NULL, "gcry_mpi_print", rc);  adjust (&result->key[0], size, GNUNET_RSA_DATA_ENCODING_LEN);  size = GNUNET_RSA_KEY_LEN - GNUNET_RSA_DATA_ENCODING_LEN;  rc = gcry_mpi_print (GCRYMPI_FMT_USG,                       &result->key[GNUNET_RSA_DATA_ENCODING_LEN], size,                       &size, skey[1]);  if (rc)    DIE_GCRY (NULL, "gcry_mpi_print", rc);  adjust (&result->key[GNUNET_RSA_DATA_ENCODING_LEN], size,          GNUNET_RSA_KEY_LEN - GNUNET_RSA_DATA_ENCODING_LEN);  gcry_mpi_release (skey[0]);  gcry_mpi_release (skey[1]);  GNUNET_unlock_gcrypt_ ();}/** * Internal: publicKey => RSA-Key. * * Note that the return type is not actually a private * key but rather an sexpression for the public key! */static struct GNUNET_RSA_PrivateKey *public2PrivateKey (const GNUNET_RSA_PublicKey * publicKey){  struct GNUNET_RSA_PrivateKey *ret;  gcry_sexp_t result;  gcry_mpi_t n;  gcry_mpi_t e;  size_t size;  size_t erroff;  int rc;  if ((ntohs (publicKey->sizen) != GNUNET_RSA_DATA_ENCODING_LEN) ||      (ntohs (publicKey->len) !=       sizeof (GNUNET_RSA_PublicKey) - sizeof (publicKey->padding)))    {      GNUNET_GE_BREAK (NULL, 0);      return NULL;    }  size = GNUNET_RSA_DATA_ENCODING_LEN;  GNUNET_lock_gcrypt_ ();  rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG, &publicKey->key[0], size, &size);  if (rc)    {      LOG_GCRY (NULL, LOG_ERROR, "gcry_mpi_scan", rc);      GNUNET_unlock_gcrypt_ ();      return NULL;    }  size = GNUNET_RSA_KEY_LEN - GNUNET_RSA_DATA_ENCODING_LEN;  rc = gcry_mpi_scan (&e,                      GCRYMPI_FMT_USG,                      &publicKey->key[GNUNET_RSA_DATA_ENCODING_LEN], size,                      &size);  if (rc)    {      LOG_GCRY (NULL, LOG_ERROR, "gcry_mpi_scan", rc);      gcry_mpi_release (n);      GNUNET_unlock_gcrypt_ ();      return NULL;    }  rc = gcry_sexp_build (&result,                        &erroff, "(public-key(rsa(n %m)(e %m)))", n, e);  gcry_mpi_release (n);  gcry_mpi_release (e);  if (rc)    {      LOG_GCRY (NULL, LOG_ERROR, "gcry_sexp_build", rc);        /* erroff gives more info */      GNUNET_unlock_gcrypt_ ();      return NULL;    }  GNUNET_unlock_gcrypt_ ();  ret = GNUNET_malloc (sizeof (struct GNUNET_RSA_PrivateKey));  ret->sexp = result;  return ret;}/** * Encode the private key in a format suitable for * storing it into a file. * @returns encoding of the private key. *    The first 4 bytes give the size of the array, as usual. */GNUNET_RSA_PrivateKeyEncoded *GNUNET_RSA_encode_key (const struct GNUNET_RSA_PrivateKey * hostkey){  GNUNET_RSA_PrivateKeyEncoded *retval;  gcry_mpi_t pkv[6];  void *pbu[6];  size_t sizes[6];  int rc;  int i;  int size;  GNUNET_lock_gcrypt_ ();#if EXTRA_CHECKS  if (gcry_pk_testkey (hostkey->sexp))    {      GNUNET_GE_BREAK (NULL, 0);      GNUNET_unlock_gcrypt_ ();      return NULL;    }#endif  memset (pkv, 0, sizeof (gcry_mpi_t) * 6);  rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpqu");  if (rc)    rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpqu");  if (rc)    rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpq");  if (rc)    rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpq");  if (rc)    rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "ned");  if (rc)    rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "ned");  if (rc)    {      LOG_GCRY (NULL, LOG_ERROR, "key_from_sexp", rc);      GNUNET_unlock_gcrypt_ ();      return NULL;    }  size = sizeof (GNUNET_RSA_PrivateKeyEncoded);  for (i = 0; i < 6; i++)    {      if (pkv[i] != NULL)        {          rc = gcry_mpi_aprint (GCRYMPI_FMT_USG,                                (unsigned char **) &pbu[i],                                &sizes[i], pkv[i]);          size += sizes[i];          if (rc)            {              LOG_GCRY (NULL, LOG_ERROR, "gcry_mpi_aprint", rc);              while (i > 0)                if (pbu[i] != NULL)                  free (pbu[--i]);              for (i = 0; i < 6; i++)                if (pkv[i] != NULL)                  gcry_mpi_release (pkv[i]);              GNUNET_unlock_gcrypt_ ();              return NULL;            }        }      else        {          pbu[i] = NULL;          sizes[i] = 0;        }    }  GNUNET_GE_ASSERT (NULL, size < 65536);  retval = GNUNET_malloc (size);  retval->len = htons (size);  i = 0;  retval->sizen = htons (sizes[0]);  memcpy (&((char *) (&retval[1]))[i], pbu[0], sizes[0]);  i += sizes[0];  retval->sizee = htons (sizes[1]);  memcpy (&((char *) (&retval[1]))[i], pbu[1], sizes[1]);  i += sizes[1];  retval->sized = htons (sizes[2]);  memcpy (&((char *) (&retval[1]))[i], pbu[2], sizes[2]);  i += sizes[2];  /* swap p and q! */  retval->sizep = htons (sizes[4]);  memcpy (&((char *) (&retval[1]))[i], pbu[4], sizes[4]);  i += sizes[4];  retval->sizeq = htons (sizes[3]);  memcpy (&((char *) (&retval[1]))[i], pbu[3], sizes[3]);  i += sizes[3];  retval->sizedmp1 = htons (0);  retval->sizedmq1 = htons (0);  memcpy (&((char *) (&retval[1]))[i], pbu[5], sizes[5]);  for (i = 0; i < 6; i++)    {      if (pkv[i] != NULL)        gcry_mpi_release (pkv[i]);      if (pbu[i] != NULL)        free (pbu[i]);    }  GNUNET_unlock_gcrypt_ ();  return retval;}/** * Decode the private key from the file-format back * to the "normal", internal format. */struct GNUNET_RSA_PrivateKey *GNUNET_RSA_decode_key (const GNUNET_RSA_PrivateKeyEncoded * encoding){  struct GNUNET_RSA_PrivateKey *ret;  gcry_sexp_t res;  gcry_mpi_t n, e, d, p, q, u;  int rc;  size_t size;  int pos;  pos = 0;  size = ntohs (encoding->sizen);  GNUNET_lock_gcrypt_ ();  rc = gcry_mpi_scan (&n,                      GCRYMPI_FMT_USG,                      &((const unsigned char *) (&encoding[1]))[pos],                      size, &size);  pos += ntohs (encoding->sizen);  if (rc)    {      LOG_GCRY (NULL, LOG_ERROR, "gcry_mpi_scan", rc);      GNUNET_unlock_gcrypt_ ();      return NULL;    }  size = ntohs (encoding->sizee);  rc = gcry_mpi_scan (&e,                      GCRYMPI_FMT_USG,                      &((const unsigned char *) (&encoding[1]))[pos],                      size, &size);  pos += ntohs (encoding->sizee);  if (rc)    {      LOG_GCRY (NULL, LOG_ERROR, "gcry_mpi_scan", rc);      gcry_mpi_release (n);      GNUNET_unlock_gcrypt_ ();      return NULL;    }  size = ntohs (encoding->sized);  rc = gcry_mpi_scan (&d,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -