Crypt-Bear

 view release on metacpan or  search on metacpan

src/ssl/ssl_rec_cbc.c  view on Meta::CPAN

	}

	/*
	 * Recompute the HMAC value. The input is the concatenation of
	 * the sequence number (8 bytes), the record header (5 bytes),
	 * and the payload.
	 *
	 * At that point, min_len is the minimum plaintext length, but
	 * max_len still includes the MAC length.
	 */
	br_enc64be(tmp2, cc->seq ++);
	tmp2[8] = (unsigned char)record_type;
	br_enc16be(tmp2 + 9, version);
	br_enc16be(tmp2 + 11, len_nomac);
	br_hmac_init(&hc, &cc->mac, cc->mac_len);
	br_hmac_update(&hc, tmp2, 13);
	br_hmac_outCT(&hc, buf, len_nomac, min_len, max_len, tmp2);

	/*
	 * Compare the extracted and recomputed MAC values.
	 */
	for (u = 0; u < cc->mac_len; u ++) {
		good &= EQ0(tmp1[u] ^ tmp2[u]);
	}

	/*
	 * Check that the plaintext length is valid. The previous
	 * check was on the encrypted length, but the padding may have
	 * turned shorter than expected.
	 *
	 * Once this final test is done, the critical "constant-time"
	 * section ends and we can make conditional jumps again.
	 */
	good &= LE(len_nomac, 16384);

	if (!good) {
		return 0;
	}
	*data_len = len_nomac;
	return buf;
}

/* see bearssl_ssl.h */
const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable = {
	{
		sizeof(br_sslrec_in_cbc_context),
		(int (*)(const br_sslrec_in_class *const *, size_t))
			&cbc_check_length,
		(unsigned char *(*)(const br_sslrec_in_class **,
			int, unsigned, void *, size_t *))
			&cbc_decrypt
	},
	(void (*)(const br_sslrec_in_cbc_class **,
		const br_block_cbcdec_class *, const void *, size_t,
		const br_hash_class *, const void *, size_t, size_t,
		const void *))
		&in_cbc_init
};

/*
 * For CBC output:
 *
 * -- With TLS 1.1+, there is an explicit IV. Generation method uses
 * HMAC, computed over the current sequence number, and the current MAC
 * key. The resulting value is truncated to the size of a block, and
 * added at the head of the plaintext; it will get encrypted along with
 * the data. This custom generation mechanism is "safe" under the
 * assumption that HMAC behaves like a random oracle; since the MAC for
 * a record is computed over the concatenation of the sequence number,
 * the record header and the plaintext, the HMAC-for-IV will not collide
 * with the normal HMAC.
 *
 * -- With TLS 1.0, for application data, we want to enforce a 1/n-1
 * split, as a countermeasure against chosen-plaintext attacks. We thus
 * need to leave some room in the buffer for that extra record.
 */

static void
out_cbc_init(br_sslrec_out_cbc_context *cc,
	const br_block_cbcenc_class *bc_impl,
	const void *bc_key, size_t bc_key_len,
	const br_hash_class *dig_impl,
	const void *mac_key, size_t mac_key_len, size_t mac_out_len,
	const void *iv)
{
	cc->vtable = &br_sslrec_out_cbc_vtable;
	cc->seq = 0;
	bc_impl->init(&cc->bc.vtable, bc_key, bc_key_len);
	br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len);
	cc->mac_len = mac_out_len;
	if (iv == NULL) {
		memset(cc->iv, 0, sizeof cc->iv);
		cc->explicit_IV = 1;
	} else {
		memcpy(cc->iv, iv, bc_impl->block_size);
		cc->explicit_IV = 0;
	}
}

static void
cbc_max_plaintext(const br_sslrec_out_cbc_context *cc,
	size_t *start, size_t *end)
{
	size_t blen, len;

	blen = cc->bc.vtable->block_size;
	if (cc->explicit_IV) {
		*start += blen;
	} else {
		*start += 4 + ((cc->mac_len + blen + 1) & ~(blen - 1));
	}
	len = (*end - *start) & ~(blen - 1);
	len -= 1 + cc->mac_len;
	if (len > 16384) {
		len = 16384;
	}
	*end = *start + len;
}

static unsigned char *
cbc_encrypt(br_sslrec_out_cbc_context *cc,



( run in 0.516 second using v1.01-cache-2.11-cpan-e1769b4cff6 )