Exemple #1
0
/* Generate two blocks in counter mode and replace the key with the result. */
static void
change_key(struct fortuna_state *st)
{
    encrypt_counter(st, st->key);
    encrypt_counter(st, st->key + AES256_BLOCKSIZE);
    krb5int_aes_enc_key(st->key, AES256_KEYSIZE, &st->ciph);
}
Exemple #2
0
/*
 * Just take 2 next blocks as new key
 */
static void
rekey(FState * st)
{
	encrypt_counter(st, st->key);
	encrypt_counter(st, st->key + CIPH_BLOCK);
	ciph_init(&st->ciph, st->key, BLOCK);
}
Exemple #3
0
/* Output pseudo-random data from the generator. */
static void
generator_output(struct fortuna_state *st, unsigned char *dst, size_t len)
{
    unsigned char result[AES256_BLOCKSIZE];
    size_t n, count = 0;

    while (len > 0) {
        /* Produce bytes and copy the result into dst. */
        encrypt_counter(st, result);
        n = (len < AES256_BLOCKSIZE) ? len : AES256_BLOCKSIZE;
        memcpy(dst, result, n);
        dst += n;
        len -= n;

        /* Each time we reach MAX_BYTES_PER_KEY bytes, change the key. */
        count += AES256_BLOCKSIZE;
        if (count >= MAX_BYTES_PER_KEY) {
            change_key(st);
            count = 0;
        }
    }
    zap(result, sizeof(result));

    /* Change the key after each request. */
    change_key(st);
}
Exemple #4
0
static void derive_key(struct AVAES *aes, const uint8_t *salt, int label,
                       uint8_t *out, int outlen)
{
    uint8_t input[16] = { 0 };
    memcpy(input, salt, 14);
    // Key derivation rate assumed to be zero
    input[14 - 7] ^= label;
    memset(out, 0, outlen);
    encrypt_counter(aes, input, out, outlen);
}
Exemple #5
0
/*
 * Fortuna relies on AES standing known-plaintext attack.
 * In case it does not, slow down the attacker by initialising
 * the couter to random value.
 */
static void
init_counter(FState * st)
{
	/* Use next block as counter. */
	encrypt_counter(st, st->counter);

	/* Hide the key. */
	rekey(st);

	/* The counter can be shuffled only once. */
	st->counter_init = 1;
}
Exemple #6
0
/*
 * Hide public constants. (counter, pools > 0)
 *
 * This can also be viewed as spreading the startup
 * entropy over all of the components.
 */
static void startup_tricks(FState *st)
{
	int i;
	uint8_t buf[block];

	/* Use next block as counter. */
	encrypt_counter(st, st->counter);

	/* Now shuffle pools, excluding #0 */
	for (i = 1; i < numPools; i++) {
		encrypt_counter(st, buf);
		encrypt_counter(st, buf + ciphBlock);
		md_update(&st->pool[i], buf, block);
	}
	memset(buf, 0, block);

	/* Hide the key. */
	rekey(st);

	/* This can be done only once. */
	st->tricksDone = 1;
}
Exemple #7
0
/*
 * Hide public constants. (counter, pools > 0)
 *
 * This can also be viewed as spreading the startup
 * entropy over all of the components.
 */
static void
startup_tricks(FState *st)
{
	int			i;
	uint8		buf[BLOCK];

	/* Use next block as counter. */
	encrypt_counter(st, st->counter);

	/* Now shuffle pools, excluding #0 */
	for (i = 1; i < NUM_POOLS; i++)
	{
		encrypt_counter(st, buf);
		encrypt_counter(st, buf + CIPH_BLOCK);
		md_update(&st->pool[i], buf, BLOCK);
	}
	px_memset(buf, 0, BLOCK);

	/* Hide the key. */
	rekey(st);

	/* This can be done only once. */
	st->tricks_done = 1;
}
Exemple #8
0
static void
extract_data(FState * st, unsigned count, unsigned char *dst)
{
    unsigned	n;
    unsigned	block_nr = 0;
    pid_t	pid = getpid();

    /* Should we reseed? */
    if (st->pool0_bytes >= POOL0_FILL || st->reseed_count == 0)
	if (enough_time_passed(st))
	    reseed(st);

    /* Do some randomization on first call */
    if (!st->tricks_done)
	startup_tricks(st);

    /* If we forked, force a reseed again */
    if (pid != st->pid) {
	st->pid = pid;
	reseed(st);
    }

    while (count > 0)
    {
	/* produce bytes */
	encrypt_counter(st, st->result);

	/* copy result */
	if (count > CIPH_BLOCK)
	    n = CIPH_BLOCK;
	else
	    n = count;
	memcpy(dst, st->result, n);
	dst += n;
	count -= n;

	/* must not give out too many bytes with one key */
	block_nr++;
	if (block_nr > (RESEED_BYTES / CIPH_BLOCK))
	{
	    rekey(st);
	    block_nr = 0;
	}
    }
    /* Set new key for next request. */
    rekey(st);
}
Exemple #9
0
static void
extract_data(FState * st, unsigned count, uint8 *dst)
{
	unsigned	n;
	unsigned	block_nr = 0;

	/* Can we reseed? */
	if (st->pool0_bytes >= POOL0_FILL && !too_often(st))
		reseed(st);

	/* Is counter initialized? */
	if (!st->counter_init)
		init_counter(st);

	while (count > 0)
	{
		/* produce bytes */
		encrypt_counter(st, st->result);

		/* copy result */
		if (count > CIPH_BLOCK)
			n = CIPH_BLOCK;
		else
			n = count;
		memcpy(dst, st->result, n);
		dst += n;
		count -= n;

		/* must not give out too many bytes with one key */
		block_nr++;
		if (block_nr > (RESEED_BYTES / CIPH_BLOCK))
		{
			rekey(st);
			block_nr = 0;
		}
	}
	/* Set new key for next request. */
	rekey(st);
}
Exemple #10
0
static void extract_data(FState *st, unsigned count, uint8_t *dst)
{
	unsigned n;
	unsigned block_nr = 0;

	/* Should we reseed? */
	if (st->pool0Bytes >= pool0Fill || st->reseedCount == 0)
		if (enough_time_passed(st))
			reseed(st);

	/* Do some randomization on first call */
	if (!st->tricksDone)
		startup_tricks(st);

	while (count > 0) {
		/* produce bytes */
		encrypt_counter(st, st->result);

		/* copy result */
		if (count > ciphBlock)
			n = ciphBlock;
		else
			n = count;
		memmove(dst, st->result, n);
		dst += n;
		count -= n;

		/* must not give out too many bytes with one key */
		block_nr++;
		if (block_nr > (reseedBytes / ciphBlock)) {
			rekey(st);
			block_nr = 0;
		}
	}
	/* Set new key for next request. */
	rekey(st);
}
Exemple #11
0
int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
                    uint8_t *out, int outlen)
{
    uint8_t iv[16] = { 0 }, hmac[20];
    uint64_t index;
    uint32_t ssrc;
    int rtcp, hmac_size, padding;
    uint8_t *buf;

    if (len < 8)
        return AVERROR_INVALIDDATA;

    rtcp = RTP_PT_IS_RTCP(in[1]);
    hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;
    padding = hmac_size;
    if (rtcp)
        padding += 4; // For the RTCP index

    if (len + padding > outlen)
        return 0;

    memcpy(out, in, len);
    buf = out;

    if (rtcp) {
        ssrc = AV_RB32(buf + 4);
        index = s->rtcp_index++;

        buf += 8;
        len -= 8;
    } else {
        int ext, csrc;
        int seq = AV_RB16(buf + 2);

        if (len < 12)
            return AVERROR_INVALIDDATA;

        ssrc = AV_RB32(buf + 8);

        if (seq < s->seq_largest)
            s->roc++;
        s->seq_largest = seq;
        index = seq + (((uint64_t)s->roc) << 16);

        csrc = buf[0] & 0x0f;
        ext = buf[0] & 0x10;

        buf += 12;
        len -= 12;

        buf += 4 * csrc;
        len -= 4 * csrc;
        if (len < 0)
            return AVERROR_INVALIDDATA;

        if (ext) {
            if (len < 4)
                return AVERROR_INVALIDDATA;
            ext = (AV_RB16(buf + 2) + 1) * 4;
            if (len < ext)
                return AVERROR_INVALIDDATA;
            len -= ext;
            buf += ext;
        }
    }

    create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
    av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
    encrypt_counter(s->aes, iv, buf, len);

    if (rtcp) {
        AV_WB32(buf + len, 0x80000000 | index);
        len += 4;
    }

    av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
    av_hmac_update(s->hmac, out, buf + len - out);
    if (!rtcp) {
        uint8_t rocbuf[4];
        AV_WB32(rocbuf, s->roc);
        av_hmac_update(s->hmac, rocbuf, 4);
    }
    av_hmac_final(s->hmac, hmac, sizeof(hmac));

    memcpy(buf + len, hmac, hmac_size);
    len += hmac_size;
    return buf + len - out;
}
Exemple #12
0
int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
{
    uint8_t iv[16] = { 0 }, hmac[20];
    int len = *lenptr;
    int av_uninit(seq_largest);
    uint32_t ssrc, av_uninit(roc);
    uint64_t index;
    int rtcp, hmac_size;

    // TODO: Missing replay protection

    if (len < 2)
        return AVERROR_INVALIDDATA;

    rtcp = RTP_PT_IS_RTCP(buf[1]);
    hmac_size = rtcp ? s->rtcp_hmac_size : s->rtp_hmac_size;

    if (len < hmac_size)
        return AVERROR_INVALIDDATA;

    // Authentication HMAC
    av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth));
    // If MKI is used, this should exclude the MKI as well
    av_hmac_update(s->hmac, buf, len - hmac_size);

    if (!rtcp) {
        int seq = AV_RB16(buf + 2);
        uint32_t v;
        uint8_t rocbuf[4];

        // RFC 3711 section 3.3.1, appendix A
        seq_largest = s->seq_initialized ? s->seq_largest : seq;
        v = roc = s->roc;
        if (seq_largest < 32768) {
            if (seq - seq_largest > 32768)
                v = roc - 1;
        } else {
            if (seq_largest - 32768 > seq)
                v = roc + 1;
        }
        if (v == roc) {
            seq_largest = FFMAX(seq_largest, seq);
        } else if (v == roc + 1) {
            seq_largest = seq;
            roc = v;
        }
        index = seq + (((uint64_t)v) << 16);

        AV_WB32(rocbuf, roc);
        av_hmac_update(s->hmac, rocbuf, 4);
    }

    av_hmac_final(s->hmac, hmac, sizeof(hmac));
    if (memcmp(hmac, buf + len - hmac_size, hmac_size)) {
        av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n");
        return AVERROR_INVALIDDATA;
    }

    len -= hmac_size;
    *lenptr = len;

    if (len < 12)
        return AVERROR_INVALIDDATA;

    if (rtcp) {
        uint32_t srtcp_index = AV_RB32(buf + len - 4);
        len -= 4;
        *lenptr = len;

        ssrc = AV_RB32(buf + 4);
        index = srtcp_index & 0x7fffffff;

        buf += 8;
        len -= 8;
        if (!(srtcp_index & 0x80000000))
            return 0;
    } else {
        int ext, csrc;
        s->seq_initialized = 1;
        s->seq_largest     = seq_largest;
        s->roc             = roc;

        csrc = buf[0] & 0x0f;
        ext  = buf[0] & 0x10;
        ssrc = AV_RB32(buf + 8);

        buf += 12;
        len -= 12;

        buf += 4 * csrc;
        len -= 4 * csrc;
        if (len < 0)
            return AVERROR_INVALIDDATA;

        if (ext) {
            if (len < 4)
                return AVERROR_INVALIDDATA;
            ext = (AV_RB16(buf + 2) + 1) * 4;
            if (len < ext)
                return AVERROR_INVALIDDATA;
            len -= ext;
            buf += ext;
        }
    }

    create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc);
    av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0);
    encrypt_counter(s->aes, iv, buf, len);

    return 0;
}
Exemple #13
0
/*
 * Just take 2 next blocks as new key
 */
static void rekey(FState *st)
{
	encrypt_counter(st, st->key);
	encrypt_counter(st, st->key + ciphBlock);
	ciph_init(&st->ciph, st->key, block);
}