Ejemplo n.º 1
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 ());
  }
}
Ejemplo n.º 2
0
int
main(int argc, char **argv)
{
    uint8_t *mkey = NULL; /** Master key. */
    uint8_t *snum = NULL; /** Serial number */
    char *key_path = NULL;

    estream_state_t *key_stream ; /** The input stream. */
    epkt_state_t *epkt; /* The packet handler attached to the framer. */

    int opt;
    int res;
    uint8_t data[128];
    uint8_t nonce[12];
    uint8_t *mac;
    EKeySkein rekeying_state;
    uint8_t session_key[32];
    int retries;
    char *keyring_filename;
    bool nokeyring = false;

    keyring_filename = strdup(KEYRINGFILE);

    while ((opt = getopt(argc, argv, "vhnf:s:m:")) != -1) {
        switch (opt) {
        case 's': /* set serial number */
            snum = malloc(12);
            res = pem64_decode_bytes(optarg, 16, snum);
            if (res != 12) {
                fprintf(stderr, "The serial number given is not the correct length. (%d/12)\n", res);
                return EXIT_CODE_CMDLINE;
            }
            break;

        case 'm': /* set master key */
            mkey = extract_master_key(optarg, strlen(optarg));
            if (mkey == NULL)
                return EXIT_CODE_CMDLINE;
            break;

        case 'f': /* set keyring filename */
            free(keyring_filename);
            keyring_filename = strdup(optarg);
            break;

        case 'n': /* do not update the keyring */
            nokeyring = true;
            break;

        case 'v': /* print version number */
            printf("%s: Version 1.1\n", argv[0]);
            return 0;

        case 'h':
        default:
            fprintf(stderr, usage, argv[0]);
            return EXIT_CODE_CMDLINE;
        }
    }

    if (optind >= argc) {
        if (snum == NULL) {
            fprintf(stderr, "A device path must be given.\n");
            fprintf(stderr, usage, argv[0]);
            return EXIT_CODE_CMDLINE;
        } else {
            key_path = calloc(1, 17 + strlen(DEVEKEY));
            memcpy(key_path, DEVEKEY, 1 + strlen(DEVEKEY));
            pem64_encode_bytes(snum, 12, key_path + 16);
        }
    } else {
        key_path = strdup(argv[optind]);
    }


    /* load keyring */
    if (nokeyring == false) {
        if (get_keyring(keyring_filename) < 0) {
            free(key_path);
            return EXIT_CODE_LOADKEYRING;
        }
    }

    /* ensure master key */
    if (mkey == NULL) {
        char s[55];
        int sidx;
        int sodx;
        int slen;

        if (isatty(STDIN) == 0) {
            fprintf(stderr, "A master key must be given.\n");
            free(key_path);
            return EXIT_CODE_MASTERKEY;
        }
        printf("Please enter a master key: ");
        if (fgets(s, sizeof(s), stdin) == NULL) {
            perror("fgets");
        }

        /* we must allow for the user entering spaces in the input */
        slen = strlen(s);
        sidx = sodx = 0;
        while ((sidx < slen) && (s[sidx] != 0)) {
            s[sodx] = s[sidx];
            if (s[sidx] != ' ') {
                sodx++;
            }
            sidx++;
        }
        s[sodx] = 0;

        mkey = extract_master_key(s, sodx);
        if (mkey == NULL) {
            free(key_path);
            return EXIT_CODE_MASTERKEY;
	}
    }

    /* open entropy key device */
    key_stream = estream_open(key_path);
    if (key_stream == NULL) {
        perror("Error");
        fprintf(stderr, "Unable to open %s as the entropy key device.\n", key_path);
        free(key_path);
        return EXIT_CODE_EKEYERR;
    }
    free(key_path);

    epkt = epkt_open(eframe_open(key_stream));

    /* reset key */
    estream_write(key_stream, reset, 1);
    epkt_setsessionkey(epkt, NULL, default_session_key);

    /* wait for serial packet */
    retries = 20;
    do {
        res = epkt_read(epkt, data, 128);
        if (res <= 0) {
            if (errno == EWOULDBLOCK)
                continue;

            perror("Unexpected error");
            return 2;

        } else if (epkt->pkt_type == PKTTYPE_SNUM) {
            break;
        }

        /* reset key */
        estream_write(key_stream, reset, 1);
        epkt_setsessionkey(epkt, NULL, default_session_key);
        retries--;

    } while (retries > 0);

    if (retries == 0) {
        fprintf(stderr, "Timeout obtaining serial number from key.\n");
        return 3;
    }

    if (res != 12) {
        fprintf(stderr, "Bad serial number from key.\n");
        return 4;
    }

    if (snum == NULL) {
        /* no serial number */
        snum = malloc(res);
        memcpy(snum, data, res);
    } else {
        /* ensure serial number matches */
        if (memcmp(snum, data, 12) != 0) {
            fprintf(stderr, "Serial number did not match the one specified.\n");
            return 4;
        }
    }

    /* Initialise the MAC checksum using the serial number and the default
     * shared key
     */
    epkt_setsessionkey(epkt, snum, default_session_key);

    /* Prepare a nonce */
    if (fill_nonce(nonce, 12) != true) {
        fprintf(stderr, "Unable to generate nonce.\n");
        return 1;
    }
    close_nonce();

    /* send nonce MAC */
    mac = calc_mac(snum, mkey, nonce, 12);
    data[0] = 'M';
    pem64_encode_bytes(mac, 6, (char *)data + 1);
    estream_write(key_stream, data, 9);

    /* wait for MAC ack packet */
    retries = 20;
    do {
        res = epkt_read(epkt, data, 128);
        if (res <= 0) {
            if (errno == EWOULDBLOCK)
                continue;

            perror("Unexpected error");
            return 2;
        }

        if (epkt->pkt_type == PKTTYPE_LTREKEYMAC)
            break;

        retries--;
    } while (retries > 0);

    if (retries == 0) {
        fprintf(stderr, "Timeout obtaining MAC acknowledgement packet.\n");
        return 3;
    }

    data[0] = 'L';
    data[17] = '.';
    pem64_encode_bytes(nonce, 12, (char *)data + 1);
    estream_write(key_stream, data, 18);

    /* wait for rekey ack packet */
    do {
        res = epkt_read(epkt, data, 128);
        if (res <= 0) {
            if (errno == EWOULDBLOCK)
                continue;

            if (errno == EPROTO) {
                fprintf(stderr, "Provided master key does not match the device's.\n");
                return 2;
            }

            perror("Unexpected error");
            return 2;
        }
    } while (epkt->pkt_type != PKTTYPE_LTREKEY);

    /* calculate new longterm key */
    PrepareSkein(&rekeying_state, snum, &(mkey[0]), EKEY_SKEIN_PERSONALISATION_LRS);
    Skein_256_Update(&rekeying_state, &(data[0]), 32);
    Skein_256_Update(&rekeying_state, nonce, 12);

    Skein_256_Final(&rekeying_state, session_key);

    if (nokeyring == false) {
        add_ltkey(snum, session_key);
        if (put_keyring(keyring_filename) < 0)
            return EXIT_CODE_WRITEKEYRING;
    } else {
        /* just display new key */
        output_key(stdout, snum, session_key);
    }
    return 0;
}
int main()
{
	int i,j,k;
	clock_t start,stop;
	double tot_time;
	int times_for_one_mac=100000000;
	int index_of_macs=0;
	
	srand(time(NULL));
	for (i=0;i<number_of_different_macs;i++)
		memset(stuff_for_mac[i],0,4096);
	memset(mac_output,0,50);
	
	init_crypto_stuctures(0,0);
	
	for (i=0;i<number_of_different_macs;i++)
	{
		for (j=0;j<4096;j++)
		{
			stuff_for_mac[i][j]=rand()%256; //get a random bytestream to mac
		}
	}	
	
	if (set_as_given_that_everything_maced_will_be_fixed_and_multiple_of_16==0)
	{
		for (i=1;i<800;i++) //for mac sizes 1...800
		{
			start=clock();
			for (j=0;j<times_for_one_mac;j++) //calulate the mac several thousand times (10 mil default)
			{
				//printf("i=%d,j=%d\n",i,j);
				#if squeeze_keys_when_macing==0
					calc_mac(stuff_for_mac[index_of_macs],i,i>32?i-32:i,mac_output);
				#else
					calc_mac(stuff_for_mac[index_of_macs],i,i>16?i-16:i,mac_output);
				#endif
				index_of_macs=(index_of_macs+1)%number_of_different_macs;
			}
			stop=clock();
		
			tot_time=((double) (stop - start)) / CLOCKS_PER_SEC;
			printf("Mac size:%d, loops:%d, time:%lf\n",i,times_for_one_mac,tot_time);
		}
		
	}
	else //if we are sure that the only possible macs would have a length of a muptiple of 16
	{
		for (k=(mac_algorithm==5?3:1);k<15;k++) //from 16 to 15*16 (=240)
		{	
			i=k*16;
			start=clock();
			for (j=0;j<times_for_one_mac;j++) //calc the mac
			{
				//printf("i=%d,j=%d\n",i,j);
				#if squeeze_keys_when_macing==0 || mac_algorithm==5
					calc_mac(stuff_for_mac[index_of_macs],i,i>32?i-32:i,mac_output);
				#else
					calc_mac(stuff_for_mac[index_of_macs],i,i>16?i-16:i,mac_output);
				#endif
				index_of_macs=(index_of_macs+1)%number_of_different_macs;

			}
			stop=clock();
		
			tot_time=((double) (stop - start)) / CLOCKS_PER_SEC;
			printf("Mac size:%d, loops:%d, time:%lf\n",i,times_for_one_mac,tot_time);
		}
	}
	clear_crypto_structures();
	return 0;
}