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