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

📄 crypto.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 3 页
字号:
			state = PARSE_FINISHED;		    }		}	      /* reading key */	      if (state == PARSE_DATA)		{		  if (isxdigit(c))		    {		      ASSERT (hb_index >= 0 && hb_index < 2);		      hex_byte[hb_index++] = c;		      if (hb_index == 2)			{			  unsigned int u;			  ASSERT(sscanf((const char *)hex_byte, "%x", &u) == 1);			  *out++ = u;			  hb_index = 0;			  if (++count == keylen)			    state = PARSE_DATA_COMPLETE;			}		    }		  else if (isspace(c))		    ;		  else		    {		      msg (M_FATAL,			   (isprint (c) ? printable_char_fmt : unprintable_char_fmt),			   c, line_num, filename, count, onekeylen, keylen);		    }		}	      ++line_index;	    }	  ++cp;	  --size;	}    }  close (fd);  /*   * Normally we will read either 1 or 2 keys from file.   */  key2->n = count / onekeylen;  ASSERT (key2->n >= 0 && key2->n <= (int) SIZE (key2->keys));  if (must_succeed)    {      if (!key2->n)	msg (M_FATAL, "Insufficient key material or header text not found found in file '%s' (%d/%d/%d bytes found/min/max)",	     filename, count, onekeylen, keylen);      if (state != PARSE_FINISHED)	msg (M_FATAL, "Footer text not found in file '%s' (%d/%d/%d bytes found/min/max)",	     filename, count, onekeylen, keylen);    }  /* zero file read buffer */  buf_clear (&in);  if (key2->n)    warn_if_group_others_accessible (filename);#if 0  /* DEBUGGING */  {    int i;    printf ("KEY READ, n=%d\n", key2->n);    for (i = 0; i < (int) SIZE (key2->keys); ++i)      {	/* format key as ascii */	const char *fmt = format_hex_ex ((const uint8_t*)&key2->keys[i],					 sizeof (key2->keys[i]),					 0,					 16,					 "\n",					 &gc);	printf ("[%d]\n%s\n\n", i, fmt);      }  }#endif  /* pop our garbage collection level */  gc_free (&gc);}intread_passphrase_hash (const char *passphrase_file,		      const EVP_MD *digest,		      uint8_t *output,		      int len){  unsigned int outlen = 0;  EVP_MD_CTX md;  ASSERT (len >= EVP_MD_size (digest));  memset (output, 0, len);  EVP_DigestInit (&md, digest);  /* read passphrase file */  {    const int min_passphrase_size = 8;    uint8_t buf[64];    int total_size = 0;    int fd = open (passphrase_file, O_RDONLY);    if (fd == -1)      msg (M_ERR, "Cannot open passphrase file: '%s'", passphrase_file);    for (;;)      {	int size = read (fd, buf, sizeof (buf));	if (size == 0)	  break;	if (size == -1)	  msg (M_ERR, "Read error on passphrase file: '%s'",	       passphrase_file);	EVP_DigestUpdate (&md, buf, size);	total_size += size;      }    close (fd);    warn_if_group_others_accessible (passphrase_file);    if (total_size < min_passphrase_size)      msg (M_FATAL,	   "Passphrase file '%s' is too small (must have at least %d characters)",	   passphrase_file, min_passphrase_size);  }  EVP_DigestFinal (&md, output, &outlen);  EVP_MD_CTX_cleanup (&md);  return outlen;}/* * Write key to file, return number of random bits * written. */intwrite_key_file (const int nkeys, const char *filename){  struct gc_arena gc = gc_new ();  int fd, i;  int nbits = 0;  /* must be large enough to hold full key file */  struct buffer out = alloc_buf_gc (2048, &gc);  struct buffer nbits_head_text = alloc_buf_gc (128, &gc);  /* how to format the ascii file representation of key */  const int bytes_per_line = 16;  /* open key file */  fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);  if (fd == -1)    msg (M_ERR, "Cannot open shared secret file '%s' for write", filename);  buf_printf (&out, "%s\n", static_key_head);  for (i = 0; i < nkeys; ++i)    {      struct key key;      char* fmt;      /* generate random bits */      generate_key_random (&key, NULL);      /* format key as ascii */      fmt = format_hex_ex ((const uint8_t*)&key,			   sizeof (key),			   0,			   bytes_per_line,			   "\n",			   &gc);      /* increment random bits counter */      nbits += sizeof (key) * 8;      /* write to holding buffer */      buf_printf (&out, "%s\n", fmt);      /* zero memory which held key component (will be freed by GC) */      memset (fmt, 0, strlen(fmt));      CLEAR (key);    }  buf_printf (&out, "%s\n", static_key_foot);  /* write number of bits */  buf_printf (&nbits_head_text, "#\n# %d bit " PACKAGE_NAME " static key\n#\n", nbits);  buf_write_string_file (&nbits_head_text, filename, fd);  /* write key file, now formatted in out, to file */  buf_write_string_file (&out, filename, fd);  if (close (fd))    msg (M_ERR, "Close error on shared secret file %s", filename);  /* zero memory which held file content (memory will be freed by GC) */  buf_clear (&out);  /* pop our garbage collection level */  gc_free (&gc);  return nbits;}voidmust_have_n_keys (const char *filename, const char *option, const struct key2 *key2, int n){  if (key2->n < n)    msg (M_FATAL, "Key file '%s' used in --%s contains insufficient key material [keys found=%d required=%d] -- try generating a new key file with '" PACKAGE " --genkey --secret [file]', or use the existing key file in bidirectional mode by specifying --%s without a key direction parameter", filename, option, key2->n, n, option);}intascii2keydirection (const char *str){  if (!str)    return KEY_DIRECTION_BIDIRECTIONAL;  else if (!strcmp (str, "0"))    return KEY_DIRECTION_NORMAL;  else if (!strcmp (str, "1"))    return KEY_DIRECTION_INVERSE;  else    msg (M_USAGE, "Unknown key direction '%s' -- must be '0' or '1'",	 str);  return KEY_DIRECTION_BIDIRECTIONAL; /* NOTREACHED */}const char *keydirection2ascii (int kd, bool remote){  if (kd == KEY_DIRECTION_BIDIRECTIONAL)    return NULL;  else if (kd == KEY_DIRECTION_NORMAL)    return remote ? "1" : "0";  else if (kd == KEY_DIRECTION_INVERSE)    return remote ? "0" : "1";  else    {      ASSERT (0);    }  return NULL; /* NOTREACHED */}voidkey_direction_state_init (struct key_direction_state *kds, int key_direction){  CLEAR (*kds);  switch (key_direction)    {    case KEY_DIRECTION_NORMAL:      kds->out_key = 0;      kds->in_key = 1;      kds->need_keys = 2;      break;    case KEY_DIRECTION_INVERSE:      kds->out_key = 1;      kds->in_key = 0;      kds->need_keys = 2;      break;    case KEY_DIRECTION_BIDIRECTIONAL:      kds->out_key = 0;      kds->in_key = 0;      kds->need_keys = 1;      break;    default:      ASSERT (0);    }}voidverify_fix_key2 (struct key2 *key2, const struct key_type *kt, const char *shared_secret_file){  int i;  for (i = 0; i < key2->n; ++i)    {      /* Fix parity for DES keys and make sure not a weak key */      fixup_key (&key2->keys[i], kt);      /* This should be a very improbable failure */      if (!check_key (&key2->keys[i], kt))	msg (M_FATAL, "Key #%d in '%s' is bad.  Try making a new key with --genkey.",	     i+1, shared_secret_file);    }}/* given a key and key_type, write key to buffer */voidwrite_key (const struct key *key, const struct key_type *kt,	   struct buffer *buf){  ASSERT (kt->cipher_length <= MAX_CIPHER_KEY_LENGTH	  && kt->hmac_length <= MAX_HMAC_KEY_LENGTH);  ASSERT (buf_write (buf, &kt->cipher_length, 1));  ASSERT (buf_write (buf, &kt->hmac_length, 1));  ASSERT (buf_write (buf, key->cipher, kt->cipher_length));  ASSERT (buf_write (buf, key->hmac, kt->hmac_length));}/* * Given a key_type and buffer, read key from buffer. * Return: 1 on success *        -1 read failure *         0 on key length mismatch  */intread_key (struct key *key, const struct key_type *kt, struct buffer *buf){  uint8_t cipher_length;  uint8_t hmac_length;  CLEAR (*key);  if (!buf_read (buf, &cipher_length, 1))    goto read_err;  if (!buf_read (buf, &hmac_length, 1))    goto read_err;  if (!buf_read (buf, key->cipher, cipher_length))    goto read_err;  if (!buf_read (buf, key->hmac, hmac_length))    goto read_err;  if (cipher_length != kt->cipher_length || hmac_length != kt->hmac_length)    goto key_len_err;  return 1;read_err:  msg (D_TLS_ERRORS, "TLS Error: error reading key from remote");  return -1;key_len_err:  msg (D_TLS_ERRORS,       "TLS Error: key length mismatch, local cipher/hmac %d/%d, remote cipher/hmac %d/%d",       kt->cipher_length, kt->hmac_length, cipher_length, hmac_length);  return 0;}voidshow_available_ciphers (){  int nid;  printf ("The following ciphers and cipher modes are available\n"	  "for use with " PACKAGE_NAME ".  Each cipher shown below may be\n"	  "used as a parameter to the --cipher option.  The default\n"	  "key size is shown as well as whether or not it can be\n"          "changed with the --keysize directive.  Using a CBC mode\n"	  "is recommended.\n\n");  for (nid = 0; nid < 10000; ++nid)	/* is there a better way to get the size of the nid list? */    {      const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid);      if (cipher && cipher_ok (OBJ_nid2sn (nid)))	{	  const unsigned int mode = EVP_CIPHER_mode (cipher);	  if (mode == EVP_CIPH_CBC_MODE#ifdef ALLOW_NON_CBC_CIPHERS	      || mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE#endif	      )	    printf ("%s %d bit default key (%s)\n",		    OBJ_nid2sn (nid),		    EVP_CIPHER_key_length (cipher) * 8,		    ((EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ?		     "variable" : "fixed"));	}    }  printf ("\n");}voidshow_available_digests (){  int nid;  printf ("The following message digests are available for use with\n"	  PACKAGE_NAME ".  A message digest is used in conjunction with\n"	  "the HMAC function, to authenticate received packets.\n"	  "You can specify a message digest as parameter to\n"	  "the --auth option.\n\n");  for (nid = 0; nid < 10000; ++nid)    {      const EVP_MD *digest = EVP_get_digestbynid (nid);      if (digest)	{	  printf ("%s %d bit digest size\n",		  OBJ_nid2sn (nid), EVP_MD_size (digest) * 8);	}    }  printf ("\n");}/* * Enable crypto acceleration, if available */static bool engine_initialized = false; /* GLOBAL */void init_crypto_lib_engine (){  if (!engine_initialized)    {#if CRYPTO_ENGINE      /* Init available hardware crypto engines. */      msg (M_INFO, "Initializing OpenSSL hardware crypto engine functionality");      ENGINE_load_builtin_engines ();      ENGINE_register_all_complete ();#else      msg (M_WARN, "Note: OpenSSL hardware crypto engine functionality is not available");#endif      engine_initialized = true;    }}/* * This routine should have additional OpenSSL crypto library initialisations * used by both crypto and ssl components of OpenVPN. */void init_crypto_lib (){}void uninit_crypto_lib (){#if CRYPTO_ENGINE  if (engine_initialized)    {      ENGINE_cleanup ();      engine_initialized = false;    }#endif}/* * Random number functions, used in cases where we want * reasonably strong cryptographic random number generation * without depleting our entropy pool.  Used for random * IV values and a number of other miscellaneous tasks. */#define NONCE_SECRET_LEN 16static uint8_t nonce_data [SHA_DIGEST_LENGTH + NONCE_SECRET_LEN]; /* GLOBAL */voidprng_init (void){  if (!RAND_bytes (nonce_data, sizeof(nonce_data)))    msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for PRNG");}voidprng_bytes (uint8_t *output, int len){  SHA_CTX ctx;  mutex_lock_static (L_PRNG);  while (len > 0)    {      const int blen = min_int (len, SHA_DIGEST_LENGTH);      SHA1_Init (&ctx);      SHA1_Update (&ctx, nonce_data, sizeof (nonce_data));      SHA1_Final (nonce_data, &ctx);      memcpy (output, nonce_data, blen);      output += blen;      len -= blen;    }  mutex_unlock_static (L_PRNG);}/* an analogue to the random() function, but use prng_bytes */long intget_random(){  long int l;  prng_bytes ((unsigned char *)&l, sizeof(l));  if (l < 0)    l = -l;  return l;}const char *md5sum (uint8_t *buf, int len, int n_print_chars, struct gc_arena *gc){  uint8_t digest[MD5_DIGEST_LENGTH];  MD5 (buf, len, digest);  return format_hex (digest, MD5_DIGEST_LENGTH, n_print_chars, gc);}#ifndef USE_SSLvoidinit_ssl_lib (void){  ERR_load_crypto_strings ();  OpenSSL_add_all_algorithms ();  init_crypto_lib ();}voidfree_ssl_lib (void){  uninit_crypto_lib ();  EVP_cleanup ();  ERR_free_strings ();}#endif /* USE_SSL */#endif /* USE_CRYPTO */

⌨️ 快捷键说明

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