Пример #1
0
/**
 * gnutls_srtp_get_keys:
 * @session: is a #gnutls_session_t type.
 * @key_material: Space to hold the generated key material
 * @key_material_size: The maximum size of the key material
 * @client_key: The master client write key, pointing inside the key material
 * @server_key: The master server write key, pointing inside the key material
 * @client_salt: The master client write salt, pointing inside the key material
 * @server_salt: The master server write salt, pointing inside the key material
 *
 * This is a helper function to generate the keying material for SRTP.
 * It requires the space of the key material to be pre-allocated (should be at least
 * 2x the maximum key size and salt size). The @client_key, @client_salt, @server_key
 * and @server_salt are convenience datums that point inside the key material. They may
 * be %NULL.
 *
 * Returns: On success the size of the key material is returned,
 * otherwise, %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not 
 * sufficient, or a negative error code.
 *
 * Since 3.1.4
 **/
int
gnutls_srtp_get_keys(gnutls_session_t session,
		     void *key_material,
		     unsigned int key_material_size,
		     gnutls_datum_t * client_key,
		     gnutls_datum_t * client_salt,
		     gnutls_datum_t * server_key,
		     gnutls_datum_t * server_salt)
{
	int ret;
	const srtp_profile_st *p;
	gnutls_srtp_profile_t profile;
	unsigned int msize;
	uint8_t *km = key_material;

	ret = gnutls_srtp_get_selected_profile(session, &profile);
	if (ret < 0)
		return gnutls_assert_val(ret);

	p = get_profile(profile);
	if (p == NULL)
		return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM);

	msize = 2 * (p->key_length + p->salt_length);
	if (msize > key_material_size)
		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);

	if (msize == 0)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	ret =
	    gnutls_prf(session, sizeof("EXTRACTOR-dtls_srtp") - 1,
		       "EXTRACTOR-dtls_srtp", 0, 0, NULL, msize,
		       key_material);
	if (ret < 0)
		return gnutls_assert_val(ret);

	if (client_key) {
		client_key->data = km;
		client_key->size = p->key_length;
	}

	if (server_key) {
		server_key->data = km + p->key_length;
		server_key->size = p->key_length;
	}

	if (client_salt) {
		client_salt->data = km + 2 * p->key_length;
		client_salt->size = p->salt_length;
	}

	if (server_salt) {
		server_salt->data =
		    km + 2 * p->key_length + p->salt_length;
		server_salt->size = p->salt_length;
	}

	return msize;
}
void session::prf (size_t label_size, const char *label,
                   int server_random_first,
                   size_t extra_size, const char *extra,
                   size_t outsize, char *out)
{
    RETWRAP (gnutls_prf (s, label_size, label, server_random_first,
                         extra_size, extra, outsize, out));
}
Пример #3
0
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
		       const char *label, int server_random_first,
		       int skip_keyblock, u8 *out, size_t out_len)
{
	if (conn == NULL || conn->session == NULL || skip_keyblock)
		return -1;

	return gnutls_prf(conn->session, os_strlen(label), label,
			  server_random_first, 0, NULL, out_len, (char *) out);
}
Пример #4
0
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
		       const char *label, int server_random_first,
		       u8 *out, size_t out_len)
{
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
	if (conn == NULL || conn->session == NULL)
		return -1;

	return gnutls_prf(conn->session, os_strlen(label), label,
			  server_random_first, 0, NULL, out_len, out);
#else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
	return -1;
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
}
Пример #5
0
static void check_prfs(gnutls_session_t session)
{
	unsigned char key_material[512];
	unsigned char key_material2[512];
	int ret;

	TRY(13, "key expansion", 0, NULL, 34, (uint8_t*)"\xcf\x3e\x1c\x03\x47\x1a\xdf\x4a\x8e\x74\xc6\xda\xcd\xda\x22\xa4\x8e\xa5\xf7\x62\xef\xd6\x47\xe7\x41\x20\xea\x44\xb8\x5d\x66\x87\x0a\x61");
	TRY(6, "hello", 0, NULL, 31, (uint8_t*)"\x83\x6c\xc7\x8e\x1b\x62\xc7\x06\x17\x99\x37\x95\x2e\xb8\x42\x5c\x42\xcd\x75\x65\x2c\xa3\x16\x2b\xab\x0a\xcf\xfc\xc8\x90\x30");
	TRY(7, "context", 5, "abcd\xfa", 31, (uint8_t*)"\x5b\xc7\x72\xe9\xda\xe4\x79\x3e\xfe\x9a\xc5\x6f\xf4\x8d\x5a\xfe\x4c\x8d\x16\xa7\xf0\x13\x13\xf1\x93\xdd\x4b\x43\x65\xc1\x94");
	TRY(12, "null-context", 0, "", 31, (uint8_t*)"\xd7\xb6\xff\x3d\xf7\xbe\x0e\xf2\xd0\xbf\x55\x0b\x56\xac\xfb\x3c\x1d\x5c\xaa\xa8\x71\x45\xf5\xd5\x71\x35\xa2\x35\x83\xc2\xe0");

	TRY_OLD(6, "hello", 0, NULL, 31, (uint8_t*)"\x53\x35\x9b\x1c\xbf\xf2\x50\x85\xa1\xbc\x42\xfb\x45\x92\xc3\xbe\x20\x24\x24\xe2\xeb\x6e\xf7\x4f\xc0\xee\xe3\xaa\x46\x36\xfd");
	TRY_OLD(7, "context", 5, "abcd\xfa", 31, (uint8_t*)"\x5f\x75\xb7\x61\x76\x4c\x1e\x86\x4b\x7d\x2e\x6c\x09\x91\xfd\x1e\xe6\xe8\xee\xf9\x86\x6a\x80\xfe\xf3\xbe\x96\xd0\x47\xf5\x9e");

	/* check whether gnutls_prf matches gnutls_prf_rfc5705 when no context is given */
	ret = gnutls_prf(session, 4, "aaaa", 0, 0, NULL, 64,
			 (void*)key_material);
	if (ret < 0) {
		fprintf(stderr, "gnutls_prf: error in %d\n", __LINE__);
		gnutls_perror(ret);
		exit(1);
	}

	ret = gnutls_prf_rfc5705(session, 4, "aaaa", 0, NULL, 64,
			 (void*)key_material2);
	if (ret < 0) {
		fprintf(stderr, "gnutls_prf_rfc5705: error in %d\n", __LINE__);
		gnutls_perror(ret);
		exit(1);
	}

	if (memcmp(key_material, key_material2, 64) != 0) {
		fprintf(stderr, "gnutls_prf: output doesn't match in cross-check\n");
		dump("got1 ", key_material, 64);
		dump("got2 ", key_material2, 64);
		exit(1);
	}
}
Пример #6
0
static void client(int fd)
{
	gnutls_session_t session;
	int ret;
	gnutls_anon_client_credentials_t anoncred;
	gnutls_datum_t mac_key, iv, cipher_key;
	gnutls_datum_t read_mac_key, read_iv, read_cipher_key;
	unsigned char rseq_number[8];
	unsigned char wseq_number[8];
	unsigned char key_material[512], *p;
	unsigned i;
	unsigned block_size, hash_size, key_size, iv_size;
	const char *err;
	/* Need to enable anonymous KX specifically. */

	global_init();

	if (debug) {
		gnutls_global_set_log_function(client_log_func);
		gnutls_global_set_log_level(4711);
	}

	gnutls_anon_allocate_client_credentials(&anoncred);

	/* Initialize TLS session
	 */
	gnutls_init(&session, GNUTLS_CLIENT);

	/* Use default priorities */
	ret = gnutls_priority_set_direct(session,
				   "NONE:+VERS-TLS1.0:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+ANON-DH:+ANON-ECDH:+CURVE-ALL",
				   &err);
	if (ret < 0) {
		fail("client: priority set failed (%s): %s\n",
		     gnutls_strerror(ret), err);
		exit(1);
	}

	/* put the anonymous credentials to the current session
	 */
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_transport_set_int(session, fd);

	/* Perform the TLS handshake
	 */
	do {
		ret = gnutls_handshake(session);
	}
	while (ret < 0 && gnutls_error_is_fatal(ret) == 0);

	if (ret < 0) {
		fail("client: Handshake failed: %s\n", strerror(ret));
		terminate();
	} else {
		if (debug)
			success("client: Handshake was completed\n");
	}

	if (debug)
		success("client: TLS version is: %s\n",
			gnutls_protocol_get_name
			(gnutls_protocol_get_version(session)));

	ret = gnutls_cipher_get(session);
	if (ret != GNUTLS_CIPHER_AES_128_CBC) {
		fprintf(stderr, "negotiated unexpected cipher: %s\n", gnutls_cipher_get_name(ret));
		terminate();
	}

	ret = gnutls_mac_get(session);
	if (ret != GNUTLS_MAC_SHA1) {
		fprintf(stderr, "negotiated unexpected mac: %s\n", gnutls_mac_get_name(ret));
		terminate();
	}

	iv_size = 16;
	hash_size = 20;
	key_size = 16;
	block_size = 2*hash_size + 2*key_size + 2 *iv_size;

	ret = gnutls_prf(session, 13, "key expansion", 1, 0, NULL, block_size,
                         (void*)key_material);
	if (ret < 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		gnutls_perror(ret);
		terminate();
	}
	p = key_material;

	/* check whether the key material matches our calculations */
	ret = gnutls_record_get_state(session, 0, &mac_key, &iv, &cipher_key, wseq_number);
	if (ret < 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		gnutls_perror(ret);
		terminate();
	}

	if (memcmp(wseq_number, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) != 0) {
		dump("wseq:", wseq_number, 8);
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}

	ret = gnutls_record_get_state(session, 1, &read_mac_key, &read_iv, &read_cipher_key, rseq_number);
	if (ret < 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		gnutls_perror(ret);
		terminate();
	}

	if (memcmp(rseq_number, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) != 0) {
		dump("rseq:", rseq_number, 8);
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}

	if (hash_size != mac_key.size || memcmp(p, mac_key.data, hash_size) != 0) {
		dump("MAC:", mac_key.data, mac_key.size);
		dump("Block:", key_material, block_size);
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}
	p+= hash_size;

	if (hash_size != read_mac_key.size || memcmp(p, read_mac_key.data, hash_size) != 0) {
		dump("MAC:", read_mac_key.data, read_mac_key.size);
		dump("Block:", key_material, block_size);
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}
	p+= hash_size;

	if (key_size != cipher_key.size || memcmp(p, cipher_key.data, key_size) != 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}
	p+= key_size;

	if (key_size != read_cipher_key.size || memcmp(p, read_cipher_key.data, key_size) != 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}
	p+= key_size;

	if (iv_size != iv.size || memcmp(p, iv.data, iv_size) != 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}
	p+=iv_size;

	if (iv_size != read_iv.size || memcmp(p, read_iv.data, iv_size) != 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}

	/* check sequence numbers */
	for (i=0;i<5;i++) {
		ret = gnutls_record_send(session, "hello", 5);
		if (ret < 0) {
			fail("gnutls_record_send: %s\n", gnutls_strerror(ret));
		}
	}

	ret = gnutls_record_get_state(session, 0, NULL, NULL, NULL, wseq_number);
	if (ret < 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		gnutls_perror(ret);
		terminate();
	}

	if (memcmp(wseq_number, "\x00\x00\x00\x00\x00\x00\x00\x06", 8) != 0) {
		dump("wseq:", wseq_number, 8);
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}

	ret = gnutls_record_get_state(session, 1, NULL, NULL, NULL, rseq_number);
	if (ret < 0) {
		fprintf(stderr, "error in %d\n", __LINE__);
		gnutls_perror(ret);
		terminate();
	}

	if (memcmp(rseq_number, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) != 0) {
		dump("wseq:", wseq_number, 8);
		fprintf(stderr, "error in %d\n", __LINE__);
		terminate();
	}
	gnutls_bye(session, GNUTLS_SHUT_WR);

	close(fd);

	gnutls_deinit(session);

	gnutls_anon_free_client_credentials(anoncred);

	gnutls_global_deinit();
}