18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without
78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met:
88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice,
100ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    this list of conditions and the following disclaimer.
118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright
138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    notice, this list of conditions and the following disclaimer in
140ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    the documentation and/or other materials provided with the distribution.
158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its
178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    contributors may be used to endorse or promote products derived
188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    from this software without specific prior written permission.
198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE.
318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/cdefs.h>
35fb3816eaffe5878bb1286adb120fd160da178a05t__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 269858 2014-08-12 11:30:16Z tuexen $");
368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h>
398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp.h>
408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h>
418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h>
428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h>
438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h>
448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h>
458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_indata.h>
468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h>
478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_auth.h>
488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG
508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SCTP_AUTH_DEBUG		(SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_AUTH1)
518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SCTP_AUTH_DEBUG2	(SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_AUTH2)
528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_DEBUG */
538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_clear_chunklist(sctp_auth_chklist_t *chklist)
578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(chklist, sizeof(*chklist));
598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* chklist->num_chunks = 0; */
608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_chklist_t *
638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_alloc_chunklist(void)
648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_auth_chklist_t *chklist;
668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(chklist, sctp_auth_chklist_t *, sizeof(*chklist),
688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_AUTH_CL);
698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (chklist == NULL) {
708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1, "sctp_alloc_chunklist: failed to get memory!\n");
718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clear_chunklist(chklist);
738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (chklist);
758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_chunklist(sctp_auth_chklist_t *list)
798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list != NULL)
818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(list, SCTP_M_AUTH_CL);
828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_chklist_t *
858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_copy_chunklist(sctp_auth_chklist_t *list)
868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_auth_chklist_t *new_list;
888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get a new list */
938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_list = sctp_alloc_chunklist();
948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_list == NULL)
958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* copy it */
978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bcopy(list, new_list, sizeof(*new_list));
988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_list);
1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add a chunk to the required chunks list
1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_add_chunk(uint8_t chunk, sctp_auth_chklist_t *list)
1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* is chunk restricted? */
1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((chunk == SCTP_INITIATION) ||
1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (chunk == SCTP_INITIATION_ACK) ||
1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (chunk == SCTP_SHUTDOWN_COMPLETE) ||
1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (chunk == SCTP_AUTHENTICATION)) {
1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list->chunks[chunk] == 0) {
1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		list->chunks[chunk] = 1;
1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		list->num_chunks++;
1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1,
1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"SCTP: added chunk %u (0x%02x) to Auth list\n",
1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chunk, chunk);
1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delete a chunk from the required chunks list
1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t *list)
1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list->chunks[chunk] == 1) {
1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		list->chunks[chunk] = 0;
1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		list->num_chunks--;
1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1,
1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"SCTP: deleted chunk %u (0x%02x) from Auth list\n",
1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chunk, chunk);
1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensize_t
1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_get_chklist_size(const sctp_auth_chklist_t *list)
1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (list->num_chunks);
1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * return the current number and list of required chunks caller must
1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * guarantee ptr has space for up to 256 bytes
1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_serialize_auth_chunks(const sctp_auth_chklist_t *list, uint8_t *ptr)
1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i, count = 0;
1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < 256; i++) {
1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (list->chunks[i] != 0) {
1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*ptr++ = i;
1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			count++;
1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (count);
1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_pack_auth_chunks(const sctp_auth_chklist_t *list, uint8_t *ptr)
1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i, size = 0;
1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list->num_chunks <= 32) {
1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* just list them, one byte each */
1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < 256; i++) {
1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (list->chunks[i] != 0) {
1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*ptr++ = i;
1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				size++;
1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int index, offset;
1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* pack into a 32 byte bitfield */
1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < 256; i++) {
1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (list->chunks[i] != 0) {
2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				index = i / 8;
2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				offset = i % 8;
2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ptr[index] |= (1 << offset);
2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size = 32;
2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (size);
2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
2118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_unpack_auth_chunks(const uint8_t *ptr, uint8_t num_chunks,
2128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    sctp_auth_chklist_t *list)
2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int size;
2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (num_chunks <= 32) {
2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* just pull them, one byte each */
2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < num_chunks; i++) {
2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)sctp_auth_add_chunk(*ptr++, list);
2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size = num_chunks;
2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int index, offset;
2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* unpack from a 32 byte bitfield */
2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (index = 0; index < 32; index++) {
2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (offset = 0; offset < 8; offset++) {
2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (ptr[index] & (1 << offset)) {
2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(void)sctp_auth_add_chunk((index * 8) + offset, list);
2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
2368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size = 32;
2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (size);
2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
2448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * allocate structure space for a key of length keylen
2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_key_t *
2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_alloc_key(uint32_t keylen)
2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *new_key;
2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(new_key, sctp_key_t *, sizeof(*new_key) + keylen,
2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_AUTH_KY);
2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_key == NULL) {
2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* out of memory */
2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key->keylen = keylen;
2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_key);
2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_key(sctp_key_t *key)
2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key != NULL)
2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(key,SCTP_M_AUTH_KY);
2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_print_key(sctp_key_t *key, const char *str)
2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key == NULL) {
27447a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("%s: [Null key]\n", str);
2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
27747a306d634abf33223ef347472c4b1cd441d139ftuexen	SCTP_PRINTF("%s: len %u, ", str, key->keylen);
2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key->keylen) {
2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < key->keylen; i++)
28047a306d634abf33223ef347472c4b1cd441d139ftuexen			SCTP_PRINTF("%02x", key->key[i]);
28147a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\n");
2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
28347a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("[Null key]\n");
2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_show_key(sctp_key_t *key, const char *str)
2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key == NULL) {
29347a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("%s: [Null key]\n", str);
2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29647a306d634abf33223ef347472c4b1cd441d139ftuexen	SCTP_PRINTF("%s: len %u, ", str, key->keylen);
2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key->keylen) {
2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < key->keylen; i++)
29947a306d634abf33223ef347472c4b1cd441d139ftuexen			SCTP_PRINTF("%02x", key->key[i]);
30047a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\n");
3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
30247a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("[Null key]\n");
3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_get_keylen(sctp_key_t *key)
3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key != NULL)
3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (key->keylen);
3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
3128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * generate a new random key of length 'keylen'
3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_key_t *
3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_generate_random_key(uint32_t keylen)
3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *new_key;
3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key = sctp_alloc_key(keylen);
3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_key == NULL) {
3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* out of memory */
3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_READ_RANDOM(new_key->key, keylen);
3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key->keylen = keylen;
3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_key);
3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_key_t *
3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_key(uint8_t *key, uint32_t keylen)
3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *new_key;
3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key = sctp_alloc_key(keylen);
3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_key == NULL) {
3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* out of memory */
3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bcopy(key, new_key->key, keylen);
3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_key);
3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * given two keys of variable size, compute which key is "larger/smaller"
3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns:  1 if key1 > key2
3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *          -1 if key1 < key2
3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *           0 if key1 = key2
3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_compare_key(sctp_key_t *key1, sctp_key_t *key2)
3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t maxlen;
3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t key1len, key2len;
3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t *key_1, *key_2;
3607ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft	uint8_t val1, val2;
3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sanity/length check */
3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key1len = sctp_get_keylen(key1);
3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key2len = sctp_get_keylen(key2);
3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((key1len == 0) && (key2len == 0))
3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else if (key1len == 0)
3688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else if (key2len == 0)
3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (1);
3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3727ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft	if (key1len < key2len) {
3737ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft		maxlen = key2len;
3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		maxlen = key1len;
3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3777ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft	key_1 = key1->key;
3787ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft	key_2 = key2->key;
3797ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft	/* check for numeric equality */
3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < maxlen; i++) {
3817ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft		/* left-pad with zeros */
3827ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft		val1 = (i < (maxlen - key1len)) ? 0 : *(key_1++);
3837ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft		val2 = (i < (maxlen - key2len)) ? 0 : *(key_2++);
3847ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft		if (val1 > val2) {
385e2828360ea9cf8951730d46f5c14626c9425cb30t			return (1);
3867ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft		} else if (val1 < val2) {
387e2828360ea9cf8951730d46f5c14626c9425cb30t			return (-1);
3887ae794ed3b1a9eeb54883dfb3241c0ef886ca43ft		}
3898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* keys are equal value, so check lengths */
3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key1len == key2len)
3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else if (key1len < key2len)
3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (1);
3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * generate the concatenated keying material based on the two keys and the
4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * shared key (if available). draft-ietf-tsvwg-auth specifies the specific
4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * order for concatenation
4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_key_t *
4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_compute_hashkey(sctp_key_t *key1, sctp_key_t *key2, sctp_key_t *shared)
4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t keylen;
4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *new_key;
4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t *key_ptr;
4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = sctp_get_keylen(key1) + sctp_get_keylen(key2) +
4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_get_keylen(shared);
4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keylen > 0) {
4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get space for the new key */
4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_key = sctp_alloc_key(keylen);
4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (new_key == NULL) {
4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* out of memory */
4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (NULL);
4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_key->keylen = keylen;
4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		key_ptr = new_key->key;
4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* all keys empty/null?! */
4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* concatenate the keys */
4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_compare_key(key1, key2) <= 0) {
4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* key is shared + key1 + key2 */
4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_get_keylen(shared)) {
4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(shared->key, key_ptr, shared->keylen);
4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			key_ptr += shared->keylen;
4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_get_keylen(key1)) {
4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(key1->key, key_ptr, key1->keylen);
4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			key_ptr += key1->keylen;
4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_get_keylen(key2)) {
4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(key2->key, key_ptr, key2->keylen);
4418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* key is shared + key2 + key1 */
4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_get_keylen(shared)) {
4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(shared->key, key_ptr, shared->keylen);
4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			key_ptr += shared->keylen;
4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_get_keylen(key2)) {
4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(key2->key, key_ptr, key2->keylen);
4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			key_ptr += key2->keylen;
4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_get_keylen(key1)) {
4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(key1->key, key_ptr, key1->keylen);
4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_key);
4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_sharedkey_t *
4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_alloc_sharedkey(void)
4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *new_key;
4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(new_key, sctp_sharedkey_t *, sizeof(*new_key),
4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_AUTH_KY);
4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_key == NULL) {
4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* out of memory */
4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key->keyid = 0;
4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key->key = NULL;
4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key->refcount = 1;
4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key->deactivated = 0;
4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_key);
4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_sharedkey(sctp_sharedkey_t *skey)
4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
4818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey == NULL)
4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
4838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&skey->refcount)) {
4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (skey->key != NULL)
4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_key(skey->key);
4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(skey, SCTP_M_AUTH_KY);
4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_sharedkey_t *
4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_sharedkey(struct sctp_keyhead *shared_keys, uint16_t key_id)
4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
4958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(skey, shared_keys, next) {
4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (skey->keyid == key_id)
4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (skey);
4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (NULL);
5018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_insert_sharedkey(struct sctp_keyhead *shared_keys,
5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		      sctp_sharedkey_t *new_skey)
5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((shared_keys == NULL) || (new_skey == NULL))
5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* insert into an empty list? */
5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (LIST_EMPTY(shared_keys)) {
5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_INSERT_HEAD(shared_keys, new_skey, next);
5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
5168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* insert into the existing list, ordered by key id */
5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(skey, shared_keys, next) {
5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (new_skey->keyid < skey->keyid) {
5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* insert it before here */
5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_INSERT_BEFORE(skey, new_skey, next);
5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (new_skey->keyid == skey->keyid) {
5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* replace the existing key */
5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* verify this key *can* be replaced */
5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((skey->deactivated) && (skey->refcount > 1)) {
5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_AUTH1,
5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					"can't replace shared key id %u\n",
5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_skey->keyid);
5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EBUSY);
5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_AUTH1,
5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				"replacing shared key id %u\n",
5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_skey->keyid);
5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_INSERT_BEFORE(skey, new_skey, next);
5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_REMOVE(skey, next);
5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_sharedkey(skey);
5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (LIST_NEXT(skey, next) == NULL) {
5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* belongs at the end of the list */
5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_INSERT_AFTER(skey, new_skey, next);
5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* shouldn't reach here */
5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t key_id)
5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
554000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
5558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the shared key */
5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, key_id);
557000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* bump the ref count */
5598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey) {
5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&skey->refcount, 1);
5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH2,
5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"%s: stcb %p key %u refcount acquire to %d\n",
563ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t			__FUNCTION__, (void *)stcb, key_id, skey->refcount);
5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked
5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_UNUSED
5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen)
5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
575000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the shared key */
5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, key_id);
578000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* decrement the ref count */
5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey) {
5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_sharedkey(skey);
5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH2,
5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"%s: stcb %p key %u refcount release to %d\n",
584ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t			__FUNCTION__, (void *)stcb, key_id, skey->refcount);
5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* see if a notification should be generated */
5878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((skey->refcount <= 1) && (skey->deactivated)) {
5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* notify ULP that key is no longer used */
5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ulp_notify(SCTP_NOTIFY_AUTH_FREE_KEY, stcb,
5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					key_id, 0, so_locked);
5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_AUTH2,
5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				"%s: stcb %p key %u no longer used, %d\n",
593ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t				__FUNCTION__, (void *)stcb, key_id, skey->refcount);
5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic sctp_sharedkey_t *
5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_copy_sharedkey(const sctp_sharedkey_t *skey)
6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *new_skey;
6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey == NULL)
6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_skey = sctp_alloc_sharedkey();
6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_skey == NULL)
6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey->key != NULL)
6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_skey->key = sctp_set_key(skey->key->key, skey->key->keylen);
6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
6118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_skey->key = NULL;
6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_skey->keyid = skey->keyid;
6138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_skey);
6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_copy_skeylist(const struct sctp_keyhead *src, struct sctp_keyhead *dest)
6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey, *new_skey;
6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int count = 0;
6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((src == NULL) || (dest == NULL))
6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(skey, src, next) {
6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_skey = sctp_copy_sharedkey(skey);
6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (new_skey != NULL) {
6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)sctp_insert_sharedkey(dest, new_skey);
6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			count++;
6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (count);
6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hmaclist_t *
6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_alloc_hmaclist(uint8_t num_hmacs)
6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmaclist_t *new_list;
6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int alloc_size;
6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	alloc_size = sizeof(*new_list) + num_hmacs * sizeof(new_list->hmac[0]);
6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(new_list, sctp_hmaclist_t *, alloc_size,
6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_AUTH_HL);
6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_list == NULL) {
6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* out of memory */
6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_list->max_algo = num_hmacs;
6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_list->num_algo = 0;
6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_list);
6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_hmaclist(sctp_hmaclist_t *list)
6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list != NULL) {
6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(list,SCTP_M_AUTH_HL);
6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		list = NULL;
6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_add_hmacid(sctp_hmaclist_t *list, uint16_t hmac_id)
6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list->num_algo == list->max_algo) {
6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1,
6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"SCTP: HMAC id list full, ignoring add %u\n", hmac_id);
6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67383a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#if defined(SCTP_SUPPORT_HMAC_SHA256)
6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((hmac_id != SCTP_AUTH_HMAC_ID_SHA1) &&
67583a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t	    (hmac_id != SCTP_AUTH_HMAC_ID_SHA256)) {
67683a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#else
67783a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t	if (hmac_id != SCTP_AUTH_HMAC_ID_SHA1) {
6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now is it already in the list */
682b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	for (i = 0; i < list->num_algo; i++) {
6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (list->hmac[i] == hmac_id) {
6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* already in list */
6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (-1);
6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_AUTH1, "SCTP: add HMAC id %u to list\n", hmac_id);
6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	list->hmac[list->num_algo++] = hmac_id;
6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
6918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hmaclist_t *
6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_copy_hmaclist(sctp_hmaclist_t *list)
6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmaclist_t *new_list;
6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get a new list */
7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_list = sctp_alloc_hmaclist(list->max_algo);
7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_list == NULL)
7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* copy it */
7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_list->max_algo = list->max_algo;
7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_list->num_algo = list->num_algo;
7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < list->num_algo; i++)
7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_list->hmac[i] = list->hmac[i];
7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_list);
7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hmaclist_t *
7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_default_supported_hmaclist(void)
7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmaclist_t *new_list;
7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
71883a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#if defined(SCTP_SUPPORT_HMAC_SHA256)
7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_list = sctp_alloc_hmaclist(2);
72083a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#else
72183a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t	new_list = sctp_alloc_hmaclist(1);
72283a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#endif
7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_list == NULL)
7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
72583a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#if defined(SCTP_SUPPORT_HMAC_SHA256)
72683a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t	/* We prefer SHA256, so list it first */
7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA256);
72883a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#endif
72983a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t	(void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1);
7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_list);
7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * HMAC algos are listed in priority/preference order
7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find the best HMAC id to use for the peer based on local support
7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint16_t
7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_negotiate_hmacid(sctp_hmaclist_t *peer, sctp_hmaclist_t *local)
7398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i, j;
7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((local == NULL) || (peer == NULL))
7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (SCTP_AUTH_HMAC_ID_RSVD);
7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < peer->num_algo; i++) {
7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (j = 0; j < local->num_algo; j++) {
7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (peer->hmac[i] == local->hmac[j]) {
7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* found the "best" one */
7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_AUTH1,
7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					"SCTP: negotiated peer HMAC id %u\n",
7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					peer->hmac[i]);
7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (peer->hmac[i]);
7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* didn't find one! */
7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (SCTP_AUTH_HMAC_ID_RSVD);
7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * serialize the HMAC algo list and return space used
7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * caller must guarantee ptr has appropriate space
7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_serialize_hmaclist(sctp_hmaclist_t *list, uint8_t *ptr)
7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t hmac_id;
7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (list == NULL)
7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < list->num_algo; i++) {
7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hmac_id = htons(list->hmac[i]);
7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bcopy(&hmac_id, ptr, sizeof(hmac_id));
7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ptr += sizeof(hmac_id);
7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (list->num_algo * sizeof(hmac_id));
7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_verify_hmac_param (struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs)
7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < num_hmacs; i++) {
78783a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t		if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) {
788e2828360ea9cf8951730d46f5c14626c9425cb30t			return (0);
78983a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t		}
7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
79183a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t	return (-1);
7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_authinfo_t *
7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_alloc_authinfo(void)
7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_authinfo_t *new_authinfo;
7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(new_authinfo, sctp_authinfo_t *, sizeof(*new_authinfo),
8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_AUTH_IF);
8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_authinfo == NULL) {
8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* out of memory */
8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(new_authinfo, sizeof(*new_authinfo));
8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (new_authinfo);
8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_authinfo(sctp_authinfo_t *authinfo)
8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (authinfo == NULL)
8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (authinfo->random != NULL)
8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_key(authinfo->random);
8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (authinfo->peer_random != NULL)
8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_key(authinfo->peer_random);
8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (authinfo->assoc_key != NULL)
8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_key(authinfo->assoc_key);
8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (authinfo->recv_key != NULL)
8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_key(authinfo->recv_key);
8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We are NOT dynamically allocating authinfo's right now... */
8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* SCTP_FREE(authinfo, SCTP_M_AUTH_??); */
8278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_get_auth_chunk_len(uint16_t hmac_algo)
8328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int size;
8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size = sizeof(struct sctp_auth_chunk) + sctp_get_hmac_digest_len(hmac_algo);
8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (SCTP_SIZE32(size));
8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_get_hmac_digest_len(uint16_t hmac_algo)
8418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (hmac_algo) {
8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA1:
8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (SCTP_AUTH_DIGEST_LEN_SHA1);
84583a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#if defined(SCTP_SUPPORT_HMAC_SHA256)
8468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA256:
8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (SCTP_AUTH_DIGEST_LEN_SHA256);
8488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
8508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* unknown HMAC algorithm: can't do anything */
8518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch */
8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic inline int
8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_get_hmac_block_len(uint16_t hmac_algo)
8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (hmac_algo) {
8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA1:
8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (64);
86183a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#if defined(SCTP_SUPPORT_HMAC_SHA256)
8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA256:
8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (64);
8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_RSVD:
8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* unknown HMAC algorithm: can't do anything */
8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch */
8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
8738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* __Userspace__ SHA1_Init is defined in libcrypto.a (libssl-dev on Ubuntu) */
8748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
8768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hmac_init(uint16_t hmac_algo, sctp_hash_context_t *ctx)
8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (hmac_algo) {
8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA1:
88083a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t		SCTP_SHA1_INIT(&ctx->sha1);
8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
88283a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#if defined(SCTP_SUPPORT_HMAC_SHA256)
8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA256:
88483a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t		SCTP_SHA256_INIT(&ctx->sha256);
8858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_RSVD:
8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* unknown HMAC algorithm: can't do anything */
8908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch */
8928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
8958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hmac_update(uint16_t hmac_algo, sctp_hash_context_t *ctx,
8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint8_t *text, uint32_t textlen)
8978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (hmac_algo) {
8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA1:
90083a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t		SCTP_SHA1_UPDATE(&ctx->sha1, text, textlen);
9018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
90283a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#if defined(SCTP_SUPPORT_HMAC_SHA256)
9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA256:
90483a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t		SCTP_SHA256_UPDATE(&ctx->sha256, text, textlen);
9058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_RSVD:
9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* unknown HMAC algorithm: can't do anything */
9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch */
9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hmac_final(uint16_t hmac_algo, sctp_hash_context_t *ctx,
9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint8_t *digest)
9178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (hmac_algo) {
9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA1:
92083a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t		SCTP_SHA1_FINAL(digest, &ctx->sha1);
9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
92283a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t#if defined(SCTP_SUPPORT_HMAC_SHA256)
9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_SHA256:
92483a86bbf399ce2b9b51cdf1c0c679944bbcee0a9t		SCTP_SHA256_FINAL(digest, &ctx->sha256);
9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_HMAC_ID_RSVD:
9288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
9298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* unknown HMAC algorithm: can't do anything */
9308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
9318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch */
9328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
9358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Keyed-Hashing for Message Authentication: FIPS 198 (RFC 2104)
9368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Compute the HMAC digest using the desired hash key, text, and HMAC
9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * algorithm.  Resulting digest is placed in 'digest' and digest length
9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is returned, if the HMAC was performed.
9408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * WARNING: it is up to the caller to supply sufficient space to hold the
9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * resultant digest.
9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hmac(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint8_t *text, uint32_t textlen, uint8_t *digest)
9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t digestlen;
9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t blocklen;
9508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hash_context_t ctx;
9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t ipad[128], opad[128];	/* keyed hash inner/outer pads */
9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sanity check the material and length */
9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((key == NULL) || (keylen == 0) || (text == NULL) ||
9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (textlen == 0) || (digest == NULL)) {
9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* can't do HMAC with empty key or text or digest store */
9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* validate the hmac algo and get the digest length */
9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digestlen = sctp_get_hmac_digest_len(hmac_algo);
9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (digestlen == 0)
9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* hash the key if it is longer than the hash block size */
9678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	blocklen = sctp_get_hmac_block_len(hmac_algo);
9688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keylen > blocklen) {
9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_init(hmac_algo, &ctx);
9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_update(hmac_algo, &ctx, key, keylen);
9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_final(hmac_algo, &ctx, temp);
9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* set the hashed key as the key */
9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		keylen = digestlen;
9748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		key = temp;
9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* initialize the inner/outer pads with the key and "append" zeroes */
9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(ipad, blocklen);
9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(opad, blocklen);
9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bcopy(key, ipad, keylen);
9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bcopy(key, opad, keylen);
9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* XOR the key with ipad and opad values */
9838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < blocklen; i++) {
9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ipad[i] ^= 0x36;
9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		opad[i] ^= 0x5c;
9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* perform inner hash */
9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_init(hmac_algo, &ctx);
9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_update(hmac_algo, &ctx, ipad, blocklen);
9918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_update(hmac_algo, &ctx, text, textlen);
9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_final(hmac_algo, &ctx, temp);
9938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* perform outer hash */
9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_init(hmac_algo, &ctx);
9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_update(hmac_algo, &ctx, opad, blocklen);
9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_update(hmac_algo, &ctx, temp, digestlen);
9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_final(hmac_algo, &ctx, digest);
9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (digestlen);
10018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* mbuf version */
10048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hmac_m(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
10068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf *m, uint32_t m_offset, uint8_t *digest, uint32_t trailer)
10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
10088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t digestlen;
10098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t blocklen;
10108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hash_context_t ctx;
10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t ipad[128], opad[128];	/* keyed hash inner/outer pads */
10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_tmp;
10158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sanity check the material and length */
10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((key == NULL) || (keylen == 0) || (m == NULL) || (digest == NULL)) {
10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* can't do HMAC with empty key or text or digest store */
10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* validate the hmac algo and get the digest length */
10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digestlen = sctp_get_hmac_digest_len(hmac_algo);
10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (digestlen == 0)
10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
10258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* hash the key if it is longer than the hash block size */
10278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	blocklen = sctp_get_hmac_block_len(hmac_algo);
10288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keylen > blocklen) {
10298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_init(hmac_algo, &ctx);
10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_update(hmac_algo, &ctx, key, keylen);
10318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_final(hmac_algo, &ctx, temp);
10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* set the hashed key as the key */
10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		keylen = digestlen;
10348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		key = temp;
10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* initialize the inner/outer pads with the key and "append" zeroes */
10378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(ipad, blocklen);
10388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(opad, blocklen);
10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bcopy(key, ipad, keylen);
10408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bcopy(key, opad, keylen);
10418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* XOR the key with ipad and opad values */
10438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < blocklen; i++) {
10448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ipad[i] ^= 0x36;
10458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		opad[i] ^= 0x5c;
10468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* perform inner hash */
10498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_init(hmac_algo, &ctx);
10508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_update(hmac_algo, &ctx, ipad, blocklen);
10518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the correct starting mbuf and offset (get start of text) */
10528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_tmp = m;
10538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while ((m_tmp != NULL) && (m_offset >= (uint32_t) SCTP_BUF_LEN(m_tmp))) {
10548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_offset -= SCTP_BUF_LEN(m_tmp);
10558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_tmp = SCTP_BUF_NEXT(m_tmp);
10568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now use the rest of the mbuf chain for the text */
10588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (m_tmp != NULL) {
10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((SCTP_BUF_NEXT(m_tmp) == NULL) && trailer) {
10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_hmac_update(hmac_algo, &ctx, mtod(m_tmp, uint8_t *) + m_offset,
10618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 SCTP_BUF_LEN(m_tmp) - (trailer+m_offset));
10628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
10638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_hmac_update(hmac_algo, &ctx, mtod(m_tmp, uint8_t *) + m_offset,
10648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 SCTP_BUF_LEN(m_tmp) - m_offset);
10658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clear the offset since it's only for the first mbuf */
10688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_offset = 0;
10698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_tmp = SCTP_BUF_NEXT(m_tmp);
10708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_final(hmac_algo, &ctx, temp);
10728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* perform outer hash */
10748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_init(hmac_algo, &ctx);
10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_update(hmac_algo, &ctx, opad, blocklen);
10768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_update(hmac_algo, &ctx, temp, digestlen);
10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac_final(hmac_algo, &ctx, digest);
10788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (digestlen);
10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
10818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
10838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * verify the HMAC digest using the desired hash key, text, and HMAC
10848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * algorithm.
10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Returns -1 on error, 0 on success.
10868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
10878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
10888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_verify_hmac(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint8_t *text, uint32_t textlen,
10908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint8_t *digest, uint32_t digestlen)
10918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t len;
10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sanity check the material and length */
10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((key == NULL) || (keylen == 0) ||
10978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (text == NULL) || (textlen == 0) || (digest == NULL)) {
10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* can't do HMAC with empty key or text or digest */
10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	len = sctp_get_hmac_digest_len(hmac_algo);
11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((len == 0) || (digestlen != len))
11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* compute the expected hash */
11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_hmac(hmac_algo, key, keylen, text, textlen, temp) != len)
11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
11088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (memcmp(digest, temp, digestlen) != 0)
11108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
11118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
11128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
11138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
11148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * computes the requested HMAC using a key struct (which may be modified if
11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the keylen exceeds the HMAC block len).
11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_compute_hmac(uint16_t hmac_algo, sctp_key_t *key, uint8_t *text,
11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t textlen, uint8_t *digest)
11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t digestlen;
11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t blocklen;
11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hash_context_t ctx;
11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sanity check */
11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((key == NULL) || (text == NULL) || (textlen == 0) ||
11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (digest == NULL)) {
11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* can't do HMAC with empty key or text or digest store */
11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* validate the hmac algo and get the digest length */
11368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digestlen = sctp_get_hmac_digest_len(hmac_algo);
11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (digestlen == 0)
11388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* hash the key if it is longer than the hash block size */
11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	blocklen = sctp_get_hmac_block_len(hmac_algo);
11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key->keylen > blocklen) {
11438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_init(hmac_algo, &ctx);
11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_update(hmac_algo, &ctx, key->key, key->keylen);
11458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_final(hmac_algo, &ctx, temp);
11468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* save the hashed key as the new key */
11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		key->keylen = digestlen;
11488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bcopy(temp, key->key, key->keylen);
11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (sctp_hmac(hmac_algo, key->key, key->keylen, text, textlen,
11518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    digest));
11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* mbuf version */
11558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_compute_hmac_m(uint16_t hmac_algo, sctp_key_t *key, struct mbuf *m,
11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t m_offset, uint8_t *digest)
11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
11598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t digestlen;
11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t blocklen;
11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hash_context_t ctx;
11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sanity check */
11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((key == NULL) || (m == NULL) || (digest == NULL)) {
11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* can't do HMAC with empty key or text or digest store */
11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
11688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* validate the hmac algo and get the digest length */
11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digestlen = sctp_get_hmac_digest_len(hmac_algo);
11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (digestlen == 0)
11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
11738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* hash the key if it is longer than the hash block size */
11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	blocklen = sctp_get_hmac_block_len(hmac_algo);
11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (key->keylen > blocklen) {
11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_init(hmac_algo, &ctx);
11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_update(hmac_algo, &ctx, key->key, key->keylen);
11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmac_final(hmac_algo, &ctx, temp);
11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* save the hashed key as the new key */
11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		key->keylen = digestlen;
11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bcopy(temp, key->key, key->keylen);
11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (sctp_hmac_m(hmac_algo, key->key, key->keylen, m, m_offset, digest, 0));
11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_is_supported_hmac(sctp_hmaclist_t *list, uint16_t id)
11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
11918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((list == NULL) || (id == SCTP_AUTH_HMAC_ID_RSVD))
11938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
11948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < list->num_algo; i++)
11968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (list->hmac[i] == id)
11978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
11988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not in the list */
12008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * clear any cached key(s) if they match the given key id on an association.
12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the cached key(s) will be recomputed and re-cached at next use.
12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASSUMES TCB_LOCK is already held
12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_clear_cachedkeys(struct sctp_tcb *stcb, uint16_t keyid)
12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL)
12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keyid == stcb->asoc.authinfo.assoc_keyid) {
12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_key(stcb->asoc.authinfo.assoc_key);
12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.authinfo.assoc_key = NULL;
12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keyid == stcb->asoc.authinfo.recv_keyid) {
12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_key(stcb->asoc.authinfo.recv_key);
12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.authinfo.recv_key = NULL;
12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
12268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * clear any cached key(s) if they match the given key id for all assocs on
12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * an endpoint.
12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASSUMES INP_WLOCK is already held
12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_clear_cachedkeys_ep(struct sctp_inpcb *inp, uint16_t keyid)
12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL)
12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* clear the cached keys on all assocs on this instance */
12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clear_cachedkeys(stcb, keyid);
12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delete a shared key from an association
12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASSUMES TCB_LOCK is already held
12498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_delete_sharedkey(struct sctp_tcb *stcb, uint16_t keyid)
12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL)
12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* is the keyid the assoc active sending key */
12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keyid == stcb->asoc.authinfo.active_keyid)
12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* does the key exist? */
12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid);
12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey == NULL)
12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* are there other refcount holders on the key? */
12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey->refcount > 1)
12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* remove it */
12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_REMOVE(skey, next);
12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_free_sharedkey(skey);	/* frees skey->key as well */
12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* clear any cached keys */
12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clear_cachedkeys(stcb, keyid);
12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deletes a shared key from the endpoint
12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASSUMES INP_WLOCK is already held
12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_delete_sharedkey_ep(struct sctp_inpcb *inp, uint16_t keyid)
12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL)
12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* is the keyid the active sending key on the endpoint */
12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keyid == inp->sctp_ep.default_keyid)
12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* does the key exist? */
12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey = sctp_find_sharedkey(&inp->sctp_ep.shared_keys, keyid);
12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey == NULL)
12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* endpoint keys are not refcounted */
13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* remove it */
13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_REMOVE(skey, next);
13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_free_sharedkey(skey);	/* frees skey->key as well */
13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* clear any cached keys */
13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clear_cachedkeys_ep(inp, keyid);
13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * set the active key on an association
13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASSUMES TCB_LOCK is already held
13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_setactivekey(struct sctp_tcb *stcb, uint16_t keyid)
13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey = NULL;
13208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the key on the assoc */
13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid);
13238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey == NULL) {
13248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* that key doesn't exist */
13258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((skey->deactivated) && (skey->refcount > 1)) {
13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* can't reactivate a deactivated key with other refcounts */
13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* set the (new) active key */
13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.authinfo.active_keyid = keyid;
13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* reset the deactivated flag */
13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey->deactivated = 0;
13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * set the active key on an endpoint
13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASSUMES INP_WLOCK is already held
13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_setactivekey_ep(struct sctp_inpcb *inp, uint16_t keyid)
13468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the key */
13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey = sctp_find_sharedkey(&inp->sctp_ep.shared_keys, keyid);
13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey == NULL) {
13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* that key doesn't exist */
13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp->sctp_ep.default_keyid = keyid;
13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
13578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deactivates a shared key from the association
13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASSUMES INP_WLOCK is already held
13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
13638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_deact_sharedkey(struct sctp_tcb *stcb, uint16_t keyid)
13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL)
13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* is the keyid the assoc active sending key */
13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keyid == stcb->asoc.authinfo.active_keyid)
13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* does the key exist? */
13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid);
13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey == NULL)
13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* are there other refcount holders on the key? */
13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey->refcount == 1) {
13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no other users, send a notification for this key */
13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_ulp_notify(SCTP_NOTIFY_AUTH_FREE_KEY, stcb, keyid, 0,
13848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SO_LOCKED);
13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* mark the key as deactivated */
13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey->deactivated = 1;
13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
13918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
13948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deactivates a shared key from the endpoint
13958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASSUMES INP_WLOCK is already held
13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_deact_sharedkey_ep(struct sctp_inpcb *inp, uint16_t keyid)
13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL)
14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* is the keyid the active sending key on the endpoint */
14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (keyid == inp->sctp_ep.default_keyid)
14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* does the key exist? */
14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skey = sctp_find_sharedkey(&inp->sctp_ep.shared_keys, keyid);
14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (skey == NULL)
14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* endpoint keys are not refcounted */
14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* remove it */
14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_REMOVE(skey, next);
14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_free_sharedkey(skey);	/* frees skey->key as well */
14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
14218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * get local authentication parameters from cookie (from INIT-ACK)
14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t offset, uint32_t length)
14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr *phdr, tmp_param;
14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t plen, ptype;
14328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t random_store[SCTP_PARAM_BUFFER_SIZE];
14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_auth_random *p_random = NULL;
14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t random_len = 0;
14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t hmacs_store[SCTP_PARAM_BUFFER_SIZE];
14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_auth_hmac_algo *hmacs = NULL;
14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t hmacs_len = 0;
14388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t chunks_store[SCTP_PARAM_BUFFER_SIZE];
14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_auth_chunk_list *chunks = NULL;
14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t num_chunks = 0;
14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *new_key;
14428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t keylen;
14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* convert to upper bound */
14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	length += offset;
14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	phdr = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param);
14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (phdr != NULL) {
14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ptype = ntohs(phdr->param_type);
14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		plen = ntohs(phdr->param_length);
14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((plen == 0) || (offset + plen > length))
14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ptype == SCTP_RANDOM) {
14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (plen > sizeof(random_store))
14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr = sctp_get_next_param(m, offset,
14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sctp_paramhdr *)random_store, min(plen, sizeof(random_store)));
14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (phdr == NULL)
14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* save the random and length for the key */
14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			p_random = (struct sctp_auth_random *)phdr;
14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			random_len = plen - sizeof(*p_random);
14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (ptype == SCTP_HMAC_LIST) {
14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int num_hmacs;
14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int i;
14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (plen > sizeof(hmacs_store))
14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr = sctp_get_next_param(m, offset,
14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sctp_paramhdr *)hmacs_store, min(plen,sizeof(hmacs_store)));
14748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (phdr == NULL)
14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* save the hmacs list and num for the key */
14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hmacs = (struct sctp_auth_hmac_algo *)phdr;
14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hmacs_len = plen - sizeof(*hmacs);
14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			num_hmacs = hmacs_len / sizeof(hmacs->hmac_ids[0]);
14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.local_hmacs != NULL)
14818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_hmaclist(stcb->asoc.local_hmacs);
14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.local_hmacs = sctp_alloc_hmaclist(num_hmacs);
14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.local_hmacs != NULL) {
14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				for (i = 0; i < num_hmacs; i++) {
14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(void)sctp_auth_add_hmacid(stcb->asoc.local_hmacs,
14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    ntohs(hmacs->hmac_ids[i]));
14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (ptype == SCTP_CHUNK_LIST) {
14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int i;
14918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (plen > sizeof(chunks_store))
14938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr = sctp_get_next_param(m, offset,
14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sctp_paramhdr *)chunks_store, min(plen,sizeof(chunks_store)));
14968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (phdr == NULL)
14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chunks = (struct sctp_auth_chunk_list *)phdr;
14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			num_chunks = plen - sizeof(*chunks);
15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* save chunks list and num for the key */
15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.local_auth_chunks != NULL)
15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_clear_chunklist(stcb->asoc.local_auth_chunks);
15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.local_auth_chunks = sctp_alloc_chunklist();
15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (i = 0; i < num_chunks; i++) {
15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_auth_add_chunk(chunks->chunk_types[i],
15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.local_auth_chunks);
15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get next parameter */
15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += SCTP_SIZE32(plen);
15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (offset + sizeof(struct sctp_paramhdr) > length)
15138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		phdr = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (uint8_t *)&tmp_param);
15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* concatenate the full random key */
15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len;
15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (chunks != NULL) {
15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		keylen += sizeof(*chunks) + num_chunks;
15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key = sctp_alloc_key(keylen);
15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_key != NULL) {
15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    /* copy in the RANDOM */
15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    if (p_random != NULL) {
15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		keylen = sizeof(*p_random) + random_len;
15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bcopy(p_random, new_key->key, keylen);
15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    }
15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    /* append in the AUTH chunks */
15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    if (chunks != NULL) {
15318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bcopy(chunks, new_key->key + keylen,
15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		      sizeof(*chunks) + num_chunks);
15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		keylen += sizeof(*chunks) + num_chunks;
15348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    }
15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    /* append in the HMACs */
15368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    if (hmacs != NULL) {
15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bcopy(hmacs, new_key->key + keylen,
15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		      sizeof(*hmacs) + hmacs_len);
15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    }
15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.authinfo.random != NULL)
1542fb3816eaffe5878bb1286adb120fd160da178a05t		sctp_free_key(stcb->asoc.authinfo.random);
15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.authinfo.random = new_key;
15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.authinfo.random_len = random_len;
15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.assoc_keyid);
15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.recv_keyid);
15478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* negotiate what HMAC to use for the peer */
15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    stcb->asoc.local_hmacs);
15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* copy defaults from the endpoint */
15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* FIX ME: put in cookie? */
15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.authinfo.active_keyid = stcb->sctp_ep->sctp_ep.default_keyid;
15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* copy out the shared key list (by reference) from the endpoint */
15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_copy_skeylist(&stcb->sctp_ep->sctp_ep.shared_keys,
15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 &stcb->asoc.shared_keys);
15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * compute and fill in the HMAC digest for a packet
15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fill_hmac_digest_m(struct mbuf *m, uint32_t auth_offset,
15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_auth_chunk *auth, struct sctp_tcb *stcb, uint16_t keyid)
15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t digestlen;
15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *key;
15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb == NULL) || (auth == NULL))
15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* zero the digest + chunk padding */
15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digestlen = sctp_get_hmac_digest_len(stcb->asoc.peer_hmac_id);
15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(auth->hmac, SCTP_SIZE32(digestlen));
15778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* is the desired key cached? */
15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((keyid != stcb->asoc.authinfo.assoc_keyid) ||
15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.authinfo.assoc_key == NULL)) {
15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.authinfo.assoc_key != NULL) {
15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* free the old cached key */
15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_key(stcb->asoc.authinfo.assoc_key);
15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid);
15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* the only way skey is NULL is if null key id 0 is used */
15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (skey != NULL)
15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			key = skey->key;
15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			key = NULL;
15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* compute a new assoc key and cache it */
15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.authinfo.assoc_key =
15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sctp_compute_hashkey(stcb->asoc.authinfo.random,
15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 stcb->asoc.authinfo.peer_random, key);
15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.authinfo.assoc_keyid = keyid;
15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1, "caching key id %u\n",
15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.authinfo.assoc_keyid);
15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG
15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_AUTH_DEBUG)
16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_print_key(stcb->asoc.authinfo.assoc_key,
16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       "Assoc Key");
16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* set in the active key id */
16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth->shared_key_id = htons(keyid);
16078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* compute and fill in the digest */
16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_compute_hmac_m(stcb->asoc.peer_hmac_id, stcb->asoc.authinfo.assoc_key,
16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  m, auth_offset, auth->hmac);
16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_bzero_m(struct mbuf *m, uint32_t m_offset, uint32_t size)
16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_tmp;
16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t *data;
16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sanity check */
16218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m == NULL)
16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the correct starting mbuf and offset (get start position) */
16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_tmp = m;
16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while ((m_tmp != NULL) && (m_offset >= (uint32_t) SCTP_BUF_LEN(m_tmp))) {
16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_offset -= SCTP_BUF_LEN(m_tmp);
16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_tmp = SCTP_BUF_NEXT(m_tmp);
16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now use the rest of the mbuf chain */
16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while ((m_tmp != NULL) && (size > 0)) {
16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		data = mtod(m_tmp, uint8_t *) + m_offset;
16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (size > (uint32_t) SCTP_BUF_LEN(m_tmp)) {
16348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bzero(data, SCTP_BUF_LEN(m_tmp));
16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size -= SCTP_BUF_LEN(m_tmp);
16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bzero(data, size);
16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = 0;
16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clear the offset since it's only for the first mbuf */
16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_offset = 0;
16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_tmp = SCTP_BUF_NEXT(m_tmp);
16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process the incoming Authentication chunk
16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * return codes:
16498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *   -1 on any authentication error
16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    0 on authentication verification
16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
16538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth,
16548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf *m, uint32_t offset)
16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t chunklen;
16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t shared_key_id;
16588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t hmac_id;
16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sharedkey_t *skey;
16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t digestlen;
16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t digest[SCTP_AUTH_DIGEST_LEN_MAX];
16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t computed_digest[SCTP_AUTH_DIGEST_LEN_MAX];
16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* auth is checked for NULL by caller */
16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chunklen = ntohs(auth->ch.chunk_length);
16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (chunklen < sizeof(*auth)) {
16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_recvauthfailed);
16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_STAT_INCR(sctps_recvauth);
16718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get the auth params */
16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	shared_key_id = ntohs(auth->shared_key_id);
16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	hmac_id = ntohs(auth->hmac_id);
16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_AUTH1,
16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		"SCTP AUTH Chunk: shared key %u, HMAC id %u\n",
16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		shared_key_id, hmac_id);
16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* is the indicated HMAC supported? */
16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!sctp_auth_is_supported_hmac(stcb->asoc.local_hmacs, hmac_id)) {
16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct mbuf *m_err;
16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_auth_invalid_hmac *err;
16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_recvivalhmacid);
16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1,
16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"SCTP Auth: unsupported HMAC id %u\n",
16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hmac_id);
16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * report this in an Error Chunk: Unsupported HMAC
16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Identifier
16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
169268beeca578347438d9c434680197647ed551935ft		m_err = sctp_get_mbuf_for_msg(sizeof(*err), 0, M_NOWAIT,
16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					      1, MT_HEADER);
16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (m_err != NULL) {
16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* pre-reserve some space */
16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_RESV_UF(m_err, sizeof(struct sctp_chunkhdr));
16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* fill in the error */
16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			err = mtod(m_err, struct sctp_auth_invalid_hmac *);
16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bzero(err, sizeof(*err));
17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			err->ph.param_type = htons(SCTP_CAUSE_UNSUPPORTED_HMACID);
17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			err->ph.param_length = htons(sizeof(*err));
17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			err->hmac_id = ntohs(hmac_id);
17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(m_err) = sizeof(*err);
17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* queue it */
17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_queue_op_err(stcb, m_err);
17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get the indicated shared key, if available */
17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->asoc.authinfo.recv_key == NULL) ||
17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.authinfo.recv_keyid != shared_key_id)) {
17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* find the shared key on the assoc first */
17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		skey = sctp_find_sharedkey(&stcb->asoc.shared_keys,
17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   shared_key_id);
17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* if the shared key isn't found, discard the chunk */
17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (skey == NULL) {
17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_recvivalkeyid);
17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_AUTH1,
17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				"SCTP Auth: unknown key id %u\n",
17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_key_id);
17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (-1);
17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* generate a notification if this is a new key id */
17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.authinfo.recv_keyid != shared_key_id)
17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * sctp_ulp_notify(SCTP_NOTIFY_AUTH_NEW_KEY, stcb,
17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * shared_key_id, (void
17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * *)stcb->asoc.authinfo.recv_keyid);
17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
173008f3696ad42fc22082922592e23297cfaf790dcctuexen			sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY,
17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    shared_key_id, stcb->asoc.authinfo.recv_keyid,
17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_SO_NOT_LOCKED);
17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* compute a new recv assoc key and cache it */
17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.authinfo.recv_key != NULL)
17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_key(stcb->asoc.authinfo.recv_key);
17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.authinfo.recv_key =
17378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sctp_compute_hashkey(stcb->asoc.authinfo.random,
17388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    stcb->asoc.authinfo.peer_random, skey->key);
17398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.authinfo.recv_keyid = shared_key_id;
17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG
17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_AUTH_DEBUG)
17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_print_key(stcb->asoc.authinfo.recv_key, "Recv Key");
17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* validate the digest length */
17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digestlen = sctp_get_hmac_digest_len(hmac_id);
17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (chunklen < (sizeof(*auth) + digestlen)) {
17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* invalid digest length */
17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_recvauthfailed);
17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1,
17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"SCTP Auth: chunk too short for HMAC\n");
17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* save a copy of the digest, zero the pseudo header, and validate */
17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bcopy(auth->hmac, digest, digestlen);
17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_bzero_m(m, offset + sizeof(*auth), SCTP_SIZE32(digestlen));
17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_compute_hmac_m(hmac_id, stcb->asoc.authinfo.recv_key,
17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    m, offset, computed_digest);
17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* compare the computed digest with the one in the AUTH chunk */
17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (memcmp(digest, computed_digest, digestlen) != 0) {
17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_recvauthfailed);
17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1,
17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"SCTP Auth: HMAC digest check failed\n");
17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Generate NOTIFICATION
17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   uint16_t keyid, uint16_t alt_keyid, int so_locked
17768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_UNUSED
17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen)
17808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
17818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
17828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_authkey_event *auth;
17838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb == NULL) ||
17868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	   (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
17878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	   (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
17888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	   (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)
17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		) {
17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* If the socket is gone we are out of here */
17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_AUTHEVNT))
17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
17978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_authkey_event),
179968beeca578347438d9c434680197647ed551935ft					  0, M_NOWAIT, 1, MT_HEADER);
18008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL)
18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth = mtod(m_notify, struct sctp_authkey_event *);
1806f496fe99adbad377f85add3a45e17f21a4702b41t	memset(auth, 0, sizeof(struct sctp_authkey_event));
18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth->auth_type = SCTP_AUTHENTICATION_EVENT;
18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth->auth_flags = 0;
18098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth->auth_length = sizeof(*auth);
18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth->auth_keynumber = keyid;
18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth->auth_altkeynumber = alt_keyid;
18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth->auth_indication = indication;
18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	auth->auth_assoc_id = sctp_get_associd(stcb);
18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = sizeof(*auth);
18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
18200ac02f34d6041cd0018437596a5a9a94685e6919tuexen	    0, 0, stcb->asoc.context, 0, 0, 0, m_notify);
18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = SCTP_BUF_LEN(m_notify);
18288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not that we need this */
18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->tail_mbuf = m_notify;
18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb, control,
18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
18368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * validates the AUTHentication related parameters in an INIT/INIT-ACK
18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Note: currently only used for INIT as INIT-ACK is handled inline
18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with sctp_load_addresses_from_init()
18398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr *phdr, parm_buf;
18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t ptype, plen;
18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int peer_supports_asconf = 0;
18468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int peer_supports_auth = 0;
18478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int got_random = 0, got_hmacs = 0, got_chklist = 0;
1848b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	uint8_t saw_asconf = 0;
1849b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	uint8_t saw_asconf_ack = 0;
18508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* go through each of the params. */
18528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (phdr) {
18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ptype = ntohs(phdr->param_type);
18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		plen = ntohs(phdr->param_length);
18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (offset + plen > limit) {
18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (plen < sizeof(struct sctp_paramhdr)) {
18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* A supported extension chunk */
18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_supported_chunk_types_param *pr_supported;
18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint8_t local_store[SCTP_PARAM_BUFFER_SIZE];
18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int num_ent, i;
18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr = sctp_get_next_param(m, offset,
18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sctp_paramhdr *)&local_store, min(plen,sizeof(local_store)));
18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (phdr == NULL) {
18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (-1);
18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			num_ent = plen - sizeof(struct sctp_paramhdr);
18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (i = 0; i < num_ent; i++) {
18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				switch (pr_supported->chunk_types[i]) {
18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case SCTP_ASCONF:
18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case SCTP_ASCONF_ACK:
18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					peer_supports_asconf = 1;
18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* one we don't care about */
18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (ptype == SCTP_RANDOM) {
18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			got_random = 1;
18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* enforce the random length */
18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (plen != (sizeof(struct sctp_auth_random) +
18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     SCTP_AUTH_RANDOM_SIZE_REQUIRED)) {
18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_AUTH1,
18938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					"SCTP: invalid RANDOM len\n");
18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (-1);
18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (ptype == SCTP_HMAC_LIST) {
18978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint8_t store[SCTP_PARAM_BUFFER_SIZE];
18988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_auth_hmac_algo *hmacs;
18998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int num_hmacs;
19008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (plen > sizeof(store))
19028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr = sctp_get_next_param(m, offset,
19048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sctp_paramhdr *)store, min(plen,sizeof(store)));
19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (phdr == NULL)
19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (-1);
19078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hmacs = (struct sctp_auth_hmac_algo *)phdr;
19088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			num_hmacs = (plen - sizeof(*hmacs)) /
19098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sizeof(hmacs->hmac_ids[0]);
19108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* validate the hmac list */
19118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_verify_hmac_param(hmacs, num_hmacs)) {
19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_AUTH1,
19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					"SCTP: invalid HMAC param\n");
19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (-1);
19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			got_hmacs = 1;
19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (ptype == SCTP_CHUNK_LIST) {
19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int i, num_chunks;
19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint8_t chunks_store[SCTP_SMALL_CHUNK_STORE];
19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* did the peer send a non-empty chunk list? */
19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_auth_chunk_list *chunks = NULL;
19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr = sctp_get_next_param(m, offset,
19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   (struct sctp_paramhdr *)chunks_store,
19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   min(plen,sizeof(chunks_store)));
19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (phdr == NULL)
19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (-1);
19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*-
19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Flip through the list and mark that the
19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * peer supports asconf/asconf_ack.
19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chunks = (struct sctp_auth_chunk_list *)phdr;
19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			num_chunks = plen - sizeof(*chunks);
19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (i = 0; i < num_chunks; i++) {
19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* record asconf/asconf-ack if listed */
19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (chunks->chunk_types[i] == SCTP_ASCONF)
19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					saw_asconf = 1;
19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (chunks->chunk_types[i] == SCTP_ASCONF_ACK)
19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					saw_asconf_ack = 1;
19408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (num_chunks)
19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				got_chklist = 1;
19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += SCTP_SIZE32(plen);
19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (offset >= limit) {
19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
19498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		phdr = sctp_get_next_param(m, offset, &parm_buf,
19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(parm_buf));
19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* validate authentication required parameters */
19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (got_random && got_hmacs) {
19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		peer_supports_auth = 1;
19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		peer_supports_auth = 0;
19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!peer_supports_auth && got_chklist) {
19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1,
19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"SCTP: peer sent chunk list w/o AUTH\n");
19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
196488673064e2b5436421cf5ca651d21701dbd98dfet	if (peer_supports_asconf && !peer_supports_auth) {
19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_AUTH1,
19668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"SCTP: peer supports ASCONF but not AUTH\n");
19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if ((peer_supports_asconf) && (peer_supports_auth) &&
19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   ((saw_asconf == 0) || (saw_asconf_ack == 0))) {
19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-2);
19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
19768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_initialize_auth_params(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t chunks_len = 0;
19798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t hmacs_len = 0;
19808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t random_len = SCTP_AUTH_RANDOM_SIZE_DEFAULT;
19818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *new_key;
19828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t keylen;
19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* initialize hmac list from endpoint */
19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.local_hmacs = sctp_copy_hmaclist(inp->sctp_ep.local_hmacs);
19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.local_hmacs != NULL) {
19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hmacs_len = stcb->asoc.local_hmacs->num_algo *
19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(stcb->asoc.local_hmacs->hmac[0]);
19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* initialize auth chunks list from endpoint */
19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.local_auth_chunks =
19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks);
19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.local_auth_chunks != NULL) {
19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i;
19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < 256; i++) {
19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.local_auth_chunks->chunks[i])
19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chunks_len++;
19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* copy defaults from the endpoint */
20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.authinfo.active_keyid = inp->sctp_ep.default_keyid;
20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* copy out the shared key list (by reference) from the endpoint */
20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys,
20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 &stcb->asoc.shared_keys);
20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now set the concatenated key (random + chunks + hmacs) */
20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* key includes parameter headers */
20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = (3 * sizeof(struct sctp_paramhdr)) + random_len + chunks_len +
20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    hmacs_len;
20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_key = sctp_alloc_key(keylen);
20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_key != NULL) {
20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paramhdr *ph;
20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int plen;
20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* generate and copy in the RANDOM */
20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph = (struct sctp_paramhdr *)new_key->key;
20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph->param_type = htons(SCTP_RANDOM);
20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		plen = sizeof(*ph) + random_len;
20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph->param_length = htons(plen);
20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_READ_RANDOM(new_key->key + sizeof(*ph), random_len);
20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		keylen = plen;
20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* append in the AUTH chunks */
20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* NOTE: currently we always have chunks to list */
20258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph = (struct sctp_paramhdr *)(new_key->key + keylen);
20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph->param_type = htons(SCTP_CHUNK_LIST);
20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		plen = sizeof(*ph) + chunks_len;
20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph->param_length = htons(plen);
20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		keylen += sizeof(*ph);
20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.local_auth_chunks) {
20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int i;
20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (i = 0; i < 256; i++) {
20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb->asoc.local_auth_chunks->chunks[i])
20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_key->key[keylen++] = i;
20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* append in the HMACs */
20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph = (struct sctp_paramhdr *)(new_key->key + keylen);
20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph->param_type = htons(SCTP_HMAC_LIST);
20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		plen = sizeof(*ph) + hmacs_len;
20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph->param_length = htons(plen);
20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		keylen += sizeof(*ph);
20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_serialize_hmaclist(stcb->asoc.local_hmacs,
20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_key->key + keylen);
20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.authinfo.random != NULL)
20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_free_key(stcb->asoc.authinfo.random);
20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.authinfo.random = new_key;
20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.authinfo.random_len = random_len;
20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_HMAC_TEST
20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * HMAC and key concatenation tests
20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_print_digest(uint8_t *digest, uint32_t digestlen, const char *str)
20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
206347a306d634abf33223ef347472c4b1cd441d139ftuexen	SCTP_PRINTF("\n%s: 0x", str);
20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (digest == NULL)
20658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < digestlen; i++)
206847a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("%02x", digest[i]);
20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_test_hmac(const char *str, uint16_t hmac_id, uint8_t *key,
20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t keylen, uint8_t *text, uint32_t textlen,
20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint8_t *digest, uint32_t digestlen)
20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t computed_digest[SCTP_AUTH_DIGEST_LEN_MAX];
20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
207847a306d634abf33223ef347472c4b1cd441d139ftuexen	SCTP_PRINTF("\n%s:", str);
20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_hmac(hmac_id, key, keylen, text, textlen, computed_digest);
20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_print_digest(digest, digestlen, "Expected digest");
20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_print_digest(computed_digest, digestlen, "Computed digest");
20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (memcmp(digest, computed_digest, digestlen) != 0) {
208347a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\nFAILED");
20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
208647a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\nPASSED");
20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * RFC 2202: HMAC-SHA1 test cases
20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_test_hmac_sha1(void)
20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t *digest;
20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t key[128];
21008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t keylen;
21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t text[128];
21028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t textlen;
21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t digestlen = 20;
21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int failed = 0;
21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * test_case =     1
21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key =           0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key_len =       20
21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data =          "Hi There"
21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data_len =      8
21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * digest =        0xb617318655057264e28bc0b6fb378c8ef146be00
21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = 20;
21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(key, 0x0b, keylen);
21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	textlen = 8;
21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strcpy(text, "Hi There");
21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digest = "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00";
21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_hmac("SHA1 test case 1", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    text, textlen, digest, digestlen) < 0)
21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * test_case =     2
21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key =           "Jefe"
21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key_len =       4
21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data =          "what do ya want for nothing?"
21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data_len =      28
21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * digest =        0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = 4;
21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strcpy(key, "Jefe");
21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	textlen = 28;
21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strcpy(text, "what do ya want for nothing?");
21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digest = "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79";
21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_hmac("SHA1 test case 2", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    text, textlen, digest, digestlen) < 0)
21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * test_case =     3
21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key =           0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
21438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key_len =       20
21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data =          0xdd repeated 50 times
21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data_len =      50
21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * digest =        0x125d7342b9ac11cd91a39af48aa17b4f63f175d3
21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = 20;
21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(key, 0xaa, keylen);
21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	textlen = 50;
21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(text, 0xdd, textlen);
21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digest = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3";
21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_hmac("SHA1 test case 3", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    text, textlen, digest, digestlen) < 0)
21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * test_case =     4
21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key =           0x0102030405060708090a0b0c0d0e0f10111213141516171819
21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key_len =       25
21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data =          0xcd repeated 50 times
21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data_len =      50
21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * digest =        0x4c9007f4026250c6bc8414f9bf50c86c2d7235da
21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = 25;
21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memcpy(key, "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", keylen);
21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	textlen = 50;
21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(text, 0xcd, textlen);
21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digest = "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda";
21708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_hmac("SHA1 test case 4", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    text, textlen, digest, digestlen) < 0)
21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
21758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * test_case =     5
21768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key =           0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
21778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key_len =       20
21788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data =          "Test With Truncation"
21798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data_len =      20
21808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * digest =        0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * digest-96 =     0x4c1a03424b55e07fe7f27be1
21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = 20;
21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(key, 0x0c, keylen);
21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	textlen = 20;
21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strcpy(text, "Test With Truncation");
21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digest = "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04";
21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_hmac("SHA1 test case 5", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    text, textlen, digest, digestlen) < 0)
21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * test_case =     6
21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key =           0xaa repeated 80 times
21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key_len =       80
21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data =          "Test Using Larger Than Block-Size Key - Hash Key First"
21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data_len =      54
21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * digest =        0xaa4ae5e15272d00e95705637ce8a3b55ed402112
21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = 80;
22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(key, 0xaa, keylen);
22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	textlen = 54;
22038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strcpy(text, "Test Using Larger Than Block-Size Key - Hash Key First");
22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digest = "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12";
22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_hmac("SHA1 test case 6", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    text, textlen, digest, digestlen) < 0)
22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * test_case =     7
22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key =           0xaa repeated 80 times
22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * key_len =       80
22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data =          "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * data_len =      73
22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * digest =        0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	keylen = 80;
22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(key, 0xaa, keylen);
22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	textlen = 73;
22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strcpy(text, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data");
22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	digest = "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91";
22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_hmac("SHA1 test case 7", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    text, textlen, digest, digestlen) < 0)
22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* done with all tests */
22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (failed)
222847a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\nSHA1 test results: %d cases failed", failed);
22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
223047a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\nSHA1 test results: all test cases passed");
22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * test assoc key concatenation
22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_test_key_concatenation(sctp_key_t *key1, sctp_key_t *key2,
22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    sctp_key_t *expected_key)
22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *key;
22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int ret_val;
22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_show_key(key1, "\nkey1");
22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_show_key(key2, "\nkey2");
22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key = sctp_compute_hashkey(key1, key2, NULL);
22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_show_key(expected_key, "\nExpected");
22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_show_key(key, "\nComputed");
22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (memcmp(key, expected_key, expected_key->keylen) != 0) {
224947a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\nFAILED");
22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret_val = -1;
22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
225247a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\nPASSED");
22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret_val = 0;
22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_free_key(key1);
22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_free_key(key2);
22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_free_key(expected_key);
22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_free_key(key);
22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (ret_val);
22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_test_authkey(void)
22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_key_t *key1, *key2, *expected_key;
22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int failed = 0;
22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* test case 1 */
22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key1 = sctp_set_key("\x01\x01\x01\x01", 4);
22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key2 = sctp_set_key("\x01\x02\x03\x04", 4);
22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	expected_key = sctp_set_key("\x01\x01\x01\x01\x01\x02\x03\x04", 8);
22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
22748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* test case 2 */
22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key1 = sctp_set_key("\x00\x00\x00\x01", 4);
22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key2 = sctp_set_key("\x02", 1);
22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	expected_key = sctp_set_key("\x00\x00\x00\x01\x02", 5);
22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* test case 3 */
22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key1 = sctp_set_key("\x01", 1);
22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key2 = sctp_set_key("\x00\x00\x00\x02", 4);
22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	expected_key = sctp_set_key("\x01\x00\x00\x00\x02", 5);
22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* test case 4 */
22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key1 = sctp_set_key("\x00\x00\x00\x01", 4);
22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key2 = sctp_set_key("\x01", 1);
22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	expected_key = sctp_set_key("\x01\x00\x00\x00\x01", 5);
22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* test case 5 */
22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key1 = sctp_set_key("\x01", 1);
22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key2 = sctp_set_key("\x00\x00\x00\x01", 4);
23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	expected_key = sctp_set_key("\x01\x00\x00\x00\x01", 5);
23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* test case 6 */
23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key1 = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07", 11);
23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key2 = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x08", 11);
23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	expected_key = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x08", 22);
23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* test case 7 */
23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key1 = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x08", 11);
23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	key2 = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07", 11);
23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	expected_key = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x08", 22);
23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		failed++;
23178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* done with all tests */
23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (failed)
232047a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\nKey concatenation test results: %d cases failed", failed);
23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
232247a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\nKey concatenation test results: all test cases passed");
23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(STANDALONE_HMAC_TEST)
23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenmain(void)
23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
23308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_test_hmac_sha1();
23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_test_authkey();
23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* STANDALONE_HMAC_TEST */
23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_HMAC_TEST */
2337