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

📄 crypto.c

📁 一个开源的VPN原码
💻 C
📖 第 1 页 / 共 3 页
字号:
    msg (M_SSLERR, "Cipher algorithm '%s' not found", ciphername);  return cipher;}static const EVP_MD *get_md (const char *digest){  const EVP_MD *md = NULL;  ASSERT (digest);  md = EVP_get_digestbyname (digest);  if (!md)    msg (M_SSLERR, "Message digest algorithm '%s' not found", digest);  return md;}static voidinit_cipher (EVP_CIPHER_CTX * ctx, const EVP_CIPHER * cipher,	     struct key *key, const struct key_type *kt, int enc,	     const char *prefix){  EVP_CIPHER_CTX_init (ctx);  if (!EVP_CipherInit_ov (ctx, cipher, NULL, NULL, enc))    msg (M_SSLERR, "EVP cipher init #1");#ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH  if (!EVP_CIPHER_CTX_set_key_length (ctx, kt->cipher_length))    msg (M_SSLERR, "EVP set key size");#endif  if (!EVP_CipherInit_ov (ctx, NULL, key->cipher, NULL, enc))    msg (M_SSLERR, "EVP cipher init #2");  msg (D_HANDSHAKE, "%s: Cipher '%s' initialized with %d bit key",       prefix,       OBJ_nid2sn (EVP_CIPHER_CTX_nid (ctx)),       EVP_CIPHER_CTX_key_length (ctx) * 8);  /* make sure we used a big enough key */  ASSERT (EVP_CIPHER_CTX_key_length (ctx) <= kt->cipher_length);  msg (D_SHOW_KEYS, "%s: CIPHER KEY: %s", prefix,       format_hex (key->cipher, kt->cipher_length, 0));  msg (D_CRYPTO_DEBUG, "%s: CIPHER block_size=%d iv_size=%d",       prefix,       EVP_CIPHER_CTX_block_size (ctx),       EVP_CIPHER_CTX_iv_length (ctx));}static voidinit_hmac (HMAC_CTX * ctx, const EVP_MD * digest,	   struct key *key, const struct key_type *kt, const char *prefix){  HMAC_Init (ctx, key->hmac, kt->hmac_length, digest);  msg (D_HANDSHAKE,       "%s: Using %d bit message digest '%s' for HMAC authentication",       prefix, HMAC_size (ctx) * 8, OBJ_nid2sn (EVP_MD_type (digest)));  /* make sure we used a big enough key */  ASSERT (HMAC_size (ctx) <= kt->hmac_length);  msg (D_SHOW_KEYS, "%s: HMAC KEY: %s", prefix,       format_hex (key->hmac, kt->hmac_length, 0));  msg (D_CRYPTO_DEBUG, "%s: HMAC size=%d block_size=%d",       prefix,       EVP_MD_size (digest),       EVP_MD_block_size (digest));}/* build a key_type */voidinit_key_type (struct key_type *kt, const char *ciphername,	       bool ciphername_defined, const char *authname,	       bool authname_defined, int keysize,	       bool cfb_ofb_allowed){  CLEAR (*kt);  if (ciphername && ciphername_defined)    {      kt->cipher = get_cipher (ciphername);      kt->cipher_length = EVP_CIPHER_key_length (kt->cipher);      if (keysize > 0 && keysize <= MAX_CIPHER_KEY_LENGTH)	kt->cipher_length = keysize;      /* check legal cipher mode */      {	const unsigned int mode = EVP_CIPHER_mode (kt->cipher);	if (!(mode == EVP_CIPH_CBC_MODE	      || (cfb_ofb_allowed && (mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE))))	  msg (M_FATAL, "Cipher %s uses a mode not supported by OpenVPN in your current configuration.  CBC mode is always supported, while CFB and OFB modes are supported only when using SSL/TLS authentication and key exchange mode.", ciphername);      }    }  else    {      msg (M_WARN,	   "******* WARNING *******: null cipher specified, no encryption will be used");    }  if (authname && authname_defined)    {      kt->digest = get_md (authname);      kt->hmac_length = EVP_MD_size (kt->digest);    }  else    {      msg (M_WARN,	   "******* WARNING *******: null MAC specified, no authentication will be used");    }}/* given a key and key_type, build a key_ctx */voidinit_key_ctx (struct key_ctx *ctx, struct key *key,	      const struct key_type *kt, int enc,	      const char *prefix){  CLEAR (*ctx);  if (kt->cipher && kt->cipher_length > 0)    {      ASSERT (ctx->cipher = (EVP_CIPHER_CTX *) malloc (sizeof (EVP_CIPHER_CTX)));      init_cipher (ctx->cipher, kt->cipher, key, kt, enc, prefix);    }  if (kt->digest && kt->hmac_length > 0)    {      ASSERT (ctx->hmac = (HMAC_CTX *) malloc (sizeof (HMAC_CTX)));      init_hmac (ctx->hmac, kt->digest, key, kt, prefix);    }}void free_key_ctx (struct key_ctx *ctx){  if (ctx->cipher)    {      EVP_CIPHER_CTX_cleanup (ctx->cipher);      free (ctx->cipher);      ctx->cipher = NULL;    }  if (ctx->hmac)    {      HMAC_CTX_cleanup (ctx->hmac);      free (ctx->hmac);      ctx->hmac = NULL;    }}void free_key_ctx_bi (struct key_ctx_bi *ctx){  free_key_ctx(&ctx->encrypt);  free_key_ctx(&ctx->decrypt);}/* * Return number of DES cblocks for the current * key type or 0 if not a DES cipher. */static intn_DES_cblocks (const struct key_type *kt){  int ret = 0;  const char *name = OBJ_nid2sn (EVP_CIPHER_nid (kt->cipher));  if (name)    {      if (!strncmp (name, "DES-", 4))	{	  ret = EVP_CIPHER_key_length (kt->cipher) / sizeof (DES_cblock);	}      else if (!strncmp (name, "DESX-", 5))	{	  ret = 1;	}    }  msg (D_CRYPTO_DEBUG, "CRYPTO INFO: n_DES_cblocks=%d", ret);  return ret;}static boolcheck_key_DES (struct key *key, const struct key_type *kt, int ndc){  int i;  struct buffer b;  buf_set_read (&b, key->cipher, kt->cipher_length);  for (i = 0; i < ndc; ++i)    {      DES_cblock *dc = (DES_cblock*) buf_read_alloc (&b, sizeof (DES_cblock));      if (!dc)	{	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: insufficient key material");	  return false;	}      if (DES_is_weak_key(dc))	{	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: weak key detected");	  return false;	}      if (!DES_check_key_parity (dc))	{	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: check_key_DES: bad parity detected");	  return false;	}    }  return true;}static voidfixup_key_DES (struct key *key, const struct key_type *kt, int ndc){  int i;  struct buffer b;  buf_set_read (&b, key->cipher, kt->cipher_length);  for (i = 0; i < ndc; ++i)    {      DES_cblock *dc = (DES_cblock*) buf_read_alloc(&b, sizeof(DES_cblock));      if (!dc)	{	  msg (D_CRYPT_ERRORS, "CRYPTO INFO: fixup_key_DES: insufficient key material");	  return;	}      DES_set_odd_parity (dc);    }}static boolkey_is_zero(struct key *key, const struct key_type *kt){  int i;  for (i = 0; i < kt->cipher_length; ++i)    if (key->cipher[i])      return false;  msg (D_CRYPT_ERRORS, "CRYPTO INFO: WARNING: zero key detected");  return true;}/* * Make sure that cipher key is a valid key for current key_type. */boolcheck_key (struct key *key, const struct key_type *kt){  if (kt->cipher)    {      /*       * Check for zero key       */      if (key_is_zero(key, kt))	return false;      /*       * Check for weak or semi-weak DES keys.       */      {	const int ndc = n_DES_cblocks (kt);	if (ndc)	  return check_key_DES (key, kt, ndc);	else	  return true;      }    }  return true;}/* * Make safe mutations to key to ensure it is valid, * such as ensuring correct parity on DES keys. * * This routine cannot guarantee it will generate a good * key.  You must always call check_key after this routine * to make sure. */ voidfixup_key (struct key *key, const struct key_type *kt){  if (kt->cipher)    {      const struct key orig = *key;      const int ndc = n_DES_cblocks (kt);      if (ndc)	fixup_key_DES (key, kt, ndc);      if (check_debug_level (D_CRYPTO_DEBUG))	{	  if (memcmp (orig.cipher, key->cipher, kt->cipher_length))	    msg (D_CRYPTO_DEBUG, "CRYPTO INFO: fixup_key: before=%s after=%s",		 format_hex (orig.cipher, kt->cipher_length, 0),		 format_hex (key->cipher, kt->cipher_length, 0));	}    }}voidcheck_replay_iv_consistency(const struct key_type *kt, bool packet_id, bool iv){  if (cfb_ofb_mode (kt) && !(packet_id && iv))    msg (M_FATAL, "--no-replay or --no-iv cannot be used with a CFB or OFB mode cipher");}boolcfb_ofb_mode(const struct key_type* kt){  if (kt->cipher) {    const unsigned int mode = EVP_CIPHER_mode (kt->cipher);    return mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE;  } else    return false;}/* * Generate a random key.  If key_type is provided, make * sure generated key is valid for key_type. */voidgenerate_key_random (struct key *key, const struct key_type *kt){  int cipher_len = MAX_CIPHER_KEY_LENGTH;  int hmac_len = MAX_HMAC_KEY_LENGTH;  do {    CLEAR (*key);    if (kt)      {	if (kt->cipher && kt->cipher_length > 0 && kt->cipher_length <= cipher_len)	  cipher_len = kt->cipher_length;	if (kt->digest && kt->hmac_length > 0 && kt->hmac_length <= hmac_len)	  hmac_len = kt->hmac_length;      }    ASSERT (RAND_bytes (key->cipher, cipher_len));    ASSERT (RAND_bytes (key->hmac, hmac_len));    if (kt)      fixup_key (key, kt);  } while (kt && !check_key (key, kt));}voidrandomize_iv (uint8_t *iv){  if (RAND_bytes (iv, EVP_MAX_IV_LENGTH) < 0)    msg (M_SSLERR, "RAND_bytes failed");}voidtest_crypto (const struct crypto_options *co, struct frame* frame){  int i, j;  struct buffer src = alloc_buf_gc (MTU_SIZE (frame));  struct buffer work = alloc_buf_gc (BUF_SIZE (frame));  struct buffer encrypt_workspace = alloc_buf_gc (BUF_SIZE (frame));  struct buffer decrypt_workspace = alloc_buf_gc (BUF_SIZE (frame));  struct buffer buf = clear_buf();  /* init work */  ASSERT (buf_init (&work, EXTRA_FRAME (frame)));  msg (M_INFO, "Entering OpenVPN crypto self-test mode.");  for (i = 1; i <= MTU_SIZE (frame); ++i)    {      const time_t current = time (NULL);      uint8_t iv_save[EVP_MAX_IV_LENGTH];      msg (M_INFO, "TESTING ENCRYPT/DECRYPT of packet length=%d", i);      /*       * Load src with random data.       */      ASSERT (buf_init (&src, 0));      ASSERT (i <= src.capacity);      src.len = i;      ASSERT (RAND_pseudo_bytes (BPTR (&src), BLEN (&src)));      /* copy source to input buf */      buf = work;      memcpy (buf_write_alloc (&buf, BLEN (&src)), BPTR (&src), BLEN (&src));      /* save IV */      memcpy (iv_save, co->iv, EVP_MAX_IV_LENGTH);      /* encrypt */      openvpn_encrypt (&buf, encrypt_workspace, co, frame, current);

⌨️ 快捷键说明

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