Exemplo n.º 1
0
/** Returns the OpenSSL keyblock size
 *
 * @copyright (c) 2002-2016, Jouni Malinen <*****@*****.**> and contributors
 * All Rights Reserved.
 *
 * These programs are licensed under the BSD license (the one with
 * advertisement clause removed).
 *
 * this function shamelessly stolen from from
 * hostap:src/crypto/tls_openssl.c:openssl_get_keyblock_size()
 *
 * @param[in] request The current request.
 * @param[in] ssl The current SSL session.
 * @return
 *	- -1 problem with the session.
 *	- >=0 length of the block.
 */
int tls_utils_keyblock_size_get(REQUEST *request, SSL *ssl)
{
	const EVP_CIPHER *c;
	const EVP_MD *h;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
	int md_size;

	if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL || ssl->read_hash == NULL)
		return -1;

	c = ssl->enc_read_ctx->cipher;
	h = EVP_MD_CTX_md(ssl->read_hash);
	if (h)
		md_size = EVP_MD_size(h);
	else if (ssl->s3)
		md_size = ssl->s3->tmp.new_mac_secret_size;
	else
		return -1;

	RDEBUG2("OpenSSL: keyblock size: key_len=%d MD_size=%d "
		   "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
		   EVP_CIPHER_iv_length(c));
	return 2 * (EVP_CIPHER_key_length(c) +
		    md_size +
		    EVP_CIPHER_iv_length(c));
#else
	const SSL_CIPHER *ssl_cipher;
	int cipher, digest;

	ssl_cipher = SSL_get_current_cipher(ssl);
	if (!ssl_cipher)
		return -1;
	cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher);
	digest = SSL_CIPHER_get_digest_nid(ssl_cipher);
	RDEBUG2("OpenSSL: cipher nid %d digest nid %d", cipher, digest);
	if (cipher < 0 || digest < 0)
		return -1;
	c = EVP_get_cipherbynid(cipher);
	h = EVP_get_digestbynid(digest);
	if (!c || !h)
		return -1;

	RDEBUG2("OpenSSL: keyblock size: key_len=%d MD_size=%d IV_len=%d",
		   EVP_CIPHER_key_length(c), EVP_MD_size(h),
		   EVP_CIPHER_iv_length(c));
	return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) +
		    EVP_CIPHER_iv_length(c));
#endif
}
Exemplo n.º 2
0
/* This equivalent functionality was submitted for OpenSSL 1.1.1+ in
 * https://github.com/openssl/openssl/pull/1666 */
static int dtls_get_data_mtu(struct openconnect_info *vpninfo, int mtu)
{
	int ivlen, maclen, blocksize = 0, pad = 0;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
	const SSL_CIPHER *s_ciph = SSL_get_current_cipher(vpninfo->dtls_ssl);
	int cipher_nid;
	const EVP_CIPHER *e_ciph;
	const EVP_MD *e_md;
	char wtf[128];

	cipher_nid = SSL_CIPHER_get_cipher_nid(s_ciph);
	if (cipher_nid == NID_chacha20_poly1305) {
		ivlen = 0; /* Automatically derived from handshake and seqno */
		maclen = 16; /* Poly1305 */
	} else {
		e_ciph = EVP_get_cipherbynid(cipher_nid);
		switch (EVP_CIPHER_mode(e_ciph)) {
		case EVP_CIPH_GCM_MODE:
			ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
			maclen = EVP_GCM_TLS_TAG_LEN;
			break;

		case EVP_CIPH_CCM_MODE:
			ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
			SSL_CIPHER_description(s_ciph, wtf, sizeof(wtf));
			if (strstr(wtf, "CCM8"))
				maclen = 8;
			else
				maclen = 16;
			break;

		case EVP_CIPH_CBC_MODE:
			blocksize = EVP_CIPHER_block_size(e_ciph);
			ivlen = EVP_CIPHER_iv_length(e_ciph);
			pad = 1;

			e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
			maclen = EVP_MD_size(e_md);
			break;

		default:
			vpn_progress(vpninfo, PRG_ERR,
				     _("Unable to calculate DTLS overhead for %s\n"),
				     SSL_CIPHER_get_name(s_ciph));
			ivlen = 0;
			maclen = DTLS_OVERHEAD;
			break;
		}
	}
#else
	/* OpenSSL <= 1.0.2 only supports CBC ciphers with PSK */
	ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(vpninfo->dtls_ssl->enc_read_ctx));
	maclen = EVP_MD_CTX_size(vpninfo->dtls_ssl->read_hash);
	blocksize = ivlen;
	pad = 1;
#endif

	/* Even when it pretended to, OpenSSL never did encrypt-then-mac.
	 * So the MAC is *inside* the encryption, unconditionally.
	 * https://github.com/openssl/openssl/pull/1705 */
	if (mtu < DTLS1_RT_HEADER_LENGTH + ivlen)
		return 0;
	mtu -= DTLS1_RT_HEADER_LENGTH + ivlen;

	/* For CBC mode round down to blocksize */
	if (blocksize)
		mtu -= mtu % blocksize;

	/* Finally, CBC modes require at least one byte to indicate
	 * padding length, as well as the MAC. */
	if (mtu < pad + maclen)
		return 0;
	mtu -= pad + maclen;
	return mtu;
}