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

📄 ssl.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 5 页
字号:
      if (!buf->len)	{	  msg (D_TLS_ERRORS,	       "TLS Error: incoming packet authentication failed from %s",	       print_sockaddr (from, &gc));	  gc_free (&gc);	  return false;	}    }  /* advance buffer pointer past opcode & session_id since our caller     already read it */  buf_advance (buf, SID_SIZE + 1);  gc_free (&gc);  return true;}/* * For debugging, print contents of key_source2 structure. */static voidkey_source_print (const struct key_source *k,		  const char *prefix){  struct gc_arena gc = gc_new ();  msg (D_SHOW_KEY_SOURCE,       "%s pre_master: %s",       prefix,       format_hex (k->pre_master, sizeof (k->pre_master), 0, &gc));  msg (D_SHOW_KEY_SOURCE,       "%s random1: %s",       prefix,       format_hex (k->random1, sizeof (k->random1), 0, &gc));  msg (D_SHOW_KEY_SOURCE,       "%s random2: %s",       prefix,       format_hex (k->random2, sizeof (k->random2), 0, &gc));  gc_free (&gc);}static voidkey_source2_print (const struct key_source2 *k){  key_source_print (&k->client, "Client");  key_source_print (&k->server, "Server");}/* * Use the TLS PRF function for generating data channel keys. * This code is taken from the OpenSSL library. * * TLS generates keys as such: * * master_secret[48] = PRF(pre_master_secret[48], "master secret", *                         ClientHello.random[32] + ServerHello.random[32]) * * key_block[] = PRF(SecurityParameters.master_secret[48], *                 "key expansion", *                 SecurityParameters.server_random[32] + *                 SecurityParameters.client_random[32]); * * Notes: * * (1) key_block contains a full set of 4 keys. * (2) The pre-master secret is generated by the client. */static voidtls1_P_hash(const EVP_MD *md,	    const uint8_t *sec,	    int sec_len,	    const uint8_t *seed,	    int seed_len,	    uint8_t *out,	    int olen){  struct gc_arena gc = gc_new ();  int chunk,n;  unsigned int j;  HMAC_CTX ctx;  HMAC_CTX ctx_tmp;  uint8_t A1[EVP_MAX_MD_SIZE];  unsigned int A1_len;  const int olen_orig = olen;  const uint8_t *out_orig = out;	  msg (D_SHOW_KEY_SOURCE, "tls1_P_hash sec: %s", format_hex (sec, sec_len, 0, &gc));  msg (D_SHOW_KEY_SOURCE, "tls1_P_hash seed: %s", format_hex (seed, seed_len, 0, &gc));  chunk=EVP_MD_size(md);  HMAC_CTX_init(&ctx);  HMAC_CTX_init(&ctx_tmp);  HMAC_Init_ex(&ctx,sec,sec_len,md, NULL);  HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL);  HMAC_Update(&ctx,seed,seed_len);  HMAC_Final(&ctx,A1,&A1_len);  n=0;  for (;;)    {      HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */      HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */      HMAC_Update(&ctx,A1,A1_len);      HMAC_Update(&ctx_tmp,A1,A1_len);      HMAC_Update(&ctx,seed,seed_len);      if (olen > chunk)	{	  HMAC_Final(&ctx,out,&j);	  out+=j;	  olen-=j;	  HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */	}      else	/* last one */	{	  HMAC_Final(&ctx,A1,&A1_len);	  memcpy(out,A1,olen);	  break;	}    }  HMAC_CTX_cleanup(&ctx);  HMAC_CTX_cleanup(&ctx_tmp);  CLEAR (A1);  msg (D_SHOW_KEY_SOURCE, "tls1_P_hash out: %s", format_hex (out_orig, olen_orig, 0, &gc));  gc_free (&gc);}static voidtls1_PRF(uint8_t *label,	 int label_len,	 const uint8_t *sec,	 int slen,	 uint8_t *out1,	 int olen){  struct gc_arena gc = gc_new ();  const EVP_MD *md5 = EVP_md5();  const EVP_MD *sha1 = EVP_sha1();  int len,i;  const uint8_t *S1,*S2;  uint8_t *out2;  out2 = (uint8_t *) gc_malloc (olen, false, &gc);  len=slen/2;  S1=sec;  S2= &(sec[len]);  len+=(slen&1); /* add for odd, make longer */	  tls1_P_hash(md5 ,S1,len,label,label_len,out1,olen);  tls1_P_hash(sha1,S2,len,label,label_len,out2,olen);  for (i=0; i<olen; i++)    out1[i]^=out2[i];  memset (out2, 0, olen);  msg (D_SHOW_KEY_SOURCE, "tls1_PRF out[%d]: %s", olen, format_hex (out1, olen, 0, &gc));  gc_free (&gc);}static voidopenvpn_PRF (const uint8_t *secret,	     int secret_len,	     const char *label,	     const uint8_t *client_seed,	     int client_seed_len,	     const uint8_t *server_seed,	     int server_seed_len,	     const struct session_id *client_sid,	     const struct session_id *server_sid,	     uint8_t *output,	     int output_len){  /* concatenate seed components */  struct buffer seed = alloc_buf (strlen (label)				  + client_seed_len				  + server_seed_len				  + SID_SIZE * 2);  ASSERT (buf_write (&seed, label, strlen (label)));  ASSERT (buf_write (&seed, client_seed, client_seed_len));  ASSERT (buf_write (&seed, server_seed, server_seed_len));  if (client_sid)      ASSERT (buf_write (&seed, client_sid->id, SID_SIZE));  if (server_sid)      ASSERT (buf_write (&seed, server_sid->id, SID_SIZE));  /* compute PRF */  tls1_PRF (BPTR(&seed), BLEN(&seed), secret, secret_len, output, output_len);  buf_clear (&seed);  free_buf (&seed);}/*  * Using source entropy from local and remote hosts, mix into * master key. */static boolgenerate_key_expansion (struct key_ctx_bi *key,			const struct key_type *key_type,			const struct key_source2 *key_src,			const struct session_id *client_sid,			const struct session_id *server_sid,			bool server){  uint8_t master[48];  struct key2 key2;  bool ret = false;  int i;  CLEAR (master);  CLEAR (key2);  /* debugging print of source key material */  key_source2_print (key_src);  /* compute master secret */  openvpn_PRF (key_src->client.pre_master,	       sizeof(key_src->client.pre_master),	       KEY_EXPANSION_ID " master secret",	       key_src->client.random1,	       sizeof(key_src->client.random1),	       key_src->server.random1,	       sizeof(key_src->server.random1),	       NULL,	       NULL,	       master,	       sizeof(master));    /* compute key expansion */  openvpn_PRF (master,	       sizeof(master),	       KEY_EXPANSION_ID " key expansion",	       key_src->client.random2,	       sizeof(key_src->client.random2),	       key_src->server.random2,	       sizeof(key_src->server.random2),	       client_sid,	       server_sid,	       (uint8_t*)key2.keys,	       sizeof(key2.keys));  key2.n = 2;  key2_print (&key2, key_type, "Master Encrypt", "Master Decrypt");  /* check for weak keys */  for (i = 0; i < 2; ++i)    {      fixup_key (&key2.keys[i], key_type);      if (!check_key (&key2.keys[i], key_type))	{	  msg (D_TLS_ERRORS, "TLS Error: Bad dynamic key generated");	  goto exit;	}    }  /* Initialize OpenSSL key contexts */  ASSERT (server == true || server == false);  init_key_ctx (&key->encrypt,		&key2.keys[(int)server],		key_type,		DO_ENCRYPT,		"Data Channel Encrypt");  init_key_ctx (&key->decrypt,		&key2.keys[1-(int)server],		key_type,		DO_DECRYPT,		"Data Channel Decrypt");  ret = true; exit:  CLEAR (master);  CLEAR (key2);  return ret;}static voidrandom_bytes_to_buf (struct buffer *buf,		     uint8_t *out,		     int outlen){  if (!RAND_bytes (out, outlen))    msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for key generation [SSL]");  ASSERT (buf_write (buf, out, outlen));}static voidkey_source2_randomize_write (struct key_source2 *k2,			     struct buffer *buf,			     bool server){  struct key_source *k = &k2->client;  if (server)    k = &k2->server;  CLEAR (*k);  if (!server)    random_bytes_to_buf (buf, k->pre_master, sizeof (k->pre_master));  random_bytes_to_buf (buf, k->random1, sizeof (k->random1));  random_bytes_to_buf (buf, k->random2, sizeof (k->random2));}static intkey_source2_read (struct key_source2 *k2,		  struct buffer *buf,		  bool server){  struct key_source *k = &k2->client;  if (!server)    k = &k2->server;  CLEAR (*k);  if (server)    {      if (!buf_read (buf, k->pre_master, sizeof (k->pre_master)))	return 0;    }  if (!buf_read (buf, k->random1, sizeof (k->random1)))    return 0;  if (!buf_read (buf, k->random2, sizeof (k->random2)))    return 0;  return 1;}/* * Macros for key_state_soft_reset & tls_process */#define ks      (&session->key[KS_PRIMARY])	/* primary key */#define ks_lame (&session->key[KS_LAME_DUCK])	/* retiring key *//* true if no in/out acknowledgements pending */#define FULL_SYNC \  (reliable_empty(ks->send_reliable) && reliable_ack_empty (ks->rec_ack))/* * Move the active key to the lame duck key and reinitialize the * active key. */static voidkey_state_soft_reset (struct tls_session *session){  ks->must_die = now + session->opt->transition_window; /* remaining lifetime of old key */  key_state_free (ks_lame, false);  *ks_lame = *ks;  key_state_init (session, ks);  ks->session_id_remote = ks_lame->session_id_remote;  ks->remote_addr = ks_lame->remote_addr;}/* * This is the primary routine for processing TLS stuff inside the * the main event loop (see openvpn.c).  When this routine exits * with non-error status, it will set *wakeup to the number of seconds * when it wants to be called again. * * Return value is true if we have placed a packet in *to_link which we * want to send to our peer. */static booltls_process (struct tls_multi *multi,	     struct tls_session *session,	     struct buffer *to_link,	     struct sockaddr_in *to_link_addr,	     struct link_socket_info *to_link_socket_info,	     interval_t *wakeup){  struct gc_arena gc = gc_new ();  struct buffer *buf;  bool state_change = false;  bool active = false;  /* Make sure we were initialized and that we're not in an error state */  ASSERT (ks->state != S_UNDEF);  ASSERT (ks->state != S_ERROR);  ASSERT (session_id_defined (&session->session_id));  /* Should we trigger a soft reset? -- new key, keeps old key for a while */  if (ks->state >= S_ACTIVE &&      ((session->opt->renegotiate_seconds	&& now >= ks->established + session->opt->renegotiate_seconds)       || (session->opt->renegotiate_bytes	   && ks->n_bytes >= session->opt->renegotiate_bytes)       || (session->opt->renegotiate_packets	   && ks->n_packets >= session->opt->renegotiate_packets)       || (packet_id_close_to_wrapping (&ks->packet_id.send))))    {      msg (D_TLS_DEBUG_LOW, "TLS: soft reset sec=%d bytes=%d/%d pkts=%d/%d",	   (int)(ks->established + session->opt->renegotiate_seconds - now),	   ks->n_bytes, session->opt->renegotiate_bytes,	   ks->n_packets, session->opt->renegotiate_packets);      key_state_soft_reset (session);    }  /* Kill lame duck key transition_window seconds after primary key negotiation */  if (lame_duck_must_die (session, wakeup)) {	key_state_free (ks_lame, true);	msg (D_TLS_DEBUG_LOW, "TLS: tls_process: killed expiring key");  }  //mutex_cycle (multi->mutex);  do    {      update_time ();      msg (D_TLS_DEBUG, "TLS: tls_process: chg=%d ks=%s lame=%s to_link->len=%d wakeup=%d",	   state_change,	   state_name (ks->state),	   state_name (ks_lame->state),	   to_link->len,	   *wakeup);      state_change = false;      /*       * TLS activity is finished once we get to S_ACTIVE,       * though we will still process acknowledgements.       *       * CHANGED with 2.0 -> now we may send tunnel configuration       * info over the control channel.       */      if (true)	{	  /* Initial handshake */	  if (ks->state == S_INITIAL)	    {	      buf = reliable_get_buf_output_sequenced (ks->send_reliable);	      if (buf)		{		  ks->must_negotiate = now + session->opt->handshake_window;		  /* null buffer */		  reliable_mark_active_outgoing (ks->send_reliable, buf, ks->initial_opcode);		  INCR_GENERATED;	      		  ks->state = S_PRE_START;		  state_change = true;		  msg (D_TLS_DEBUG, "TLS: Initial Handshake, sid=%s",		       session_id_print (&session->session_id, &gc));		}	    }	  /* Are we timed out on receive? */	  if (now >= ks->must_negotiate)	    {	      if (ks->state < S_ACTIVE)		{		  msg (D_TLS_ERRORS,		       "TLS Error: TLS key negotiation failed to occur within %d seconds",		       session->opt->handshake_window);		  goto error;		}	      else /* assume that ks->state == S_ACTIVE */		{		  msg (D_TLS_DEBUG_MED, "STATE S_NORMAL");		  ks->state = S_NORMAL;		  ks->must_negotiate = 0;		}	    }	  /* Wait for Initial Handshake ACK */	  if (ks->state == S_PRE_START && FULL_SYNC)	    {	      ks->state = S_START;	      state_change = true;	      msg (D_TLS_DEBUG_MED, "STATE S_START");	    }	  /* Wait for ACK */	  if (((ks->state == S_GOT_KEY && !session->opt->server) ||	       (ks->state == S_SENT_KEY && session->opt->server)))	    {	      if (FULL_SYNC)		{		  ks->established = now;		  msg (D_TLS_DEBUG_MED, "STATE S_ACTIVE");		  if (check_debug_level (D_HANDSHAKE))		    print_details (ks->ssl, "Control Channel:");		  state_change = true;		  ks->state = S_ACTIVE;		  INCR_SUCCESS;		  /* Set outgoing address for data channel packets */		  link_socket_set_outgoing_addr (NULL, to_link_socket_info, &ks->remote_addr, session->common_name);#ifdef MEASURE_TLS_HANDSHAKE_STATS		  show_tls_performance_stats();#endif		}

⌨️ 快捷键说明

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