Example #1
0
stl_string calc_mac (DnsRR &tsig_rr, message_buff msg, stl_string sign_key, message_buff *extra) {
  struct hmac_md5_ctx md5;
  unsigned char md5res [MD5_DIGEST_SIZE];
  memset (&md5, 0, sizeof (hmac_md5_ctx));
    
  unsigned char *digestpos = rr_getdata (tsig_rr.RDATA, DNS_TYPE_TSIG, 3);
  uint16_t digestlen = uint16_value (digestpos);
  
//  print_buff (sign_key.size(), (unsigned char*)sign_key.c_str());
  hmac_md5_set_key(&md5, sign_key.size(), (uint8_t *)sign_key.c_str());
  
//  printf ("Begin MAC calculation\n");
  
  /* original MAC */
  if (extra && extra->len) hmac_md5_update(&md5, extra->len, extra->msg);
  
  /* message */
  hmac_md5_update(&md5, 10, msg.msg);
  hmac_md5_update(&md5, 2, uint16_buff (uint16_value (msg.msg + 10) - 1));
  hmac_md5_update(&md5, msg.len - 12, msg.msg + 12);
  
  /* tsig rr */
  stl_string canname = tsig_rr.NAME.canonical();
  hmac_md5_update(&md5, canname.size(), (const uint8_t *)canname.c_str());
  hmac_md5_update(&md5, 2, uint16_buff (QCLASS_ANY));
  hmac_md5_update(&md5, 4, uint32_buff (0));
  
  /* start of TSIG rrdata */
  domainname dom = domainname (true, tsig_rr.RDATA);
  canname = dom.canonical();
  hmac_md5_update (&md5, canname.size(), (const uint8_t*)canname.c_str());
  hmac_md5_update(&md5, 8, digestpos - 8);
  
  /* rest, excluding original ID */
  hmac_md5_update(&md5, tsig_rr.RDLENGTH - (digestpos - tsig_rr.RDATA) - digestlen - 4,
                  digestpos + digestlen + 4);
  hmac_md5_digest(&md5, MD5_DIGEST_SIZE, md5res);
  
//  printf ("End MAC calculation\n");
  
//  print_buff (MD5_DIGEST_SIZE, md5res);
  
  stl_string ret;
  ret.append ((char*)md5res, MD5_DIGEST_SIZE);
  return ret;
}
Example #2
0
bool disk_init(sd_disk *sd)
{
    uint32_t pstart = 0;
    uint16_t psize = 0;

    //
    // Find MBR and First partition and get fat and root directory from them
    //
    if (sd_read_block(0, sd)
            && BLOCK_EQ(510,0x55) && BLOCK_EQ(511,0xAA) && BLOCK_EQ(P1_START+4,0x04)) {
        pstart = uint32_value(sd->buf+P1_START+8);
        if (pstart != 0 && sd_read_block(pstart, sd)) {
            // fat start = pstart + number reserved sectors
            sd->fat_start = pstart + uint16_value(sd->buf+14);

            sd->p_size = uint16_value(sd->buf+19);

            // root_dir start = <fat start> + <fat size> * <number of fats>;
            sd->root_dir = sd->fat_start + uint8_value(sd->buf+16) * uint16_value(sd->buf+22);

            // data_start = <root_dir start> + <num root entries> * 32 / 512
            sd->data_start = sd->root_dir + (uint16_value(sd->buf+17) >> 4);
            return true;
        }
Example #3
0
/// @brief verifies TSIG of received response
///
/// Make sure that message_buff is trimmed down to not include TSIG
/// record, as it must be passed in message_tsig.
///
/// @param check_tsig TSIG RR from the original message
/// @param message_tsig TSIR RR from the response message that we are validating
/// @param key the key used for signing
/// @param message received message (without TSIG record)
void verify_signature (DnsRR *check_tsig, DnsRR *message_tsig,
                       stl_string key, message_buff message) {
  if (!message_tsig)
    throw PException (true, "Unsigned answer to a signed message (key %s)", check_tsig->NAME.tocstr ());

  unsigned char *errorptr = rr_getdata (check_tsig->RDATA, DNS_TYPE_TSIG, 5);

  domainname alg_name = rr_getdomain (check_tsig->RDATA, DNS_TYPE_TSIG),
             rr_alg_name = rr_getdomain (message_tsig->RDATA, DNS_TYPE_TSIG);
  if (rr_alg_name != alg_name || check_tsig->NAME != message_tsig->NAME) {
    memcpy (errorptr, uint16_buff (RCODE_BADKEY), 2);
    throw PException (true, "Key name/algorithm does not match: question signed with %s, answer "
                      "signed with %s", check_tsig->NAME.tocstr(), message_tsig->NAME.tocstr());
  }
  
  unsigned char *rr_macpos = rr_getdata (message_tsig->RDATA, DNS_TYPE_TSIG, 3),
                *macpos    = rr_getdata (check_tsig->RDATA, DNS_TYPE_TSIG, 3);
  uint16_t rr_maclen = uint16_value (rr_macpos),
           maclen    = uint16_value (macpos);
  
  if ((message.msg[3] & 15) == RCODE_NOTAUTH) {
    /* error! */
    uint16_t err = rr_getshort (message_tsig->RDATA, DNS_TYPE_TSIG, 5);
    if (err == RCODE_BADSIG)
      throw PException (true, "Question signed with %s had bad signature", check_tsig->NAME.tocstr());
    else if (err == RCODE_BADKEY)
      throw PException (true, "Question was signed with bad key (%s)", check_tsig->NAME.tocstr());
    else if (err == RCODE_BADTIME)
      throw PException (true, "Question sign time invalid (query time %d, answer time %d)",
                        uint48_value (rr_getdata (check_tsig->RDATA, DNS_TYPE_TSIG, 1)),
                        uint48_value (rr_getdata (message_tsig->RDATA, DNS_TYPE_TSIG, 1)));
    else throw PException (true, "Unknown sign error: %d", err);
  }
  
  time_t clienttime = time (NULL);
  u_int48 servertime = uint48_value (rr_getdata (check_tsig->RDATA, DNS_TYPE_TSIG, 1));
  uint16_t fudge = rr_getshort (check_tsig->RDATA, DNS_TYPE_TSIG, 2);
  
  if ( (clienttime > servertime && clienttime - servertime > fudge) ||
       (servertime > clienttime && servertime - clienttime > fudge) ) {
      throw PException (true, "Answer sign time invalid (answer time %d, real time %d)",
                        uint48_value (rr_getdata (message_tsig->RDATA, DNS_TYPE_TSIG, 1)),
                        clienttime);
    // TODO: set TSIG error of check_tsig for servers
  }

  if (rr_maclen != MD5_DIGEST_SIZE) {
    memcpy (errorptr, uint16_buff (RCODE_BADSIG), 2);
    throw PException (true, "Incorrect MAC size: %d", rr_maclen);
  }
  
  /* calculate MAC */
  message_buff ext; /* TODO: document: if this is from a message, it actually
                       means that the message was unsigned, but we should still
                       include the two length */
  if (maclen)
    ext = message_buff (macpos, maclen + 2);
  stl_string mac = calc_mac (*message_tsig, message, key, &ext);
  
  if (memcmp (mac.c_str(), rr_macpos + 2, MD5_DIGEST_SIZE) != 0) {
    memcpy (errorptr, uint16_buff (RCODE_BADSIG), 2);
    throw PException (true, "Message signed with key %s has bad signature",
                      message_tsig->NAME.tocstr ());
  }
}