int receive_exchange_key(FILE * log_server, char * ciphersuite_to_use, unsigned char * master_secret, char * premaster_secret, char * random_from_client, char * random_from_server){

    if(!decrypt_secret_RSA(log_server, premaster_secret)){
        printf("SERVER: decription failed\n");
        return 0;
    }
    
    const EVP_MD * evp_md;
    
    if(atoi(ciphersuite_to_use) == atoi(TLS_DHE_RSA_WITH_SHA224) || atoi(ciphersuite_to_use) == atoi(TLS_RSA_WITH_SHA224)){
        evp_md = EVP_sha224();
    }
    else if(atoi(ciphersuite_to_use) == atoi(TLS_RSA_WITH_SHA256) || atoi(ciphersuite_to_use) == atoi(TLS_DHE_RSA_WITH_SHA256)){
        evp_md = EVP_sha256();
    }
    else if(atoi(ciphersuite_to_use) == atoi(TLS_DHE_RSA_WITH_SHA384) || atoi(ciphersuite_to_use) == atoi(TLS_RSA_WITH_SHA384)){
        evp_md = EVP_sha384();
    }
    else {
        evp_md = EVP_sha512();
    }
    
	if(!compute_master_secret (master_secret, evp_md, random_from_client, random_from_server, premaster_secret, "master secret")){
		printf("SERVER: computing master_secret failed\n");
		return 0;
	}
	return 1;
}
示例#2
0
int main(int argc, char **argv) {
  int err, option_index, c, clientlen, counter;
  unsigned char rcv_plaintext[AES_BLOCK_SIZE];
  unsigned char rcv_ciphertext[AES_BLOCK_SIZE];
  unsigned char send_plaintext[AES_BLOCK_SIZE];
  unsigned char send_ciphertext[AES_BLOCK_SIZE];
  aes_context enc_ctx, dec_ctx;
  in_addr_t ip_addr;
  struct sockaddr_in server_addr;
  FILE *c_file, *d_file, *m_file;
  ssize_t read_size, write_size;
  struct sockaddr_in client_addr;
  tls_msg err_msg, send_msg, rcv_msg;
  mpz_t client_exp, client_mod;
  fd_set readfds;
  struct timeval tv;

  c_file = d_file = m_file = NULL;

  mpz_init(client_exp);
  mpz_init(client_mod);

  /*
   * This section is networking code that you don't need to worry about.
   * Look further down in the function for your part.
   */

  memset(&ip_addr, 0, sizeof(in_addr_t));

  option_index = 0;
  err = 0;

  static struct option long_options[] = {
    {"ip", required_argument, 0, 'i'},
    {"cert", required_argument, 0, 'c'},
    {"exponent", required_argument, 0, 'd'},
    {"modulus", required_argument, 0, 'm'},
    {0, 0, 0, 0},
  };

  while (1) {
    c = getopt_long(argc, argv, "c:i:d:m:", long_options, &option_index);
    if (c < 0) {
      break;
    }
    switch(c) {
    case 0:
      usage();
      break;
    case 'c':
      c_file = fopen(optarg, "r");
      if (c_file == NULL) {
	perror("Certificate file error");
	exit(1);
      }
      break;
    case 'd':
      d_file = fopen(optarg, "r");
      if (d_file == NULL) {
	perror("Exponent file error");
	exit(1);
      }
      break;
    case 'i':
      ip_addr = inet_addr(optarg);
      break;
    case 'm':
      m_file = fopen(optarg, "r");
      if (m_file == NULL) {
	perror("Modulus file error");
	exit(1);
      }
      break;
    case '?':
      usage();
      break;
    default:
      usage();
      break;
    }
  }

  if (d_file == NULL || c_file == NULL || m_file == NULL) {
    usage();
  }
  if (argc != 9) {
    usage();
  }

  mpz_inp_str(client_exp, d_file, 0);
  mpz_inp_str(client_mod, m_file, 0);

  signal(SIGTERM, kill_handler);

  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockfd < 0) {
    perror("Could not open socket");
    exit(1);
  }

  memset(&server_addr, 0, sizeof(struct sockaddr_in));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = ip_addr;
  server_addr.sin_port = htons(HANDSHAKE_PORT);
  err = connect(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr));
  if (err < 0) {
    perror("Could not bind socket");
    cleanup();
  }

  // YOUR CODE HERE
  // IMPLEMENT THE TLS HANDSHAKE


  // send client hello
  hello_message client_hello_msg = {CLIENT_HELLO, random_int(), TLS_RSA_WITH_AES_128_ECB_SHA256};
  err = send_tls_message(sockfd, &client_hello_msg, HELLO_MSG_SIZE);
  if (err == ERR_FAILURE) {
    exit(1);
  }


  // receive server hello
  hello_message server_hello_msg;
  err = receive_tls_message(sockfd, &server_hello_msg, HELLO_MSG_SIZE, SERVER_HELLO);
  if (err == ERR_FAILURE) {
    exit(1);
  }

  // send client certificate
  cert_message client_cert_msg;
  client_cert_msg.type = CLIENT_CERTIFICATE;
  fgets(client_cert_msg.cert, RSA_MAX_LEN, c_file);
  err = send_tls_message(sockfd, &client_cert_msg, CERT_MSG_SIZE);
  if (err == ERR_FAILURE) {
    exit(1);
  }

  //receive server certificate

  cert_message server_cert_msg;

  err = receive_tls_message(sockfd, &server_cert_msg, CERT_MSG_SIZE, SERVER_CERTIFICATE);
  if (err == ERR_FAILURE) {
    exit(1);
  }

  mpz_t cert_plaintext;
  mpz_init(cert_plaintext);

  mpz_t ca_key_exp;
  mpz_init(ca_key_exp);

  mpz_t ca_key_mod;
  mpz_init(ca_key_mod);

  mpz_set_str(ca_key_exp, CA_EXPONENT, 0);
  mpz_set_str(ca_key_mod, CA_MODULUS, 0);

  decrypt_cert(cert_plaintext, &server_cert_msg, ca_key_exp, ca_key_mod);

  char cert_plaintext_string[RSA_MAX_LEN];
  mpz_get_ascii(cert_plaintext_string, cert_plaintext);


  mpz_t exponentNum;
  mpz_init(exponentNum);
  mpz_t modNum;
  mpz_init(modNum);
  get_cert_exponent(exponentNum, cert_plaintext_string);
  get_cert_modulus(modNum, cert_plaintext_string);


  mpz_t premaster_secret_int;
  mpz_init(premaster_secret_int);
  
  int p_secret_int = random_int();
  mpz_t p_secret;
  mpz_init(p_secret);
  mpz_add_ui(p_secret, p_secret, p_secret_int);

  perform_rsa(premaster_secret_int, p_secret, exponentNum, modNum);

  ps_msg premaster_secret;
  premaster_secret.type = PREMASTER_SECRET;
  mpz_get_str(premaster_secret.ps, 16, premaster_secret_int);


  // send premaster secret
  err = send_tls_message(sockfd, &premaster_secret, PS_MSG_SIZE);
  if (err == ERR_FAILURE) {
    exit(1);
  }

 
  ps_msg master_secret;

  // receive master secret
  err = receive_tls_message(sockfd, &master_secret, PS_MSG_SIZE, VERIFY_MASTER_SECRET);
  if (err == ERR_FAILURE) {
    exit(1);
  }


  mpz_t decrypted_master_secret;
  mpz_init(decrypted_master_secret);

  mpz_t key_exp;
  mpz_init(key_exp);

  mpz_t key_mod;
  mpz_init(key_mod);

  

  fseek (d_file, 0, SEEK_END);
  long length = ftell (d_file);
  fseek (d_file, 0, SEEK_SET);

  char private_key[length];
  fgets(private_key, length, d_file);
  mpz_set_str(key_exp, private_key, 0);

  fseek (m_file, 0, SEEK_END);
  length = ftell (m_file);
  fseek (m_file, 0, SEEK_SET);

  char modulus[length];
  fgets(modulus, length, m_file);
  mpz_set_str(key_mod, modulus, 0);


  decrypt_verify_master_secret(decrypted_master_secret, &master_secret, key_exp, key_mod);

  char decrypted_master_secret_char[16];

  mpz_get_str(decrypted_master_secret_char, 16, decrypted_master_secret);

  unsigned char computed_master_secret[16];

  compute_master_secret(p_secret_int, client_hello_msg.random, server_hello_msg.random, computed_master_secret);

  
  if (strcasecmp(decrypted_master_secret_char, hex_to_str(computed_master_secret, 16)) == 0) {
    printf("Begin messages.\n");
  } 

  /*
   * START ENCRYPTED MESSAGES
   */

  memset(send_plaintext, 0, AES_BLOCK_SIZE);
  memset(send_ciphertext, 0, AES_BLOCK_SIZE);
  memset(rcv_plaintext, 0, AES_BLOCK_SIZE);
  memset(rcv_ciphertext, 0, AES_BLOCK_SIZE);

  memset(&rcv_msg, 0, TLS_MSG_SIZE);

  aes_init(&enc_ctx);
  aes_init(&dec_ctx);
  
  // YOUR CODE HERE
  // SET AES KEYS

  if (aes_setkey_enc (&enc_ctx, computed_master_secret, 128)){
    printf("setting key didn't work n***a\n");
  }

  if (aes_setkey_dec (&dec_ctx, computed_master_secret, 128)){
    printf("setting key didn't work n***a\n");
  }

  fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
  /* Send and receive data. */
  while (1) {
    FD_ZERO(&readfds);
    FD_SET(STDIN_FILENO, &readfds);
    FD_SET(sockfd, &readfds);
    tv.tv_sec = 2;
    tv.tv_usec = 10;

    select(sockfd+1, &readfds, NULL, NULL, &tv);
    if (FD_ISSET(STDIN_FILENO, &readfds)) {
      counter = 0;
      memset(&send_msg, 0, TLS_MSG_SIZE);
      send_msg.type = ENCRYPTED_MESSAGE;
      memset(send_plaintext, 0, AES_BLOCK_SIZE);
      read_size = read(STDIN_FILENO, send_plaintext, AES_BLOCK_SIZE);
      while (read_size > 0 && counter + AES_BLOCK_SIZE < TLS_MSG_SIZE - INT_SIZE) {
	if (read_size > 0) {
	  err = aes_crypt_ecb(&enc_ctx, AES_ENCRYPT, send_plaintext, send_ciphertext);
	  memcpy(send_msg.msg + counter, send_ciphertext, AES_BLOCK_SIZE);
	  counter += AES_BLOCK_SIZE;
	}
	memset(send_plaintext, 0, AES_BLOCK_SIZE);
	read_size = read(STDIN_FILENO, send_plaintext, AES_BLOCK_SIZE);
      }
      write_size = write(sockfd, &send_msg, INT_SIZE+counter+AES_BLOCK_SIZE);
      if (write_size < 0) {
	perror("Could not write to socket");
	cleanup();
      }
    } else if (FD_ISSET(sockfd, &readfds)) {
      memset(&rcv_msg, 0, TLS_MSG_SIZE);
      memset(rcv_ciphertext, 0, AES_BLOCK_SIZE);
      read_size = read(sockfd, &rcv_msg, TLS_MSG_SIZE);
      if (read_size > 0) {
	if (rcv_msg.type != ENCRYPTED_MESSAGE) {
	  goto out;
	}
	memcpy(rcv_ciphertext, rcv_msg.msg, AES_BLOCK_SIZE);
	counter = 0;
	while (counter < read_size - INT_SIZE - AES_BLOCK_SIZE) {
	  aes_crypt_ecb(&dec_ctx, AES_DECRYPT, rcv_ciphertext, rcv_plaintext);
	  printf("%s", rcv_plaintext);
	  counter += AES_BLOCK_SIZE;
	  memcpy(rcv_ciphertext, rcv_msg.msg+counter, AES_BLOCK_SIZE);
	}
	printf("\n");
      }
    }

  }

 out:
  close(sockfd);
  return 0;
}
示例#3
0
/**
 * Send the client key exchange message, as detailed in section 7.4.7
 * Use the server's public key (if it has one) to encrypt a key. (or DH?)
 * Return true if this succeeded, false otherwise.
 */ 
static int send_client_key_exchange( int connection, TLSParameters *parameters )
{   
  unsigned char *key_exchange_message;
  int key_exchange_message_len;
  unsigned char *premaster_secret;
  int premaster_secret_len;

  switch ( parameters->pending_send_parameters.suite ) {
    case TLS_NULL_WITH_NULL_NULL:
      // XXX this is an error, exit here
      break;
    case TLS_RSA_WITH_NULL_MD5:
    case TLS_RSA_WITH_NULL_SHA:
    case TLS_RSA_EXPORT_WITH_RC4_40_MD5:
    case TLS_RSA_WITH_RC4_128_MD5:
    case TLS_RSA_WITH_RC4_128_SHA:
    case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
    case TLS_RSA_WITH_IDEA_CBC_SHA:
    case TLS_RSA_EXPORT_WITH_DES40_CBC_SHA:
    case TLS_RSA_WITH_DES_CBC_SHA:
    case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
    case TLS_RSA_WITH_AES_128_CBC_SHA:
    case TLS_RSA_WITH_AES_256_CBC_SHA:
      premaster_secret_len = MASTER_SECRET_LENGTH;
      premaster_secret = malloc( premaster_secret_len );
      key_exchange_message_len = rsa_key_exchange( 
        &parameters->server_public_key.rsa_public_key,
        premaster_secret, &key_exchange_message );
      break;
    case TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
    case TLS_DH_DSS_WITH_DES_CBC_SHA:
    case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
    case TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
    case TLS_DH_RSA_WITH_DES_CBC_SHA:
    case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
    case TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
    case TLS_DHE_DSS_WITH_DES_CBC_SHA:
    case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
    case TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
    case TLS_DHE_RSA_WITH_DES_CBC_SHA:
    case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
    case TLS_DH_anon_EXPORT_WITH_RC4_40_MD5:
    case TLS_DH_anon_WITH_RC4_128_MD5:
    case TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
    case TLS_DH_anon_WITH_DES_CBC_SHA:
    case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
    case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
    case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
    case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
    case TLS_DH_anon_WITH_AES_128_CBC_SHA:
    case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
    case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
    case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
    case TLS_DH_anon_WITH_AES_256_CBC_SHA:
      premaster_secret_len = parameters->server_dh_key.p.size;
      premaster_secret = malloc( premaster_secret_len );
      key_exchange_message_len = dh_key_exchange( &parameters->server_dh_key,
        premaster_secret, &key_exchange_message );
      break;
    default:
      return 0;
  }

  if ( send_handshake_message( connection, client_key_exchange,
       key_exchange_message, key_exchange_message_len, parameters ) )
  {
    free( key_exchange_message );
    return 0;
  }

  free( key_exchange_message );

  // Now, turn the premaster secret into an actual master secret (the
  // server side will do this concurrently).
  compute_master_secret( premaster_secret, premaster_secret_len, parameters );

  // XXX - for security, should also "purge" the premaster secret from
  // memory.
  calculate_keys( parameters );

  free( premaster_secret );

  return 1;
}
int main(int argc, char **argv) {
	int err, option_index, c, clientlen, counter;
	unsigned char rcv_plaintext[AES_BLOCK_SIZE];
	unsigned char rcv_ciphertext[AES_BLOCK_SIZE];
	unsigned char send_plaintext[AES_BLOCK_SIZE];
	unsigned char send_ciphertext[AES_BLOCK_SIZE];
	aes_context enc_ctx, dec_ctx;
	in_addr_t ip_addr;
	struct sockaddr_in server_addr;
	FILE *c_file, *d_file, *m_file;
	ssize_t read_size, write_size;
	struct sockaddr_in client_addr;
	tls_msg err_msg, send_msg, rcv_msg;
	mpz_t client_exp, client_mod;
	fd_set readfds;
	struct timeval tv;

	c_file = d_file = m_file = NULL;

	mpz_init(client_exp);
	mpz_init(client_mod);


	/*
	 * This section is networking code that you don't need to worry about.
	 * Look further down in the function for your part.
	 */

	memset(&ip_addr, 0, sizeof(in_addr_t));

	option_index = 0;
	err = 0;

	static struct option long_options[] = {
		{"ip", required_argument, 0, 'i'},
		{"cert", required_argument, 0, 'c'},
		{"exponent", required_argument, 0, 'd'},
		{"modulus", required_argument, 0, 'm'},
		{0, 0, 0, 0},
	};

	while (1) {
		c = getopt_long(argc, argv, "c:i:d:m:", long_options, &option_index);
		if (c < 0) {
			break;
		}
		switch(c) {
		case 0:
			usage();
			break;
		case 'c':
			c_file = fopen(optarg, "r");
			if (c_file == NULL) {
				perror("Certificate file error");
				exit(1);
			}
			break;
		case 'd':
			d_file = fopen(optarg, "r");
			if (d_file == NULL) {
				perror("Exponent file error");
				exit(1);
			}
			break;
		case 'i':
			ip_addr = inet_addr(optarg);
			break;
		case 'm':
			m_file = fopen(optarg, "r");
			if (m_file == NULL) {
				perror("Modulus file error");
				exit(1);
			}
			break;
		case '?':
			usage();
			break;
		default:
			usage();
			break;
		}
	}

	if (d_file == NULL || c_file == NULL || m_file == NULL) {
		usage();
	}
	if (argc != 9) {
		usage();
	}

	mpz_inp_str(client_exp, d_file, 0);
	mpz_inp_str(client_mod, m_file, 0);

	signal(SIGTERM, kill_handler);

	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0) {
		perror("Could not open socket");
		exit(1);
	}


	memset(&server_addr, 0, sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = ip_addr;
	server_addr.sin_port = htons(HANDSHAKE_PORT);
	err = connect(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr));
	if (err < 0) {
		perror("Could not bind socket");
		cleanup();
	}

	// YOUR CODE HERE
	// IMPLEMENT THE TLS HANDSHAKE
	int send_message_int, receive_messge_int;
	/* error handling (To be continued) */
	// ********************************************************************
	// ********************************************************************
	// ********************************************************************
	
	// Whenever send or receive, need to check this feedback
	int feedback;
	//  =============== [Send] Client Hello =======================
	hello_message client_hello_message;
	int client_random;
	int server_random;
	memset(&client_hello_message, 0, sizeof(hello_message));

	client_random = random_int();
	printf("client_random: %d\n", client_random);
	client_hello_message.type = CLIENT_HELLO;
	client_hello_message.random = client_random;
	client_hello_message.cipher_suite = TLS_RSA_WITH_AES_128_ECB_SHA256;
	feedback = send_tls_message(sockfd, &client_hello_message, sizeof(hello_message));
	if (feedback != ERR_OK){
		perror("[CLIENT_HELLO]: can't send tls message");
		cleanup();	
	}

	//  =============== [Receive] Sever Hello =======================
	hello_message server_hello_message;
	memset(&server_hello_message, 0, sizeof(hello_message));
	feedback = receive_tls_message(sockfd, &server_hello_message, sizeof(hello_message), SERVER_HELLO);
	if (feedback != ERR_OK){
		perror("[SERVER_HELLO]: can't receive tls message");
		cleanup();		
	}
	server_random = server_hello_message.random;
	printf("server_random: %d\n", server_random);

	//  =============== [Send] Client Certificate ================
	mpz_t client_certificate_mpz;
	cert_message client_certificate;
	int byte_read;
	mpz_init(client_certificate_mpz);
	// May need to verify whether we connect to the correct server(i.e.torus.ce.berkeley.edu).
	memset(&client_certificate, 0, sizeof(cert_message));
	client_certificate.type = CLIENT_CERTIFICATE;
	fread(client_certificate.cert, RSA_MAX_LEN, 1, c_file);
	//printf("Client Certificate: %s\n", client_certificate.cert);
	feedback = send_tls_message(sockfd, &client_certificate, CERT_MSG_SIZE);
	if (feedback != ERR_OK){
		perror("[CLIENT CERTIFICATE]: can't send tls message");
		cleanup();
	}

	//  =============== [Receive] Server Certificate ================
	cert_message server_certificate;
	mpz_t decrypted_sever_cert_mpz;
	mpz_t ca_exponent;
	mpz_t ca_modulus;
	mpz_t server_public_key_exponent;
	mpz_t server_public_key_modulus;
	char decrypted_server_cert [RSA_MAX_LEN];

	memset(&server_certificate, 0, sizeof(cert_message));
	mpz_init(decrypted_sever_cert_mpz);
	mpz_init(ca_exponent);
	mpz_init(ca_modulus);
	mpz_init(server_public_key_exponent);
	mpz_init(server_public_key_modulus);
	memset(decrypted_server_cert, 0, RSA_MAX_LEN);

	feedback = receive_tls_message(sockfd, &server_certificate, sizeof(cert_message), SERVER_CERTIFICATE);
	if (feedback != ERR_OK){
		perror("[SERVER CERTIFICATE]: can't receive tls message");
		cleanup();
	}
	// May need to verify whether we connect to the correct server(i.e.torus.ce.berkeley.edu).
	// Decrypt Server Certificate
	mpz_set_str(ca_exponent, CA_EXPONENT, 0);
	mpz_set_str(ca_modulus, CA_MODULUS, 0);
	decrypt_cert(decrypted_sever_cert_mpz, &server_certificate, ca_exponent, ca_modulus);
	mpz_get_ascii(decrypted_server_cert, decrypted_sever_cert_mpz);                       // Convert mpz to char array
	//printf("decrypted_server_cert: %s\n", decrypted_server_cert);
	get_cert_exponent(server_public_key_exponent, decrypted_server_cert);
	get_cert_modulus(server_public_key_modulus, decrypted_server_cert);


	//  =============== [Send] E_server_public_key (Premaster Secret) ================
	// Construct encrypted(premaster secret)
	mpz_t premaster_secret_encrypted, premaster_secret_mpz;
	int premaster_secret;
	char premaster[16];
	ps_msg encrypted_ps_message;
	mpz_init(premaster_secret_encrypted);
	mpz_init(premaster_secret_mpz);	
	memset(&encrypted_ps_message, 0, sizeof(ps_msg));
	
	// Generate and Covert Premaster Secret to mpz
	sleep(3);
	premaster_secret = random_int();
	printf("premaster_secret: %d\n", premaster_secret);
	sprintf(premaster, "%d", premaster_secret);
	mpz_set_str(premaster_secret_mpz, premaster, 10);
	// perform_rsa(premaster_secret_encrypted, premaster_secret_mpz, server_public_key_exponent, server_public_key_modulus);
	// ps_msg *encrypted_ps_message;
	// encrypted_ps_message = (ps_msg*) malloc(sizeof(ps_msg));
	// encrypted_ps_message->type = PREMASTER_SECRET;
	// mpz_get_ascii(encrypted_ps_message->ps, premaster_secret_encrypted);
	// send_tls_message(sockfd, encrypted_ps_message, sizeof(ps_msg));
	// ps_msg encrypted_server_ms_message;
	// memset(&encrypted_server_ms_message, 0, sizeof(ps_msg));
	// receive_messge_int = receive_tls_message(sockfd, &encrypted_server_ms_message, sizeof(ps_msg), PREMASTER_SECRET);
	// if (receive_messge_int == ERR_FAILURE) {
	// 	perror("Could not get the master secret");
	// 	cleanup();
	// }
	// gmp_printf("premaster_secret_mpz: %Zd\n", premaster_secret_mpz);
	// gmp_printf("server_public_key_exponent: %Zx\n", server_public_key_exponent);
	// gmp_printf("server_public_key_modulus: %Zx\n", server_public_key_modulus);
	perform_rsa(premaster_secret_encrypted, premaster_secret_mpz, server_public_key_exponent, server_public_key_modulus);
	encrypted_ps_message.type = PREMASTER_SECRET;
	mpz_get_str(encrypted_ps_message.ps, 16, premaster_secret_encrypted);
	feedback = send_tls_message(sockfd, &encrypted_ps_message, sizeof(ps_msg));
	if (feedback != ERR_OK) {
		perror("[E_server_public_key (Premaster secret)]: can't send tls message");
		cleanup();
	}
	
	//  =============== [Receive] E_client_public_key (Master Secret) ================
	ps_msg encrypted_server_ms_message;
	mpz_t decrypted_ms;
	mpz_t master_secret_mpz;
	unsigned long long master_secret_long;
	unsigned char master_secret[SHA_BLOCK_SIZE];
	int result;
	memset(&encrypted_server_ms_message, 0, sizeof(ps_msg));
	mpz_init(decrypted_ms);
	memset(master_secret, 0, SHA_BLOCK_SIZE);
	mpz_init(master_secret_mpz);
	feedback = receive_tls_message(sockfd, &encrypted_server_ms_message, sizeof(ps_msg), VERIFY_MASTER_SECRET);
	if (feedback != ERR_OK) {
		perror("[E_client_public_key (master secret)]: can't receive tls message");
		cleanup();
	}

	decrypt_verify_master_secret(decrypted_ms, &encrypted_server_ms_message, client_exp, client_mod);
	compute_master_secret(premaster_secret, client_random, server_random, master_secret);
	char* master_secret_str = hex_to_str(master_secret, SHA_BLOCK_SIZE);
	mpz_set_str(master_secret_mpz, master_secret_str, 16);
	result = mpz_cmp(master_secret_mpz, decrypted_ms);
	printf("%d", result);
	if (result != 0) {
		perror("Decrypted server master secret doesn't match computed master secret!");
		cleanup();
	}
	if (client_random != premaster_secret && server_random != premaster_secret){
		//printf("1\n");
	}else{
		//printf("0\n");
	}
	//printf("result: %d\n", result);
	free(master_secret_str);
	close(sockfd);
	mpz_clear(client_exp);
	mpz_clear(client_mod);
	mpz_clear(client_certificate_mpz);
	mpz_clear(decrypted_sever_cert_mpz);
	mpz_clear(ca_exponent);
	mpz_clear(ca_modulus);
	mpz_clear(premaster_secret_encrypted);
	mpz_clear(server_public_key_exponent);
	mpz_clear(server_public_key_modulus);
	mpz_clear(premaster_secret_mpz);
	mpz_clear(decrypted_ms);
	mpz_clear(master_secret_mpz);
	cleanup();
	return 0;
}