Ejemplo n.º 1
0
void
handle_packet(const u_char *packet, int length) {
  static int n = 0;
  static unsigned char initial_hello[] = { 
    0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
  };
  uint8 *data; 
  size_t data_length, rlen;
  int i, res;
#if DTLS_VERSION == 0xfeff
#ifndef SHA1_DIGEST_LENGTH
#define SHA1_DIGEST_LENGTH 20
#endif
  uint8 hash_buf[16 + SHA1_DIGEST_LENGTH];
#elif DTLS_VERSION == 0xfefd
  uint8 hash_buf[DTLS_SHA256_DIGEST_LENGTH];
#endif
#define verify_data_length 12
  int is_client;
  n++;

  SKIP_ETH_HEADER(packet, length);
  SKIP_IP_HEADER(packet, length);

  /* determine from port if this is a client */
  is_client = dtls_uint16_to_int(packet) != 20220;

  SKIP_UDP_HEADER(packet, length);

  while (length) {
    rlen = dtls_uint16_to_int(packet + 11) + sizeof(dtls_record_header_t);

    if (!rlen) {
      fprintf(stderr, "invalid length!\n");
      return;
    }

    /* skip packet if it is from a different epoch */
    if (dtls_uint16_to_int(packet + 3) != epoch[is_client])
      goto next;

    res = decrypt_verify(is_client, packet, rlen,
			 &data, &data_length);

    if (res <= 0)
      goto next;
    
    printf("packet %d (from %s):\n", n, is_client ? "client" : "server");
    hexdump(packet, sizeof(dtls_record_header_t));
    printf("\n");
    hexdump(data, data_length);
    printf("\n");
    
    if (packet[0] == 22 && data[0] == 1) { /* ClientHello */
      if (memcmp(packet, initial_hello, sizeof(initial_hello)) == 0)
	goto next;
	
      memcpy(dtls_kb_client_iv(OTHER_CONFIG), data + 14, 32);

	clear_hash();
#if DTLS_VERSION == 0xfeff
      hs_hash[0] = dtls_new_hash(HASH_MD5);
      hs_hash[1] = dtls_new_hash(HASH_SHA1);

      hs_hash[0]->init(hs_hash[0]->data);
      hs_hash[1]->init(hs_hash[1]->data);
#elif DTLS_VERSION == 0xfefd
      dtls_hash_init(hs_hash[0]);
#endif
    }
    
    if (packet[0] == 22 && data[0] == 2) { /* ServerHello */
      memcpy(dtls_kb_server_iv(OTHER_CONFIG), data + 14, 32);
      /* FIXME: search in ciphers */
      OTHER_CONFIG->cipher = TLS_PSK_WITH_AES_128_CCM_8;
    }
    
    if (packet[0] == 20 && data[0] == 1) { /* ChangeCipherSpec */
      printf("client random: ");
      dump(dtls_kb_client_iv(OTHER_CONFIG), 32);
      printf("\nserver random: ");
      dump(dtls_kb_server_iv(OTHER_CONFIG), 32);
      printf("\n");
      master_secret_len = 
	dtls_prf(pre_master_secret, pre_master_len,
		 (unsigned char *)"master secret", 13,
		 dtls_kb_client_iv(OTHER_CONFIG), 32,
		 dtls_kb_server_iv(OTHER_CONFIG), 32,
		 master_secret, DTLS_MASTER_SECRET_LENGTH);
  
      printf("master_secret:\n  ");
      for(i = 0; i < master_secret_len; i++) 
	printf("%02x", master_secret[i]);
      printf("\n");

      /* create key_block from master_secret
       * key_block = PRF(master_secret,
                     "key expansion" + server_random + client_random) */
      dtls_prf(master_secret, master_secret_len,
	       (unsigned char *)"key expansion", 13,
	       dtls_kb_server_iv(OTHER_CONFIG), 32,
	       dtls_kb_client_iv(OTHER_CONFIG), 32,
	       OTHER_CONFIG->key_block, 
	       dtls_kb_size(OTHER_CONFIG));

      OTHER_CONFIG->read_cipher = 
	dtls_cipher_new(OTHER_CONFIG->cipher,
			dtls_kb_client_write_key(OTHER_CONFIG),
			dtls_kb_key_size(OTHER_CONFIG));

      if (!OTHER_CONFIG->read_cipher) {
	warn("cannot create read cipher\n");
      } else {
	dtls_cipher_set_iv(OTHER_CONFIG->read_cipher,
			   dtls_kb_client_iv(OTHER_CONFIG),
			   dtls_kb_iv_size(OTHER_CONFIG));
      }

      OTHER_CONFIG->write_cipher = 
	dtls_cipher_new(OTHER_CONFIG->cipher, 
			dtls_kb_server_write_key(OTHER_CONFIG),
			dtls_kb_key_size(OTHER_CONFIG));
      
      if (!OTHER_CONFIG->write_cipher) {
	warn("cannot create write cipher\n");
      } else {
	dtls_cipher_set_iv(OTHER_CONFIG->write_cipher,
			   dtls_kb_server_iv(OTHER_CONFIG),
			   dtls_kb_iv_size(OTHER_CONFIG));
      }

      /* if (is_client) */
	SWITCH_CONFIG;
      epoch[is_client]++;

      printf("key_block:\n");
      printf("  client_MAC_secret:\t");  
      dump(dtls_kb_client_mac_secret(CURRENT_CONFIG), 
	   dtls_kb_mac_secret_size(CURRENT_CONFIG));
      printf("\n");

      printf("  server_MAC_secret:\t");  
      dump(dtls_kb_server_mac_secret(CURRENT_CONFIG), 
	   dtls_kb_mac_secret_size(CURRENT_CONFIG));
      printf("\n");

      printf("  client_write_key:\t");  
      dump(dtls_kb_client_write_key(CURRENT_CONFIG), 
	   dtls_kb_key_size(CURRENT_CONFIG));
      printf("\n");

      printf("  server_write_key:\t");  
      dump(dtls_kb_server_write_key(CURRENT_CONFIG), 
	   dtls_kb_key_size(CURRENT_CONFIG));
      printf("\n");

      printf("  client_IV:\t\t");  
      dump(dtls_kb_client_iv(CURRENT_CONFIG), 
	   dtls_kb_iv_size(CURRENT_CONFIG));
      printf("\n");
      
      printf("  server_IV:\t\t");  
      dump(dtls_kb_server_iv(CURRENT_CONFIG), 
	   dtls_kb_iv_size(CURRENT_CONFIG));
      printf("\n");
      
    }

    if (packet[0] == 22) {
      if (data[0] == 20) { /* Finished */
	finalize_hash(hash_buf);
	/* clear_hash(); */

	update_hash((unsigned char *)packet, sizeof(dtls_record_header_t),
		    data, data_length);

	dtls_prf(master_secret, master_secret_len,
		 is_client 
		 ? (unsigned char *)"client finished" 
		 : (unsigned char *)"server finished" 
		 , 15,
		 hash_buf, sizeof(hash_buf),
		 NULL, 0,
		 data + sizeof(dtls_handshake_header_t),
		 verify_data_length);
	printf("verify_data:\n");
	dump(data, data_length);
	printf("\n");
      } else {
	update_hash((unsigned char *)packet, sizeof(dtls_record_header_t),
		    data, data_length);
      }
    }

    if (packet[0] == 23) {	/* Application Data */
      printf("Application Data:\n");
      dump(data, data_length);
      printf("\n");
    }

  next:
    length -= rlen;
    packet += rlen;
  }
}
Ejemplo n.º 2
0
static int handle_data (int sock, struct allnet_header * hp,
                        char * data, int dsize, char ** contact, keyset * kset,
                        char ** message, char ** desc, int * verified,
                        time_t * sent, int * duplicate, int * broadcast)
{
  int verif = 0;
  char * text = NULL;
  int tsize = decrypt_verify (hp->sig_algo, data, dsize, contact, kset, &text,
                              (char *) (hp->source), hp->src_nbits,
                              (char *) (hp->destination), hp->dst_nbits, 0);
  if (tsize < 0) {
    printf ("no signature to verify, but decrypted from %s\n", *contact);
    tsize = -tsize;
  } else if (tsize > 0) {
    verif = 1;
  }
  if (tsize < CHAT_DESCRIPTOR_SIZE) {
#ifdef DEBUG_PRINT
    printf ("decrypted packet has size %d, min is %zd, dropping\n",
            tsize, CHAT_DESCRIPTOR_SIZE);
#endif /* DEBUG_PRINT */
    return 0;
  }
  if (*contact == NULL) {
#ifdef DEBUG_PRINT
    printf ("contact not known\n");
#endif /* DEBUG_PRINT */
    if (text != NULL) free (text);
    return 0;
  }
#ifdef DEBUG_PRINT
  printf ("got packet from contact %s\n", *contact);
#endif /* DEBUG_PRINT */
  struct chat_descriptor * cdp = (struct chat_descriptor *) text;

  int app = readb32u (cdp->app_media.app);
  if (app != XCHAT_ALLNET_APP_ID) {
#ifdef DEBUG_PRINT
    printf ("handle_data ignoring unknown app %08x\n", app);
    print_buffer (text, CHAT_DESCRIPTOR_SIZE, "chat descriptor", 100, 1);
#endif /* DEBUG_PRINT */
    return 0;
  }
  int media = readb32u (cdp->app_media.media);
  if ((media != ALLNET_MEDIA_TEXT_PLAIN) &&
      (media != ALLNET_MEDIA_PUBLIC_KEY)) {
#ifdef DEBUG_PRINT
    printf ("handle_data ignoring media type %08x\n", media);
    print_buffer (text, CHAT_DESCRIPTOR_SIZE, "chat descriptor", 100, 1);
#endif /* DEBUG_PRINT */
    return 0;
  }
  char * cleartext = text + CHAT_DESCRIPTOR_SIZE;
  int msize = tsize - CHAT_DESCRIPTOR_SIZE;

  long long int seq = readb64u (cdp->counter);
  if (seq == COUNTER_FLAG) {
    do_chat_control (*contact, *kset, text, tsize, sock, hp->hops + 4);
    send_ack (sock, hp, cdp->message_ack, verif, *contact, *kset);
    if (*contact != NULL) { free (*contact); *contact = NULL; }
    if (text != NULL) free (text);
    return 0;
  }

  *broadcast = 0;
  *duplicate = 0;
  if (was_received (*contact, *kset, seq))
    *duplicate = 1;

  save_incoming (*contact, *kset, cdp, cleartext, msize);

  if (media == ALLNET_MEDIA_PUBLIC_KEY) {
    cleartext = "received a key for an additional device";
    msize = strlen (cleartext);
  }

  *desc = chat_descriptor_to_string (cdp, 0, 0);
  *verified = verif;
  if (sent != NULL)
    *sent = (readb64u (cdp->timestamp) >> 16) & 0xffffffff;

  *message = malloc_or_fail (msize + 1, "handle_data message");
  memcpy (*message, cleartext, msize);
  (*message) [msize] = '\0';   /* null-terminate the message */

  /* printf ("hp->hops = %d\n", hp->hops); */

  send_ack (sock, hp, cdp->message_ack, verif, *contact, *kset);

  free (text);

  return msize;
}