LCOV - code coverage report
Current view: top level - netwerk/sctp/src/netinet - sctp_auth.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 888 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 64 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
       3             :  * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
       4             :  * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are met:
       8             :  *
       9             :  * a) Redistributions of source code must retain the above copyright notice,
      10             :  *    this list of conditions and the following disclaimer.
      11             :  *
      12             :  * b) Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in
      14             :  *    the documentation and/or other materials provided with the distribution.
      15             :  *
      16             :  * c) Neither the name of Cisco Systems, Inc. nor the names of its
      17             :  *    contributors may be used to endorse or promote products derived
      18             :  *    from this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
      22             :  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      24             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      30             :  * THE POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : #ifdef __FreeBSD__
      34             : #include <sys/cdefs.h>
      35             : __FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 271673 2014-09-16 14:20:33Z tuexen $");
      36             : #endif
      37             : 
      38             : #include <netinet/sctp_os.h>
      39             : #include <netinet/sctp.h>
      40             : #include <netinet/sctp_header.h>
      41             : #include <netinet/sctp_pcb.h>
      42             : #include <netinet/sctp_var.h>
      43             : #include <netinet/sctp_sysctl.h>
      44             : #include <netinet/sctputil.h>
      45             : #include <netinet/sctp_indata.h>
      46             : #include <netinet/sctp_output.h>
      47             : #include <netinet/sctp_auth.h>
      48             : 
      49             : #ifdef SCTP_DEBUG
      50             : #define SCTP_AUTH_DEBUG         (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_AUTH1)
      51             : #define SCTP_AUTH_DEBUG2        (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_AUTH2)
      52             : #endif /* SCTP_DEBUG */
      53             : 
      54             : 
      55             : void
      56           0 : sctp_clear_chunklist(sctp_auth_chklist_t *chklist)
      57             : {
      58           0 :         bzero(chklist, sizeof(*chklist));
      59             :         /* chklist->num_chunks = 0; */
      60           0 : }
      61             : 
      62             : sctp_auth_chklist_t *
      63           0 : sctp_alloc_chunklist(void)
      64             : {
      65             :         sctp_auth_chklist_t *chklist;
      66             : 
      67           0 :         SCTP_MALLOC(chklist, sctp_auth_chklist_t *, sizeof(*chklist),
      68             :                     SCTP_M_AUTH_CL);
      69           0 :         if (chklist == NULL) {
      70           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1, "sctp_alloc_chunklist: failed to get memory!\n");
      71             :         } else {
      72           0 :                 sctp_clear_chunklist(chklist);
      73             :         }
      74           0 :         return (chklist);
      75             : }
      76             : 
      77             : void
      78           0 : sctp_free_chunklist(sctp_auth_chklist_t *list)
      79             : {
      80           0 :         if (list != NULL)
      81           0 :                 SCTP_FREE(list, SCTP_M_AUTH_CL);
      82           0 : }
      83             : 
      84             : sctp_auth_chklist_t *
      85           0 : sctp_copy_chunklist(sctp_auth_chklist_t *list)
      86             : {
      87             :         sctp_auth_chklist_t *new_list;
      88             : 
      89           0 :         if (list == NULL)
      90           0 :                 return (NULL);
      91             : 
      92             :         /* get a new list */
      93           0 :         new_list = sctp_alloc_chunklist();
      94           0 :         if (new_list == NULL)
      95           0 :                 return (NULL);
      96             :         /* copy it */
      97           0 :         bcopy(list, new_list, sizeof(*new_list));
      98             : 
      99           0 :         return (new_list);
     100             : }
     101             : 
     102             : 
     103             : /*
     104             :  * add a chunk to the required chunks list
     105             :  */
     106             : int
     107           0 : sctp_auth_add_chunk(uint8_t chunk, sctp_auth_chklist_t *list)
     108             : {
     109           0 :         if (list == NULL)
     110           0 :                 return (-1);
     111             : 
     112             :         /* is chunk restricted? */
     113           0 :         if ((chunk == SCTP_INITIATION) ||
     114           0 :             (chunk == SCTP_INITIATION_ACK) ||
     115           0 :             (chunk == SCTP_SHUTDOWN_COMPLETE) ||
     116             :             (chunk == SCTP_AUTHENTICATION)) {
     117           0 :                 return (-1);
     118             :         }
     119           0 :         if (list->chunks[chunk] == 0) {
     120           0 :                 list->chunks[chunk] = 1;
     121           0 :                 list->num_chunks++;
     122           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1,
     123             :                         "SCTP: added chunk %u (0x%02x) to Auth list\n",
     124             :                         chunk, chunk);
     125             :         }
     126           0 :         return (0);
     127             : }
     128             : 
     129             : /*
     130             :  * delete a chunk from the required chunks list
     131             :  */
     132             : int
     133           0 : sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t *list)
     134             : {
     135           0 :         if (list == NULL)
     136           0 :                 return (-1);
     137             : 
     138           0 :         if (list->chunks[chunk] == 1) {
     139           0 :                 list->chunks[chunk] = 0;
     140           0 :                 list->num_chunks--;
     141           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1,
     142             :                         "SCTP: deleted chunk %u (0x%02x) from Auth list\n",
     143             :                         chunk, chunk);
     144             :         }
     145           0 :         return (0);
     146             : }
     147             : 
     148             : size_t
     149           0 : sctp_auth_get_chklist_size(const sctp_auth_chklist_t *list)
     150             : {
     151           0 :         if (list == NULL)
     152           0 :                 return (0);
     153             :         else
     154           0 :                 return (list->num_chunks);
     155             : }
     156             : 
     157             : /*
     158             :  * return the current number and list of required chunks caller must
     159             :  * guarantee ptr has space for up to 256 bytes
     160             :  */
     161             : int
     162           0 : sctp_serialize_auth_chunks(const sctp_auth_chklist_t *list, uint8_t *ptr)
     163             : {
     164           0 :         int i, count = 0;
     165             : 
     166           0 :         if (list == NULL)
     167           0 :                 return (0);
     168             : 
     169           0 :         for (i = 0; i < 256; i++) {
     170           0 :                 if (list->chunks[i] != 0) {
     171           0 :                         *ptr++ = i;
     172           0 :                         count++;
     173             :                 }
     174             :         }
     175           0 :         return (count);
     176             : }
     177             : 
     178             : int
     179           0 : sctp_pack_auth_chunks(const sctp_auth_chklist_t *list, uint8_t *ptr)
     180             : {
     181           0 :         int i, size = 0;
     182             : 
     183           0 :         if (list == NULL)
     184           0 :                 return (0);
     185             : 
     186           0 :         if (list->num_chunks <= 32) {
     187             :                 /* just list them, one byte each */
     188           0 :                 for (i = 0; i < 256; i++) {
     189           0 :                         if (list->chunks[i] != 0) {
     190           0 :                                 *ptr++ = i;
     191           0 :                                 size++;
     192             :                         }
     193             :                 }
     194             :         } else {
     195             :                 int index, offset;
     196             : 
     197             :                 /* pack into a 32 byte bitfield */
     198           0 :                 for (i = 0; i < 256; i++) {
     199           0 :                         if (list->chunks[i] != 0) {
     200           0 :                                 index = i / 8;
     201           0 :                                 offset = i % 8;
     202           0 :                                 ptr[index] |= (1 << offset);
     203             :                         }
     204             :                 }
     205           0 :                 size = 32;
     206             :         }
     207           0 :         return (size);
     208             : }
     209             : 
     210             : int
     211           0 : sctp_unpack_auth_chunks(const uint8_t *ptr, uint8_t num_chunks,
     212             :     sctp_auth_chklist_t *list)
     213             : {
     214             :         int i;
     215             :         int size;
     216             : 
     217           0 :         if (list == NULL)
     218           0 :                 return (0);
     219             : 
     220           0 :         if (num_chunks <= 32) {
     221             :                 /* just pull them, one byte each */
     222           0 :                 for (i = 0; i < num_chunks; i++) {
     223           0 :                         (void)sctp_auth_add_chunk(*ptr++, list);
     224             :                 }
     225           0 :                 size = num_chunks;
     226             :         } else {
     227             :                 int index, offset;
     228             : 
     229             :                 /* unpack from a 32 byte bitfield */
     230           0 :                 for (index = 0; index < 32; index++) {
     231           0 :                         for (offset = 0; offset < 8; offset++) {
     232           0 :                                 if (ptr[index] & (1 << offset)) {
     233           0 :                                         (void)sctp_auth_add_chunk((index * 8) + offset, list);
     234             :                                 }
     235             :                         }
     236             :                 }
     237           0 :                 size = 32;
     238             :         }
     239           0 :         return (size);
     240             : }
     241             : 
     242             : 
     243             : /*
     244             :  * allocate structure space for a key of length keylen
     245             :  */
     246             : sctp_key_t *
     247           0 : sctp_alloc_key(uint32_t keylen)
     248             : {
     249             :         sctp_key_t *new_key;
     250             : 
     251           0 :         SCTP_MALLOC(new_key, sctp_key_t *, sizeof(*new_key) + keylen,
     252             :                     SCTP_M_AUTH_KY);
     253           0 :         if (new_key == NULL) {
     254             :                 /* out of memory */
     255           0 :                 return (NULL);
     256             :         }
     257           0 :         new_key->keylen = keylen;
     258           0 :         return (new_key);
     259             : }
     260             : 
     261             : void
     262           0 : sctp_free_key(sctp_key_t *key)
     263             : {
     264           0 :         if (key != NULL)
     265           0 :                 SCTP_FREE(key,SCTP_M_AUTH_KY);
     266           0 : }
     267             : 
     268             : void
     269           0 : sctp_print_key(sctp_key_t *key, const char *str)
     270             : {
     271             :         uint32_t i;
     272             : 
     273           0 :         if (key == NULL) {
     274           0 :                 SCTP_PRINTF("%s: [Null key]\n", str);
     275           0 :                 return;
     276             :         }
     277           0 :         SCTP_PRINTF("%s: len %u, ", str, key->keylen);
     278           0 :         if (key->keylen) {
     279           0 :                 for (i = 0; i < key->keylen; i++)
     280           0 :                         SCTP_PRINTF("%02x", key->key[i]);
     281           0 :                 SCTP_PRINTF("\n");
     282             :         } else {
     283           0 :                 SCTP_PRINTF("[Null key]\n");
     284             :         }
     285             : }
     286             : 
     287             : void
     288           0 : sctp_show_key(sctp_key_t *key, const char *str)
     289             : {
     290             :         uint32_t i;
     291             : 
     292           0 :         if (key == NULL) {
     293           0 :                 SCTP_PRINTF("%s: [Null key]\n", str);
     294           0 :                 return;
     295             :         }
     296           0 :         SCTP_PRINTF("%s: len %u, ", str, key->keylen);
     297           0 :         if (key->keylen) {
     298           0 :                 for (i = 0; i < key->keylen; i++)
     299           0 :                         SCTP_PRINTF("%02x", key->key[i]);
     300           0 :                 SCTP_PRINTF("\n");
     301             :         } else {
     302           0 :                 SCTP_PRINTF("[Null key]\n");
     303             :         }
     304             : }
     305             : 
     306             : static uint32_t
     307           0 : sctp_get_keylen(sctp_key_t *key)
     308             : {
     309           0 :         if (key != NULL)
     310           0 :                 return (key->keylen);
     311             :         else
     312           0 :                 return (0);
     313             : }
     314             : 
     315             : /*
     316             :  * generate a new random key of length 'keylen'
     317             :  */
     318             : sctp_key_t *
     319           0 : sctp_generate_random_key(uint32_t keylen)
     320             : {
     321             :         sctp_key_t *new_key;
     322             : 
     323           0 :         new_key = sctp_alloc_key(keylen);
     324           0 :         if (new_key == NULL) {
     325             :                 /* out of memory */
     326           0 :                 return (NULL);
     327             :         }
     328           0 :         SCTP_READ_RANDOM(new_key->key, keylen);
     329           0 :         new_key->keylen = keylen;
     330           0 :         return (new_key);
     331             : }
     332             : 
     333             : sctp_key_t *
     334           0 : sctp_set_key(uint8_t *key, uint32_t keylen)
     335             : {
     336             :         sctp_key_t *new_key;
     337             : 
     338           0 :         new_key = sctp_alloc_key(keylen);
     339           0 :         if (new_key == NULL) {
     340             :                 /* out of memory */
     341           0 :                 return (NULL);
     342             :         }
     343           0 :         bcopy(key, new_key->key, keylen);
     344           0 :         return (new_key);
     345             : }
     346             : 
     347             : /*-
     348             :  * given two keys of variable size, compute which key is "larger/smaller"
     349             :  * returns:  1 if key1 > key2
     350             :  *          -1 if key1 < key2
     351             :  *           0 if key1 = key2
     352             :  */
     353             : static int
     354           0 : sctp_compare_key(sctp_key_t *key1, sctp_key_t *key2)
     355             : {
     356             :         uint32_t maxlen;
     357             :         uint32_t i;
     358             :         uint32_t key1len, key2len;
     359             :         uint8_t *key_1, *key_2;
     360             :         uint8_t val1, val2;
     361             : 
     362             :         /* sanity/length check */
     363           0 :         key1len = sctp_get_keylen(key1);
     364           0 :         key2len = sctp_get_keylen(key2);
     365           0 :         if ((key1len == 0) && (key2len == 0))
     366           0 :                 return (0);
     367           0 :         else if (key1len == 0)
     368           0 :                 return (-1);
     369           0 :         else if (key2len == 0)
     370           0 :                 return (1);
     371             : 
     372           0 :         if (key1len < key2len) {
     373           0 :                 maxlen = key2len;
     374             :         } else {
     375           0 :                 maxlen = key1len;
     376             :         }
     377           0 :         key_1 = key1->key;
     378           0 :         key_2 = key2->key;
     379             :         /* check for numeric equality */
     380           0 :         for (i = 0; i < maxlen; i++) {
     381             :                 /* left-pad with zeros */
     382           0 :                 val1 = (i < (maxlen - key1len)) ? 0 : *(key_1++);
     383           0 :                 val2 = (i < (maxlen - key2len)) ? 0 : *(key_2++);
     384           0 :                 if (val1 > val2) {
     385           0 :                         return (1);
     386           0 :                 } else if (val1 < val2) {
     387           0 :                         return (-1);
     388             :                 }
     389             :         }
     390             :         /* keys are equal value, so check lengths */
     391           0 :         if (key1len == key2len)
     392           0 :                 return (0);
     393           0 :         else if (key1len < key2len)
     394           0 :                 return (-1);
     395             :         else
     396           0 :                 return (1);
     397             : }
     398             : 
     399             : /*
     400             :  * generate the concatenated keying material based on the two keys and the
     401             :  * shared key (if available). draft-ietf-tsvwg-auth specifies the specific
     402             :  * order for concatenation
     403             :  */
     404             : sctp_key_t *
     405           0 : sctp_compute_hashkey(sctp_key_t *key1, sctp_key_t *key2, sctp_key_t *shared)
     406             : {
     407             :         uint32_t keylen;
     408             :         sctp_key_t *new_key;
     409             :         uint8_t *key_ptr;
     410             : 
     411           0 :         keylen = sctp_get_keylen(key1) + sctp_get_keylen(key2) +
     412           0 :             sctp_get_keylen(shared);
     413             : 
     414           0 :         if (keylen > 0) {
     415             :                 /* get space for the new key */
     416           0 :                 new_key = sctp_alloc_key(keylen);
     417           0 :                 if (new_key == NULL) {
     418             :                         /* out of memory */
     419           0 :                         return (NULL);
     420             :                 }
     421           0 :                 new_key->keylen = keylen;
     422           0 :                 key_ptr = new_key->key;
     423             :         } else {
     424             :                 /* all keys empty/null?! */
     425           0 :                 return (NULL);
     426             :         }
     427             : 
     428             :         /* concatenate the keys */
     429           0 :         if (sctp_compare_key(key1, key2) <= 0) {
     430             :                 /* key is shared + key1 + key2 */
     431           0 :                 if (sctp_get_keylen(shared)) {
     432           0 :                         bcopy(shared->key, key_ptr, shared->keylen);
     433           0 :                         key_ptr += shared->keylen;
     434             :                 }
     435           0 :                 if (sctp_get_keylen(key1)) {
     436           0 :                         bcopy(key1->key, key_ptr, key1->keylen);
     437           0 :                         key_ptr += key1->keylen;
     438             :                 }
     439           0 :                 if (sctp_get_keylen(key2)) {
     440           0 :                         bcopy(key2->key, key_ptr, key2->keylen);
     441             :                 }
     442             :         } else {
     443             :                 /* key is shared + key2 + key1 */
     444           0 :                 if (sctp_get_keylen(shared)) {
     445           0 :                         bcopy(shared->key, key_ptr, shared->keylen);
     446           0 :                         key_ptr += shared->keylen;
     447             :                 }
     448           0 :                 if (sctp_get_keylen(key2)) {
     449           0 :                         bcopy(key2->key, key_ptr, key2->keylen);
     450           0 :                         key_ptr += key2->keylen;
     451             :                 }
     452           0 :                 if (sctp_get_keylen(key1)) {
     453           0 :                         bcopy(key1->key, key_ptr, key1->keylen);
     454             :                 }
     455             :         }
     456           0 :         return (new_key);
     457             : }
     458             : 
     459             : 
     460             : sctp_sharedkey_t *
     461           0 : sctp_alloc_sharedkey(void)
     462             : {
     463             :         sctp_sharedkey_t *new_key;
     464             : 
     465           0 :         SCTP_MALLOC(new_key, sctp_sharedkey_t *, sizeof(*new_key),
     466             :                     SCTP_M_AUTH_KY);
     467           0 :         if (new_key == NULL) {
     468             :                 /* out of memory */
     469           0 :                 return (NULL);
     470             :         }
     471           0 :         new_key->keyid = 0;
     472           0 :         new_key->key = NULL;
     473           0 :         new_key->refcount = 1;
     474           0 :         new_key->deactivated = 0;
     475           0 :         return (new_key);
     476             : }
     477             : 
     478             : void
     479           0 : sctp_free_sharedkey(sctp_sharedkey_t *skey)
     480             : {
     481           0 :         if (skey == NULL)
     482           0 :                 return;
     483             : 
     484           0 :         if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&skey->refcount)) {
     485           0 :                 if (skey->key != NULL)
     486           0 :                         sctp_free_key(skey->key);
     487           0 :                 SCTP_FREE(skey, SCTP_M_AUTH_KY);
     488             :         }
     489             : }
     490             : 
     491             : sctp_sharedkey_t *
     492           0 : sctp_find_sharedkey(struct sctp_keyhead *shared_keys, uint16_t key_id)
     493             : {
     494             :         sctp_sharedkey_t *skey;
     495             : 
     496           0 :         LIST_FOREACH(skey, shared_keys, next) {
     497           0 :                 if (skey->keyid == key_id)
     498           0 :                         return (skey);
     499             :         }
     500           0 :         return (NULL);
     501             : }
     502             : 
     503             : int
     504           0 : sctp_insert_sharedkey(struct sctp_keyhead *shared_keys,
     505             :                       sctp_sharedkey_t *new_skey)
     506             : {
     507             :         sctp_sharedkey_t *skey;
     508             : 
     509           0 :         if ((shared_keys == NULL) || (new_skey == NULL))
     510           0 :                 return (EINVAL);
     511             : 
     512             :         /* insert into an empty list? */
     513           0 :         if (LIST_EMPTY(shared_keys)) {
     514           0 :                 LIST_INSERT_HEAD(shared_keys, new_skey, next);
     515           0 :                 return (0);
     516             :         }
     517             :         /* insert into the existing list, ordered by key id */
     518           0 :         LIST_FOREACH(skey, shared_keys, next) {
     519           0 :                 if (new_skey->keyid < skey->keyid) {
     520             :                         /* insert it before here */
     521           0 :                         LIST_INSERT_BEFORE(skey, new_skey, next);
     522           0 :                         return (0);
     523           0 :                 } else if (new_skey->keyid == skey->keyid) {
     524             :                         /* replace the existing key */
     525             :                         /* verify this key *can* be replaced */
     526           0 :                         if ((skey->deactivated) && (skey->refcount > 1)) {
     527           0 :                                 SCTPDBG(SCTP_DEBUG_AUTH1,
     528             :                                         "can't replace shared key id %u\n",
     529             :                                         new_skey->keyid);
     530           0 :                                 return (EBUSY);
     531             :                         }
     532           0 :                         SCTPDBG(SCTP_DEBUG_AUTH1,
     533             :                                 "replacing shared key id %u\n",
     534             :                                 new_skey->keyid);
     535           0 :                         LIST_INSERT_BEFORE(skey, new_skey, next);
     536           0 :                         LIST_REMOVE(skey, next);
     537           0 :                         sctp_free_sharedkey(skey);
     538           0 :                         return (0);
     539             :                 }
     540           0 :                 if (LIST_NEXT(skey, next) == NULL) {
     541             :                         /* belongs at the end of the list */
     542           0 :                         LIST_INSERT_AFTER(skey, new_skey, next);
     543           0 :                         return (0);
     544             :                 }
     545             :         }
     546             :         /* shouldn't reach here */
     547           0 :         return (0);
     548             : }
     549             : 
     550             : void
     551           0 : sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t key_id)
     552             : {
     553             :         sctp_sharedkey_t *skey;
     554             : 
     555             :         /* find the shared key */
     556           0 :         skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, key_id);
     557             : 
     558             :         /* bump the ref count */
     559           0 :         if (skey) {
     560           0 :                 atomic_add_int(&skey->refcount, 1);
     561           0 :                 SCTPDBG(SCTP_DEBUG_AUTH2,
     562             :                         "%s: stcb %p key %u refcount acquire to %d\n",
     563             :                         __FUNCTION__, (void *)stcb, key_id, skey->refcount);
     564             :         }
     565           0 : }
     566             : 
     567             : void
     568           0 : sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked
     569             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     570             :         SCTP_UNUSED
     571             : #endif
     572             : )
     573             : {
     574             :         sctp_sharedkey_t *skey;
     575             : 
     576             :         /* find the shared key */
     577           0 :         skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, key_id);
     578             : 
     579             :         /* decrement the ref count */
     580           0 :         if (skey) {
     581           0 :                 sctp_free_sharedkey(skey);
     582           0 :                 SCTPDBG(SCTP_DEBUG_AUTH2,
     583             :                         "%s: stcb %p key %u refcount release to %d\n",
     584             :                         __FUNCTION__, (void *)stcb, key_id, skey->refcount);
     585             : 
     586             :                 /* see if a notification should be generated */
     587           0 :                 if ((skey->refcount <= 1) && (skey->deactivated)) {
     588             :                         /* notify ULP that key is no longer used */
     589           0 :                         sctp_ulp_notify(SCTP_NOTIFY_AUTH_FREE_KEY, stcb,
     590             :                                         key_id, 0, so_locked);
     591           0 :                         SCTPDBG(SCTP_DEBUG_AUTH2,
     592             :                                 "%s: stcb %p key %u no longer used, %d\n",
     593             :                                 __FUNCTION__, (void *)stcb, key_id, skey->refcount);
     594             :                 }
     595             :         }
     596           0 : }
     597             : 
     598             : static sctp_sharedkey_t *
     599           0 : sctp_copy_sharedkey(const sctp_sharedkey_t *skey)
     600             : {
     601             :         sctp_sharedkey_t *new_skey;
     602             : 
     603           0 :         if (skey == NULL)
     604           0 :                 return (NULL);
     605           0 :         new_skey = sctp_alloc_sharedkey();
     606           0 :         if (new_skey == NULL)
     607           0 :                 return (NULL);
     608           0 :         if (skey->key != NULL)
     609           0 :                 new_skey->key = sctp_set_key(skey->key->key, skey->key->keylen);
     610             :         else
     611           0 :                 new_skey->key = NULL;
     612           0 :         new_skey->keyid = skey->keyid;
     613           0 :         return (new_skey);
     614             : }
     615             : 
     616             : int
     617           0 : sctp_copy_skeylist(const struct sctp_keyhead *src, struct sctp_keyhead *dest)
     618             : {
     619             :         sctp_sharedkey_t *skey, *new_skey;
     620           0 :         int count = 0;
     621             : 
     622           0 :         if ((src == NULL) || (dest == NULL))
     623           0 :                 return (0);
     624           0 :         LIST_FOREACH(skey, src, next) {
     625           0 :                 new_skey = sctp_copy_sharedkey(skey);
     626           0 :                 if (new_skey != NULL) {
     627           0 :                         (void)sctp_insert_sharedkey(dest, new_skey);
     628           0 :                         count++;
     629             :                 }
     630             :         }
     631           0 :         return (count);
     632             : }
     633             : 
     634             : 
     635             : sctp_hmaclist_t *
     636           0 : sctp_alloc_hmaclist(uint16_t num_hmacs)
     637             : {
     638             :         sctp_hmaclist_t *new_list;
     639             :         int alloc_size;
     640             : 
     641           0 :         alloc_size = sizeof(*new_list) + num_hmacs * sizeof(new_list->hmac[0]);
     642           0 :         SCTP_MALLOC(new_list, sctp_hmaclist_t *, alloc_size,
     643             :                     SCTP_M_AUTH_HL);
     644           0 :         if (new_list == NULL) {
     645             :                 /* out of memory */
     646           0 :                 return (NULL);
     647             :         }
     648           0 :         new_list->max_algo = num_hmacs;
     649           0 :         new_list->num_algo = 0;
     650           0 :         return (new_list);
     651             : }
     652             : 
     653             : void
     654           0 : sctp_free_hmaclist(sctp_hmaclist_t *list)
     655             : {
     656           0 :         if (list != NULL) {
     657           0 :                 SCTP_FREE(list,SCTP_M_AUTH_HL);
     658           0 :                 list = NULL;
     659             :         }
     660           0 : }
     661             : 
     662             : int
     663           0 : sctp_auth_add_hmacid(sctp_hmaclist_t *list, uint16_t hmac_id)
     664             : {
     665             :         int i;
     666           0 :         if (list == NULL)
     667           0 :                 return (-1);
     668           0 :         if (list->num_algo == list->max_algo) {
     669           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1,
     670             :                         "SCTP: HMAC id list full, ignoring add %u\n", hmac_id);
     671           0 :                 return (-1);
     672             :         }
     673             : #if defined(SCTP_SUPPORT_HMAC_SHA256)
     674             :         if ((hmac_id != SCTP_AUTH_HMAC_ID_SHA1) &&
     675             :             (hmac_id != SCTP_AUTH_HMAC_ID_SHA256)) {
     676             : #else
     677           0 :         if (hmac_id != SCTP_AUTH_HMAC_ID_SHA1) {
     678             : #endif
     679           0 :                 return (-1);
     680             :         }
     681             :         /* Now is it already in the list */
     682           0 :         for (i = 0; i < list->num_algo; i++) {
     683           0 :                 if (list->hmac[i] == hmac_id) {
     684             :                         /* already in list */
     685           0 :                         return (-1);
     686             :                 }
     687             :         }
     688           0 :         SCTPDBG(SCTP_DEBUG_AUTH1, "SCTP: add HMAC id %u to list\n", hmac_id);
     689           0 :         list->hmac[list->num_algo++] = hmac_id;
     690           0 :         return (0);
     691             : }
     692             : 
     693             : sctp_hmaclist_t *
     694           0 : sctp_copy_hmaclist(sctp_hmaclist_t *list)
     695             : {
     696             :         sctp_hmaclist_t *new_list;
     697             :         int i;
     698             : 
     699           0 :         if (list == NULL)
     700           0 :                 return (NULL);
     701             :         /* get a new list */
     702           0 :         new_list = sctp_alloc_hmaclist(list->max_algo);
     703           0 :         if (new_list == NULL)
     704           0 :                 return (NULL);
     705             :         /* copy it */
     706           0 :         new_list->max_algo = list->max_algo;
     707           0 :         new_list->num_algo = list->num_algo;
     708           0 :         for (i = 0; i < list->num_algo; i++)
     709           0 :                 new_list->hmac[i] = list->hmac[i];
     710           0 :         return (new_list);
     711             : }
     712             : 
     713             : sctp_hmaclist_t *
     714           0 : sctp_default_supported_hmaclist(void)
     715             : {
     716             :         sctp_hmaclist_t *new_list;
     717             : 
     718             : #if defined(SCTP_SUPPORT_HMAC_SHA256)
     719             :         new_list = sctp_alloc_hmaclist(2);
     720             : #else
     721           0 :         new_list = sctp_alloc_hmaclist(1);
     722             : #endif
     723           0 :         if (new_list == NULL)
     724           0 :                 return (NULL);
     725             : #if defined(SCTP_SUPPORT_HMAC_SHA256)
     726             :         /* We prefer SHA256, so list it first */
     727             :         (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA256);
     728             : #endif
     729           0 :         (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1);
     730           0 :         return (new_list);
     731             : }
     732             : 
     733             : /*-
     734             :  * HMAC algos are listed in priority/preference order
     735             :  * find the best HMAC id to use for the peer based on local support
     736             :  */
     737             : uint16_t
     738           0 : sctp_negotiate_hmacid(sctp_hmaclist_t *peer, sctp_hmaclist_t *local)
     739             : {
     740             :         int i, j;
     741             : 
     742           0 :         if ((local == NULL) || (peer == NULL))
     743           0 :                 return (SCTP_AUTH_HMAC_ID_RSVD);
     744             : 
     745           0 :         for (i = 0; i < peer->num_algo; i++) {
     746           0 :                 for (j = 0; j < local->num_algo; j++) {
     747           0 :                         if (peer->hmac[i] == local->hmac[j]) {
     748             :                                 /* found the "best" one */
     749           0 :                                 SCTPDBG(SCTP_DEBUG_AUTH1,
     750             :                                         "SCTP: negotiated peer HMAC id %u\n",
     751             :                                         peer->hmac[i]);
     752           0 :                                 return (peer->hmac[i]);
     753             :                         }
     754             :                 }
     755             :         }
     756             :         /* didn't find one! */
     757           0 :         return (SCTP_AUTH_HMAC_ID_RSVD);
     758             : }
     759             : 
     760             : /*-
     761             :  * serialize the HMAC algo list and return space used
     762             :  * caller must guarantee ptr has appropriate space
     763             :  */
     764             : int
     765           0 : sctp_serialize_hmaclist(sctp_hmaclist_t *list, uint8_t *ptr)
     766             : {
     767             :         int i;
     768             :         uint16_t hmac_id;
     769             : 
     770           0 :         if (list == NULL)
     771           0 :                 return (0);
     772             : 
     773           0 :         for (i = 0; i < list->num_algo; i++) {
     774           0 :                 hmac_id = htons(list->hmac[i]);
     775           0 :                 bcopy(&hmac_id, ptr, sizeof(hmac_id));
     776           0 :                 ptr += sizeof(hmac_id);
     777             :         }
     778           0 :         return (list->num_algo * sizeof(hmac_id));
     779             : }
     780             : 
     781             : int
     782           0 : sctp_verify_hmac_param (struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs)
     783             : {
     784             :         uint32_t i;
     785             : 
     786           0 :         for (i = 0; i < num_hmacs; i++) {
     787           0 :                 if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) {
     788           0 :                         return (0);
     789             :                 }
     790             :         }
     791           0 :         return (-1);
     792             : }
     793             : 
     794             : sctp_authinfo_t *
     795           0 : sctp_alloc_authinfo(void)
     796             : {
     797             :         sctp_authinfo_t *new_authinfo;
     798             : 
     799           0 :         SCTP_MALLOC(new_authinfo, sctp_authinfo_t *, sizeof(*new_authinfo),
     800             :                     SCTP_M_AUTH_IF);
     801             : 
     802           0 :         if (new_authinfo == NULL) {
     803             :                 /* out of memory */
     804           0 :                 return (NULL);
     805             :         }
     806           0 :         bzero(new_authinfo, sizeof(*new_authinfo));
     807           0 :         return (new_authinfo);
     808             : }
     809             : 
     810             : void
     811           0 : sctp_free_authinfo(sctp_authinfo_t *authinfo)
     812             : {
     813           0 :         if (authinfo == NULL)
     814           0 :                 return;
     815             : 
     816           0 :         if (authinfo->random != NULL)
     817           0 :                 sctp_free_key(authinfo->random);
     818           0 :         if (authinfo->peer_random != NULL)
     819           0 :                 sctp_free_key(authinfo->peer_random);
     820           0 :         if (authinfo->assoc_key != NULL)
     821           0 :                 sctp_free_key(authinfo->assoc_key);
     822           0 :         if (authinfo->recv_key != NULL)
     823           0 :                 sctp_free_key(authinfo->recv_key);
     824             : 
     825             :         /* We are NOT dynamically allocating authinfo's right now... */
     826             :         /* SCTP_FREE(authinfo, SCTP_M_AUTH_??); */
     827             : }
     828             : 
     829             : 
     830             : uint32_t
     831           0 : sctp_get_auth_chunk_len(uint16_t hmac_algo)
     832             : {
     833             :         int size;
     834             : 
     835           0 :         size = sizeof(struct sctp_auth_chunk) + sctp_get_hmac_digest_len(hmac_algo);
     836           0 :         return (SCTP_SIZE32(size));
     837             : }
     838             : 
     839             : uint32_t
     840           0 : sctp_get_hmac_digest_len(uint16_t hmac_algo)
     841             : {
     842           0 :         switch (hmac_algo) {
     843             :         case SCTP_AUTH_HMAC_ID_SHA1:
     844           0 :                 return (SCTP_AUTH_DIGEST_LEN_SHA1);
     845             : #if defined(SCTP_SUPPORT_HMAC_SHA256)
     846             :         case SCTP_AUTH_HMAC_ID_SHA256:
     847             :                 return (SCTP_AUTH_DIGEST_LEN_SHA256);
     848             : #endif
     849             :         default:
     850             :                 /* unknown HMAC algorithm: can't do anything */
     851           0 :                 return (0);
     852             :         } /* end switch */
     853             : }
     854             : 
     855             : static inline int
     856           0 : sctp_get_hmac_block_len(uint16_t hmac_algo)
     857             : {
     858           0 :         switch (hmac_algo) {
     859             :         case SCTP_AUTH_HMAC_ID_SHA1:
     860           0 :                 return (64);
     861             : #if defined(SCTP_SUPPORT_HMAC_SHA256)
     862             :         case SCTP_AUTH_HMAC_ID_SHA256:
     863             :                 return (64);
     864             : #endif
     865             :         case SCTP_AUTH_HMAC_ID_RSVD:
     866             :         default:
     867             :                 /* unknown HMAC algorithm: can't do anything */
     868           0 :                 return (0);
     869             :         } /* end switch */
     870             : }
     871             : 
     872             : #if defined(__Userspace__)
     873             : /* __Userspace__ SHA1_Init is defined in libcrypto.a (libssl-dev on Ubuntu) */
     874             : #endif
     875             : static void
     876           0 : sctp_hmac_init(uint16_t hmac_algo, sctp_hash_context_t *ctx)
     877             : {
     878           0 :         switch (hmac_algo) {
     879             :         case SCTP_AUTH_HMAC_ID_SHA1:
     880           0 :                 SCTP_SHA1_INIT(&ctx->sha1);
     881           0 :                 break;
     882             : #if defined(SCTP_SUPPORT_HMAC_SHA256)
     883             :         case SCTP_AUTH_HMAC_ID_SHA256:
     884             :                 SCTP_SHA256_INIT(&ctx->sha256);
     885             :                 break;
     886             : #endif
     887             :         case SCTP_AUTH_HMAC_ID_RSVD:
     888             :         default:
     889             :                 /* unknown HMAC algorithm: can't do anything */
     890           0 :                 return;
     891             :         } /* end switch */
     892             : }
     893             : 
     894             : static void
     895           0 : sctp_hmac_update(uint16_t hmac_algo, sctp_hash_context_t *ctx,
     896             :     uint8_t *text, uint32_t textlen)
     897             : {
     898           0 :         switch (hmac_algo) {
     899             :         case SCTP_AUTH_HMAC_ID_SHA1:
     900           0 :                 SCTP_SHA1_UPDATE(&ctx->sha1, text, textlen);
     901           0 :                 break;
     902             : #if defined(SCTP_SUPPORT_HMAC_SHA256)
     903             :         case SCTP_AUTH_HMAC_ID_SHA256:
     904             :                 SCTP_SHA256_UPDATE(&ctx->sha256, text, textlen);
     905             :                 break;
     906             : #endif
     907             :         case SCTP_AUTH_HMAC_ID_RSVD:
     908             :         default:
     909             :                 /* unknown HMAC algorithm: can't do anything */
     910           0 :                 return;
     911             :         } /* end switch */
     912             : }
     913             : 
     914             : static void
     915           0 : sctp_hmac_final(uint16_t hmac_algo, sctp_hash_context_t *ctx,
     916             :     uint8_t *digest)
     917             : {
     918           0 :         switch (hmac_algo) {
     919             :         case SCTP_AUTH_HMAC_ID_SHA1:
     920           0 :                 SCTP_SHA1_FINAL(digest, &ctx->sha1);
     921           0 :                 break;
     922             : #if defined(SCTP_SUPPORT_HMAC_SHA256)
     923             :         case SCTP_AUTH_HMAC_ID_SHA256:
     924             :                 SCTP_SHA256_FINAL(digest, &ctx->sha256);
     925             :                 break;
     926             : #endif
     927             :         case SCTP_AUTH_HMAC_ID_RSVD:
     928             :         default:
     929             :                 /* unknown HMAC algorithm: can't do anything */
     930           0 :                 return;
     931             :         } /* end switch */
     932             : }
     933             : 
     934             : /*-
     935             :  * Keyed-Hashing for Message Authentication: FIPS 198 (RFC 2104)
     936             :  *
     937             :  * Compute the HMAC digest using the desired hash key, text, and HMAC
     938             :  * algorithm.  Resulting digest is placed in 'digest' and digest length
     939             :  * is returned, if the HMAC was performed.
     940             :  *
     941             :  * WARNING: it is up to the caller to supply sufficient space to hold the
     942             :  * resultant digest.
     943             :  */
     944             : uint32_t
     945           0 : sctp_hmac(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
     946             :     uint8_t *text, uint32_t textlen, uint8_t *digest)
     947             : {
     948             :         uint32_t digestlen;
     949             :         uint32_t blocklen;
     950             :         sctp_hash_context_t ctx;
     951             :         uint8_t ipad[128], opad[128];   /* keyed hash inner/outer pads */
     952             :         uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
     953             :         uint32_t i;
     954             : 
     955             :         /* sanity check the material and length */
     956           0 :         if ((key == NULL) || (keylen == 0) || (text == NULL) ||
     957           0 :             (textlen == 0) || (digest == NULL)) {
     958             :                 /* can't do HMAC with empty key or text or digest store */
     959           0 :                 return (0);
     960             :         }
     961             :         /* validate the hmac algo and get the digest length */
     962           0 :         digestlen = sctp_get_hmac_digest_len(hmac_algo);
     963           0 :         if (digestlen == 0)
     964           0 :                 return (0);
     965             : 
     966             :         /* hash the key if it is longer than the hash block size */
     967           0 :         blocklen = sctp_get_hmac_block_len(hmac_algo);
     968           0 :         if (keylen > blocklen) {
     969           0 :                 sctp_hmac_init(hmac_algo, &ctx);
     970           0 :                 sctp_hmac_update(hmac_algo, &ctx, key, keylen);
     971           0 :                 sctp_hmac_final(hmac_algo, &ctx, temp);
     972             :                 /* set the hashed key as the key */
     973           0 :                 keylen = digestlen;
     974           0 :                 key = temp;
     975             :         }
     976             :         /* initialize the inner/outer pads with the key and "append" zeroes */
     977           0 :         bzero(ipad, blocklen);
     978           0 :         bzero(opad, blocklen);
     979           0 :         bcopy(key, ipad, keylen);
     980           0 :         bcopy(key, opad, keylen);
     981             : 
     982             :         /* XOR the key with ipad and opad values */
     983           0 :         for (i = 0; i < blocklen; i++) {
     984           0 :                 ipad[i] ^= 0x36;
     985           0 :                 opad[i] ^= 0x5c;
     986             :         }
     987             : 
     988             :         /* perform inner hash */
     989           0 :         sctp_hmac_init(hmac_algo, &ctx);
     990           0 :         sctp_hmac_update(hmac_algo, &ctx, ipad, blocklen);
     991           0 :         sctp_hmac_update(hmac_algo, &ctx, text, textlen);
     992           0 :         sctp_hmac_final(hmac_algo, &ctx, temp);
     993             : 
     994             :         /* perform outer hash */
     995           0 :         sctp_hmac_init(hmac_algo, &ctx);
     996           0 :         sctp_hmac_update(hmac_algo, &ctx, opad, blocklen);
     997           0 :         sctp_hmac_update(hmac_algo, &ctx, temp, digestlen);
     998           0 :         sctp_hmac_final(hmac_algo, &ctx, digest);
     999             : 
    1000           0 :         return (digestlen);
    1001             : }
    1002             : 
    1003             : /* mbuf version */
    1004             : uint32_t
    1005           0 : sctp_hmac_m(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
    1006             :     struct mbuf *m, uint32_t m_offset, uint8_t *digest, uint32_t trailer)
    1007             : {
    1008             :         uint32_t digestlen;
    1009             :         uint32_t blocklen;
    1010             :         sctp_hash_context_t ctx;
    1011             :         uint8_t ipad[128], opad[128];   /* keyed hash inner/outer pads */
    1012             :         uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
    1013             :         uint32_t i;
    1014             :         struct mbuf *m_tmp;
    1015             : 
    1016             :         /* sanity check the material and length */
    1017           0 :         if ((key == NULL) || (keylen == 0) || (m == NULL) || (digest == NULL)) {
    1018             :                 /* can't do HMAC with empty key or text or digest store */
    1019           0 :                 return (0);
    1020             :         }
    1021             :         /* validate the hmac algo and get the digest length */
    1022           0 :         digestlen = sctp_get_hmac_digest_len(hmac_algo);
    1023           0 :         if (digestlen == 0)
    1024           0 :                 return (0);
    1025             : 
    1026             :         /* hash the key if it is longer than the hash block size */
    1027           0 :         blocklen = sctp_get_hmac_block_len(hmac_algo);
    1028           0 :         if (keylen > blocklen) {
    1029           0 :                 sctp_hmac_init(hmac_algo, &ctx);
    1030           0 :                 sctp_hmac_update(hmac_algo, &ctx, key, keylen);
    1031           0 :                 sctp_hmac_final(hmac_algo, &ctx, temp);
    1032             :                 /* set the hashed key as the key */
    1033           0 :                 keylen = digestlen;
    1034           0 :                 key = temp;
    1035             :         }
    1036             :         /* initialize the inner/outer pads with the key and "append" zeroes */
    1037           0 :         bzero(ipad, blocklen);
    1038           0 :         bzero(opad, blocklen);
    1039           0 :         bcopy(key, ipad, keylen);
    1040           0 :         bcopy(key, opad, keylen);
    1041             : 
    1042             :         /* XOR the key with ipad and opad values */
    1043           0 :         for (i = 0; i < blocklen; i++) {
    1044           0 :                 ipad[i] ^= 0x36;
    1045           0 :                 opad[i] ^= 0x5c;
    1046             :         }
    1047             : 
    1048             :         /* perform inner hash */
    1049           0 :         sctp_hmac_init(hmac_algo, &ctx);
    1050           0 :         sctp_hmac_update(hmac_algo, &ctx, ipad, blocklen);
    1051             :         /* find the correct starting mbuf and offset (get start of text) */
    1052           0 :         m_tmp = m;
    1053           0 :         while ((m_tmp != NULL) && (m_offset >= (uint32_t) SCTP_BUF_LEN(m_tmp))) {
    1054           0 :                 m_offset -= SCTP_BUF_LEN(m_tmp);
    1055           0 :                 m_tmp = SCTP_BUF_NEXT(m_tmp);
    1056             :         }
    1057             :         /* now use the rest of the mbuf chain for the text */
    1058           0 :         while (m_tmp != NULL) {
    1059           0 :                 if ((SCTP_BUF_NEXT(m_tmp) == NULL) && trailer) {
    1060           0 :                         sctp_hmac_update(hmac_algo, &ctx, mtod(m_tmp, uint8_t *) + m_offset,
    1061           0 :                                          SCTP_BUF_LEN(m_tmp) - (trailer+m_offset));
    1062             :                 } else {
    1063           0 :                         sctp_hmac_update(hmac_algo, &ctx, mtod(m_tmp, uint8_t *) + m_offset,
    1064           0 :                                          SCTP_BUF_LEN(m_tmp) - m_offset);
    1065             :                 }
    1066             : 
    1067             :                 /* clear the offset since it's only for the first mbuf */
    1068           0 :                 m_offset = 0;
    1069           0 :                 m_tmp = SCTP_BUF_NEXT(m_tmp);
    1070             :         }
    1071           0 :         sctp_hmac_final(hmac_algo, &ctx, temp);
    1072             : 
    1073             :         /* perform outer hash */
    1074           0 :         sctp_hmac_init(hmac_algo, &ctx);
    1075           0 :         sctp_hmac_update(hmac_algo, &ctx, opad, blocklen);
    1076           0 :         sctp_hmac_update(hmac_algo, &ctx, temp, digestlen);
    1077           0 :         sctp_hmac_final(hmac_algo, &ctx, digest);
    1078             : 
    1079           0 :         return (digestlen);
    1080             : }
    1081             : 
    1082             : /*-
    1083             :  * verify the HMAC digest using the desired hash key, text, and HMAC
    1084             :  * algorithm.
    1085             :  * Returns -1 on error, 0 on success.
    1086             :  */
    1087             : int
    1088           0 : sctp_verify_hmac(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
    1089             :     uint8_t *text, uint32_t textlen,
    1090             :     uint8_t *digest, uint32_t digestlen)
    1091             : {
    1092             :         uint32_t len;
    1093             :         uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
    1094             : 
    1095             :         /* sanity check the material and length */
    1096           0 :         if ((key == NULL) || (keylen == 0) ||
    1097           0 :             (text == NULL) || (textlen == 0) || (digest == NULL)) {
    1098             :                 /* can't do HMAC with empty key or text or digest */
    1099           0 :                 return (-1);
    1100             :         }
    1101           0 :         len = sctp_get_hmac_digest_len(hmac_algo);
    1102           0 :         if ((len == 0) || (digestlen != len))
    1103           0 :                 return (-1);
    1104             : 
    1105             :         /* compute the expected hash */
    1106           0 :         if (sctp_hmac(hmac_algo, key, keylen, text, textlen, temp) != len)
    1107           0 :                 return (-1);
    1108             : 
    1109           0 :         if (memcmp(digest, temp, digestlen) != 0)
    1110           0 :                 return (-1);
    1111             :         else
    1112           0 :                 return (0);
    1113             : }
    1114             : 
    1115             : 
    1116             : /*
    1117             :  * computes the requested HMAC using a key struct (which may be modified if
    1118             :  * the keylen exceeds the HMAC block len).
    1119             :  */
    1120             : uint32_t
    1121           0 : sctp_compute_hmac(uint16_t hmac_algo, sctp_key_t *key, uint8_t *text,
    1122             :     uint32_t textlen, uint8_t *digest)
    1123             : {
    1124             :         uint32_t digestlen;
    1125             :         uint32_t blocklen;
    1126             :         sctp_hash_context_t ctx;
    1127             :         uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
    1128             : 
    1129             :         /* sanity check */
    1130           0 :         if ((key == NULL) || (text == NULL) || (textlen == 0) ||
    1131             :             (digest == NULL)) {
    1132             :                 /* can't do HMAC with empty key or text or digest store */
    1133           0 :                 return (0);
    1134             :         }
    1135             :         /* validate the hmac algo and get the digest length */
    1136           0 :         digestlen = sctp_get_hmac_digest_len(hmac_algo);
    1137           0 :         if (digestlen == 0)
    1138           0 :                 return (0);
    1139             : 
    1140             :         /* hash the key if it is longer than the hash block size */
    1141           0 :         blocklen = sctp_get_hmac_block_len(hmac_algo);
    1142           0 :         if (key->keylen > blocklen) {
    1143           0 :                 sctp_hmac_init(hmac_algo, &ctx);
    1144           0 :                 sctp_hmac_update(hmac_algo, &ctx, key->key, key->keylen);
    1145           0 :                 sctp_hmac_final(hmac_algo, &ctx, temp);
    1146             :                 /* save the hashed key as the new key */
    1147           0 :                 key->keylen = digestlen;
    1148           0 :                 bcopy(temp, key->key, key->keylen);
    1149             :         }
    1150           0 :         return (sctp_hmac(hmac_algo, key->key, key->keylen, text, textlen,
    1151             :             digest));
    1152             : }
    1153             : 
    1154             : /* mbuf version */
    1155             : uint32_t
    1156           0 : sctp_compute_hmac_m(uint16_t hmac_algo, sctp_key_t *key, struct mbuf *m,
    1157             :     uint32_t m_offset, uint8_t *digest)
    1158             : {
    1159             :         uint32_t digestlen;
    1160             :         uint32_t blocklen;
    1161             :         sctp_hash_context_t ctx;
    1162             :         uint8_t temp[SCTP_AUTH_DIGEST_LEN_MAX];
    1163             : 
    1164             :         /* sanity check */
    1165           0 :         if ((key == NULL) || (m == NULL) || (digest == NULL)) {
    1166             :                 /* can't do HMAC with empty key or text or digest store */
    1167           0 :                 return (0);
    1168             :         }
    1169             :         /* validate the hmac algo and get the digest length */
    1170           0 :         digestlen = sctp_get_hmac_digest_len(hmac_algo);
    1171           0 :         if (digestlen == 0)
    1172           0 :                 return (0);
    1173             : 
    1174             :         /* hash the key if it is longer than the hash block size */
    1175           0 :         blocklen = sctp_get_hmac_block_len(hmac_algo);
    1176           0 :         if (key->keylen > blocklen) {
    1177           0 :                 sctp_hmac_init(hmac_algo, &ctx);
    1178           0 :                 sctp_hmac_update(hmac_algo, &ctx, key->key, key->keylen);
    1179           0 :                 sctp_hmac_final(hmac_algo, &ctx, temp);
    1180             :                 /* save the hashed key as the new key */
    1181           0 :                 key->keylen = digestlen;
    1182           0 :                 bcopy(temp, key->key, key->keylen);
    1183             :         }
    1184           0 :         return (sctp_hmac_m(hmac_algo, key->key, key->keylen, m, m_offset, digest, 0));
    1185             : }
    1186             : 
    1187             : int
    1188           0 : sctp_auth_is_supported_hmac(sctp_hmaclist_t *list, uint16_t id)
    1189             : {
    1190             :         int i;
    1191             : 
    1192           0 :         if ((list == NULL) || (id == SCTP_AUTH_HMAC_ID_RSVD))
    1193           0 :                 return (0);
    1194             : 
    1195           0 :         for (i = 0; i < list->num_algo; i++)
    1196           0 :                 if (list->hmac[i] == id)
    1197           0 :                         return (1);
    1198             : 
    1199             :         /* not in the list */
    1200           0 :         return (0);
    1201             : }
    1202             : 
    1203             : 
    1204             : /*-
    1205             :  * clear any cached key(s) if they match the given key id on an association.
    1206             :  * the cached key(s) will be recomputed and re-cached at next use.
    1207             :  * ASSUMES TCB_LOCK is already held
    1208             :  */
    1209             : void
    1210           0 : sctp_clear_cachedkeys(struct sctp_tcb *stcb, uint16_t keyid)
    1211             : {
    1212           0 :         if (stcb == NULL)
    1213           0 :                 return;
    1214             : 
    1215           0 :         if (keyid == stcb->asoc.authinfo.assoc_keyid) {
    1216           0 :                 sctp_free_key(stcb->asoc.authinfo.assoc_key);
    1217           0 :                 stcb->asoc.authinfo.assoc_key = NULL;
    1218             :         }
    1219           0 :         if (keyid == stcb->asoc.authinfo.recv_keyid) {
    1220           0 :                 sctp_free_key(stcb->asoc.authinfo.recv_key);
    1221           0 :                 stcb->asoc.authinfo.recv_key = NULL;
    1222             :         }
    1223             : }
    1224             : 
    1225             : /*-
    1226             :  * clear any cached key(s) if they match the given key id for all assocs on
    1227             :  * an endpoint.
    1228             :  * ASSUMES INP_WLOCK is already held
    1229             :  */
    1230             : void
    1231           0 : sctp_clear_cachedkeys_ep(struct sctp_inpcb *inp, uint16_t keyid)
    1232             : {
    1233             :         struct sctp_tcb *stcb;
    1234             : 
    1235           0 :         if (inp == NULL)
    1236           0 :                 return;
    1237             : 
    1238             :         /* clear the cached keys on all assocs on this instance */
    1239           0 :         LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
    1240           0 :                 SCTP_TCB_LOCK(stcb);
    1241           0 :                 sctp_clear_cachedkeys(stcb, keyid);
    1242           0 :                 SCTP_TCB_UNLOCK(stcb);
    1243             :         }
    1244             : }
    1245             : 
    1246             : /*-
    1247             :  * delete a shared key from an association
    1248             :  * ASSUMES TCB_LOCK is already held
    1249             :  */
    1250             : int
    1251           0 : sctp_delete_sharedkey(struct sctp_tcb *stcb, uint16_t keyid)
    1252             : {
    1253             :         sctp_sharedkey_t *skey;
    1254             : 
    1255           0 :         if (stcb == NULL)
    1256           0 :                 return (-1);
    1257             : 
    1258             :         /* is the keyid the assoc active sending key */
    1259           0 :         if (keyid == stcb->asoc.authinfo.active_keyid)
    1260           0 :                 return (-1);
    1261             : 
    1262             :         /* does the key exist? */
    1263           0 :         skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid);
    1264           0 :         if (skey == NULL)
    1265           0 :                 return (-1);
    1266             : 
    1267             :         /* are there other refcount holders on the key? */
    1268           0 :         if (skey->refcount > 1)
    1269           0 :                 return (-1);
    1270             : 
    1271             :         /* remove it */
    1272           0 :         LIST_REMOVE(skey, next);
    1273           0 :         sctp_free_sharedkey(skey);      /* frees skey->key as well */
    1274             : 
    1275             :         /* clear any cached keys */
    1276           0 :         sctp_clear_cachedkeys(stcb, keyid);
    1277           0 :         return (0);
    1278             : }
    1279             : 
    1280             : /*-
    1281             :  * deletes a shared key from the endpoint
    1282             :  * ASSUMES INP_WLOCK is already held
    1283             :  */
    1284             : int
    1285           0 : sctp_delete_sharedkey_ep(struct sctp_inpcb *inp, uint16_t keyid)
    1286             : {
    1287             :         sctp_sharedkey_t *skey;
    1288             : 
    1289           0 :         if (inp == NULL)
    1290           0 :                 return (-1);
    1291             : 
    1292             :         /* is the keyid the active sending key on the endpoint */
    1293           0 :         if (keyid == inp->sctp_ep.default_keyid)
    1294           0 :                 return (-1);
    1295             : 
    1296             :         /* does the key exist? */
    1297           0 :         skey = sctp_find_sharedkey(&inp->sctp_ep.shared_keys, keyid);
    1298           0 :         if (skey == NULL)
    1299           0 :                 return (-1);
    1300             : 
    1301             :         /* endpoint keys are not refcounted */
    1302             : 
    1303             :         /* remove it */
    1304           0 :         LIST_REMOVE(skey, next);
    1305           0 :         sctp_free_sharedkey(skey);      /* frees skey->key as well */
    1306             : 
    1307             :         /* clear any cached keys */
    1308           0 :         sctp_clear_cachedkeys_ep(inp, keyid);
    1309           0 :         return (0);
    1310             : }
    1311             : 
    1312             : /*-
    1313             :  * set the active key on an association
    1314             :  * ASSUMES TCB_LOCK is already held
    1315             :  */
    1316             : int
    1317           0 : sctp_auth_setactivekey(struct sctp_tcb *stcb, uint16_t keyid)
    1318             : {
    1319           0 :         sctp_sharedkey_t *skey = NULL;
    1320             : 
    1321             :         /* find the key on the assoc */
    1322           0 :         skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid);
    1323           0 :         if (skey == NULL) {
    1324             :                 /* that key doesn't exist */
    1325           0 :                 return (-1);
    1326             :         }
    1327           0 :         if ((skey->deactivated) && (skey->refcount > 1)) {
    1328             :                 /* can't reactivate a deactivated key with other refcounts */
    1329           0 :                 return (-1);
    1330             :         }
    1331             : 
    1332             :         /* set the (new) active key */
    1333           0 :         stcb->asoc.authinfo.active_keyid = keyid;
    1334             :         /* reset the deactivated flag */
    1335           0 :         skey->deactivated = 0;
    1336             : 
    1337           0 :         return (0);
    1338             : }
    1339             : 
    1340             : /*-
    1341             :  * set the active key on an endpoint
    1342             :  * ASSUMES INP_WLOCK is already held
    1343             :  */
    1344             : int
    1345           0 : sctp_auth_setactivekey_ep(struct sctp_inpcb *inp, uint16_t keyid)
    1346             : {
    1347             :         sctp_sharedkey_t *skey;
    1348             : 
    1349             :         /* find the key */
    1350           0 :         skey = sctp_find_sharedkey(&inp->sctp_ep.shared_keys, keyid);
    1351           0 :         if (skey == NULL) {
    1352             :                 /* that key doesn't exist */
    1353           0 :                 return (-1);
    1354             :         }
    1355           0 :         inp->sctp_ep.default_keyid = keyid;
    1356           0 :         return (0);
    1357             : }
    1358             : 
    1359             : /*-
    1360             :  * deactivates a shared key from the association
    1361             :  * ASSUMES INP_WLOCK is already held
    1362             :  */
    1363             : int
    1364           0 : sctp_deact_sharedkey(struct sctp_tcb *stcb, uint16_t keyid)
    1365             : {
    1366             :         sctp_sharedkey_t *skey;
    1367             : 
    1368           0 :         if (stcb == NULL)
    1369           0 :                 return (-1);
    1370             : 
    1371             :         /* is the keyid the assoc active sending key */
    1372           0 :         if (keyid == stcb->asoc.authinfo.active_keyid)
    1373           0 :                 return (-1);
    1374             : 
    1375             :         /* does the key exist? */
    1376           0 :         skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid);
    1377           0 :         if (skey == NULL)
    1378           0 :                 return (-1);
    1379             : 
    1380             :         /* are there other refcount holders on the key? */
    1381           0 :         if (skey->refcount == 1) {
    1382             :                 /* no other users, send a notification for this key */
    1383           0 :                 sctp_ulp_notify(SCTP_NOTIFY_AUTH_FREE_KEY, stcb, keyid, 0,
    1384             :                                 SCTP_SO_LOCKED);
    1385             :         }
    1386             : 
    1387             :         /* mark the key as deactivated */
    1388           0 :         skey->deactivated = 1;
    1389             : 
    1390           0 :         return (0);
    1391             : }
    1392             : 
    1393             : /*-
    1394             :  * deactivates a shared key from the endpoint
    1395             :  * ASSUMES INP_WLOCK is already held
    1396             :  */
    1397             : int
    1398           0 : sctp_deact_sharedkey_ep(struct sctp_inpcb *inp, uint16_t keyid)
    1399             : {
    1400             :         sctp_sharedkey_t *skey;
    1401             : 
    1402           0 :         if (inp == NULL)
    1403           0 :                 return (-1);
    1404             : 
    1405             :         /* is the keyid the active sending key on the endpoint */
    1406           0 :         if (keyid == inp->sctp_ep.default_keyid)
    1407           0 :                 return (-1);
    1408             : 
    1409             :         /* does the key exist? */
    1410           0 :         skey = sctp_find_sharedkey(&inp->sctp_ep.shared_keys, keyid);
    1411           0 :         if (skey == NULL)
    1412           0 :                 return (-1);
    1413             : 
    1414             :         /* endpoint keys are not refcounted */
    1415             : 
    1416             :         /* remove it */
    1417           0 :         LIST_REMOVE(skey, next);
    1418           0 :         sctp_free_sharedkey(skey);      /* frees skey->key as well */
    1419             : 
    1420           0 :         return (0);
    1421             : }
    1422             : 
    1423             : /*
    1424             :  * get local authentication parameters from cookie (from INIT-ACK)
    1425             :  */
    1426             : void
    1427           0 : sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
    1428             :     uint32_t offset, uint32_t length)
    1429             : {
    1430             :         struct sctp_paramhdr *phdr, tmp_param;
    1431             :         uint16_t plen, ptype;
    1432             :         uint8_t random_store[SCTP_PARAM_BUFFER_SIZE];
    1433           0 :         struct sctp_auth_random *p_random = NULL;
    1434           0 :         uint16_t random_len = 0;
    1435             :         uint8_t hmacs_store[SCTP_PARAM_BUFFER_SIZE];
    1436           0 :         struct sctp_auth_hmac_algo *hmacs = NULL;
    1437           0 :         uint16_t hmacs_len = 0;
    1438             :         uint8_t chunks_store[SCTP_PARAM_BUFFER_SIZE];
    1439           0 :         struct sctp_auth_chunk_list *chunks = NULL;
    1440           0 :         uint16_t num_chunks = 0;
    1441             :         sctp_key_t *new_key;
    1442             :         uint32_t keylen;
    1443             : 
    1444             :         /* convert to upper bound */
    1445           0 :         length += offset;
    1446             : 
    1447           0 :         phdr = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
    1448             :             sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param);
    1449           0 :         while (phdr != NULL) {
    1450           0 :                 ptype = ntohs(phdr->param_type);
    1451           0 :                 plen = ntohs(phdr->param_length);
    1452             : 
    1453           0 :                 if ((plen == 0) || (offset + plen > length))
    1454             :                         break;
    1455             : 
    1456           0 :                 if (ptype == SCTP_RANDOM) {
    1457           0 :                         if (plen > sizeof(random_store))
    1458           0 :                                 break;
    1459           0 :                         phdr = sctp_get_next_param(m, offset,
    1460             :                             (struct sctp_paramhdr *)random_store, min(plen, sizeof(random_store)));
    1461           0 :                         if (phdr == NULL)
    1462           0 :                                 return;
    1463             :                         /* save the random and length for the key */
    1464           0 :                         p_random = (struct sctp_auth_random *)phdr;
    1465           0 :                         random_len = plen - sizeof(*p_random);
    1466           0 :                 } else if (ptype == SCTP_HMAC_LIST) {
    1467             :                         uint16_t num_hmacs;
    1468             :                         uint16_t i;
    1469             : 
    1470           0 :                         if (plen > sizeof(hmacs_store))
    1471           0 :                                 break;
    1472           0 :                         phdr = sctp_get_next_param(m, offset,
    1473             :                             (struct sctp_paramhdr *)hmacs_store, min(plen,sizeof(hmacs_store)));
    1474           0 :                         if (phdr == NULL)
    1475           0 :                                 return;
    1476             :                         /* save the hmacs list and num for the key */
    1477           0 :                         hmacs = (struct sctp_auth_hmac_algo *)phdr;
    1478           0 :                         hmacs_len = plen - sizeof(*hmacs);
    1479           0 :                         num_hmacs = hmacs_len / sizeof(hmacs->hmac_ids[0]);
    1480           0 :                         if (stcb->asoc.local_hmacs != NULL)
    1481           0 :                                 sctp_free_hmaclist(stcb->asoc.local_hmacs);
    1482           0 :                         stcb->asoc.local_hmacs = sctp_alloc_hmaclist(num_hmacs);
    1483           0 :                         if (stcb->asoc.local_hmacs != NULL) {
    1484           0 :                                 for (i = 0; i < num_hmacs; i++) {
    1485           0 :                                         (void)sctp_auth_add_hmacid(stcb->asoc.local_hmacs,
    1486           0 :                                             ntohs(hmacs->hmac_ids[i]));
    1487             :                                 }
    1488             :                         }
    1489           0 :                 } else if (ptype == SCTP_CHUNK_LIST) {
    1490             :                         int i;
    1491             : 
    1492           0 :                         if (plen > sizeof(chunks_store))
    1493           0 :                                 break;
    1494           0 :                         phdr = sctp_get_next_param(m, offset,
    1495             :                             (struct sctp_paramhdr *)chunks_store, min(plen,sizeof(chunks_store)));
    1496           0 :                         if (phdr == NULL)
    1497           0 :                                 return;
    1498           0 :                         chunks = (struct sctp_auth_chunk_list *)phdr;
    1499           0 :                         num_chunks = plen - sizeof(*chunks);
    1500             :                         /* save chunks list and num for the key */
    1501           0 :                         if (stcb->asoc.local_auth_chunks != NULL)
    1502           0 :                                 sctp_clear_chunklist(stcb->asoc.local_auth_chunks);
    1503             :                         else
    1504           0 :                                 stcb->asoc.local_auth_chunks = sctp_alloc_chunklist();
    1505           0 :                         for (i = 0; i < num_chunks; i++) {
    1506           0 :                                 (void)sctp_auth_add_chunk(chunks->chunk_types[i],
    1507             :                                     stcb->asoc.local_auth_chunks);
    1508             :                         }
    1509             :                 }
    1510             :                 /* get next parameter */
    1511           0 :                 offset += SCTP_SIZE32(plen);
    1512           0 :                 if (offset + sizeof(struct sctp_paramhdr) > length)
    1513           0 :                         break;
    1514           0 :                 phdr = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
    1515             :                     (uint8_t *)&tmp_param);
    1516             :         }
    1517             :         /* concatenate the full random key */
    1518           0 :         keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len;
    1519           0 :         if (chunks != NULL) {
    1520           0 :                 keylen += sizeof(*chunks) + num_chunks;
    1521             :         }
    1522           0 :         new_key = sctp_alloc_key(keylen);
    1523           0 :         if (new_key != NULL) {
    1524             :             /* copy in the RANDOM */
    1525           0 :             if (p_random != NULL) {
    1526           0 :                 keylen = sizeof(*p_random) + random_len;
    1527           0 :                 bcopy(p_random, new_key->key, keylen);
    1528             :             }
    1529             :             /* append in the AUTH chunks */
    1530           0 :             if (chunks != NULL) {
    1531           0 :                 bcopy(chunks, new_key->key + keylen,
    1532             :                       sizeof(*chunks) + num_chunks);
    1533           0 :                 keylen += sizeof(*chunks) + num_chunks;
    1534             :             }
    1535             :             /* append in the HMACs */
    1536           0 :             if (hmacs != NULL) {
    1537           0 :                 bcopy(hmacs, new_key->key + keylen,
    1538             :                       sizeof(*hmacs) + hmacs_len);
    1539             :             }
    1540             :         }
    1541           0 :         if (stcb->asoc.authinfo.random != NULL)
    1542           0 :                 sctp_free_key(stcb->asoc.authinfo.random);
    1543           0 :         stcb->asoc.authinfo.random = new_key;
    1544           0 :         stcb->asoc.authinfo.random_len = random_len;
    1545           0 :         sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.assoc_keyid);
    1546           0 :         sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.recv_keyid);
    1547             : 
    1548             :         /* negotiate what HMAC to use for the peer */
    1549           0 :         stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
    1550             :             stcb->asoc.local_hmacs);
    1551             : 
    1552             :         /* copy defaults from the endpoint */
    1553             :         /* FIX ME: put in cookie? */
    1554           0 :         stcb->asoc.authinfo.active_keyid = stcb->sctp_ep->sctp_ep.default_keyid;
    1555             :         /* copy out the shared key list (by reference) from the endpoint */
    1556           0 :         (void)sctp_copy_skeylist(&stcb->sctp_ep->sctp_ep.shared_keys,
    1557             :                                  &stcb->asoc.shared_keys);
    1558             : }
    1559             : 
    1560             : /*
    1561             :  * compute and fill in the HMAC digest for a packet
    1562             :  */
    1563             : void
    1564           0 : sctp_fill_hmac_digest_m(struct mbuf *m, uint32_t auth_offset,
    1565             :     struct sctp_auth_chunk *auth, struct sctp_tcb *stcb, uint16_t keyid)
    1566             : {
    1567             :         uint32_t digestlen;
    1568             :         sctp_sharedkey_t *skey;
    1569             :         sctp_key_t *key;
    1570             : 
    1571           0 :         if ((stcb == NULL) || (auth == NULL))
    1572           0 :                 return;
    1573             : 
    1574             :         /* zero the digest + chunk padding */
    1575           0 :         digestlen = sctp_get_hmac_digest_len(stcb->asoc.peer_hmac_id);
    1576           0 :         bzero(auth->hmac, SCTP_SIZE32(digestlen));
    1577             : 
    1578             :         /* is the desired key cached? */
    1579           0 :         if ((keyid != stcb->asoc.authinfo.assoc_keyid) ||
    1580           0 :             (stcb->asoc.authinfo.assoc_key == NULL)) {
    1581           0 :                 if (stcb->asoc.authinfo.assoc_key != NULL) {
    1582             :                         /* free the old cached key */
    1583           0 :                         sctp_free_key(stcb->asoc.authinfo.assoc_key);
    1584             :                 }
    1585           0 :                 skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid);
    1586             :                 /* the only way skey is NULL is if null key id 0 is used */
    1587           0 :                 if (skey != NULL)
    1588           0 :                         key = skey->key;
    1589             :                 else
    1590           0 :                         key = NULL;
    1591             :                 /* compute a new assoc key and cache it */
    1592           0 :                 stcb->asoc.authinfo.assoc_key =
    1593           0 :                     sctp_compute_hashkey(stcb->asoc.authinfo.random,
    1594             :                                          stcb->asoc.authinfo.peer_random, key);
    1595           0 :                 stcb->asoc.authinfo.assoc_keyid = keyid;
    1596           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1, "caching key id %u\n",
    1597             :                         stcb->asoc.authinfo.assoc_keyid);
    1598             : #ifdef SCTP_DEBUG
    1599           0 :                 if (SCTP_AUTH_DEBUG)
    1600           0 :                         sctp_print_key(stcb->asoc.authinfo.assoc_key,
    1601             :                                        "Assoc Key");
    1602             : #endif
    1603             :         }
    1604             : 
    1605             :         /* set in the active key id */
    1606           0 :         auth->shared_key_id = htons(keyid);
    1607             : 
    1608             :         /* compute and fill in the digest */
    1609           0 :         (void)sctp_compute_hmac_m(stcb->asoc.peer_hmac_id, stcb->asoc.authinfo.assoc_key,
    1610           0 :                                   m, auth_offset, auth->hmac);
    1611             : }
    1612             : 
    1613             : 
    1614             : static void
    1615           0 : sctp_bzero_m(struct mbuf *m, uint32_t m_offset, uint32_t size)
    1616             : {
    1617             :         struct mbuf *m_tmp;
    1618             :         uint8_t *data;
    1619             : 
    1620             :         /* sanity check */
    1621           0 :         if (m == NULL)
    1622           0 :                 return;
    1623             : 
    1624             :         /* find the correct starting mbuf and offset (get start position) */
    1625           0 :         m_tmp = m;
    1626           0 :         while ((m_tmp != NULL) && (m_offset >= (uint32_t) SCTP_BUF_LEN(m_tmp))) {
    1627           0 :                 m_offset -= SCTP_BUF_LEN(m_tmp);
    1628           0 :                 m_tmp = SCTP_BUF_NEXT(m_tmp);
    1629             :         }
    1630             :         /* now use the rest of the mbuf chain */
    1631           0 :         while ((m_tmp != NULL) && (size > 0)) {
    1632           0 :                 data = mtod(m_tmp, uint8_t *) + m_offset;
    1633           0 :                 if (size > (uint32_t) SCTP_BUF_LEN(m_tmp)) {
    1634           0 :                         bzero(data, SCTP_BUF_LEN(m_tmp));
    1635           0 :                         size -= SCTP_BUF_LEN(m_tmp);
    1636             :                 } else {
    1637           0 :                         bzero(data, size);
    1638           0 :                         size = 0;
    1639             :                 }
    1640             :                 /* clear the offset since it's only for the first mbuf */
    1641           0 :                 m_offset = 0;
    1642           0 :                 m_tmp = SCTP_BUF_NEXT(m_tmp);
    1643             :         }
    1644             : }
    1645             : 
    1646             : /*-
    1647             :  * process the incoming Authentication chunk
    1648             :  * return codes:
    1649             :  *   -1 on any authentication error
    1650             :  *    0 on authentication verification
    1651             :  */
    1652             : int
    1653           0 : sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth,
    1654             :     struct mbuf *m, uint32_t offset)
    1655             : {
    1656             :         uint16_t chunklen;
    1657             :         uint16_t shared_key_id;
    1658             :         uint16_t hmac_id;
    1659             :         sctp_sharedkey_t *skey;
    1660             :         uint32_t digestlen;
    1661             :         uint8_t digest[SCTP_AUTH_DIGEST_LEN_MAX];
    1662             :         uint8_t computed_digest[SCTP_AUTH_DIGEST_LEN_MAX];
    1663             : 
    1664             :         /* auth is checked for NULL by caller */
    1665           0 :         chunklen = ntohs(auth->ch.chunk_length);
    1666           0 :         if (chunklen < sizeof(*auth)) {
    1667           0 :                 SCTP_STAT_INCR(sctps_recvauthfailed);
    1668           0 :                 return (-1);
    1669             :         }
    1670           0 :         SCTP_STAT_INCR(sctps_recvauth);
    1671             : 
    1672             :         /* get the auth params */
    1673           0 :         shared_key_id = ntohs(auth->shared_key_id);
    1674           0 :         hmac_id = ntohs(auth->hmac_id);
    1675           0 :         SCTPDBG(SCTP_DEBUG_AUTH1,
    1676             :                 "SCTP AUTH Chunk: shared key %u, HMAC id %u\n",
    1677             :                 shared_key_id, hmac_id);
    1678             : 
    1679             :         /* is the indicated HMAC supported? */
    1680           0 :         if (!sctp_auth_is_supported_hmac(stcb->asoc.local_hmacs, hmac_id)) {
    1681             :                 struct mbuf *m_err;
    1682             :                 struct sctp_auth_invalid_hmac *err;
    1683             : 
    1684           0 :                 SCTP_STAT_INCR(sctps_recvivalhmacid);
    1685           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1,
    1686             :                         "SCTP Auth: unsupported HMAC id %u\n",
    1687             :                         hmac_id);
    1688             :                 /*
    1689             :                  * report this in an Error Chunk: Unsupported HMAC
    1690             :                  * Identifier
    1691             :                  */
    1692           0 :                 m_err = sctp_get_mbuf_for_msg(sizeof(*err), 0, M_NOWAIT,
    1693             :                                               1, MT_HEADER);
    1694           0 :                 if (m_err != NULL) {
    1695             :                         /* pre-reserve some space */
    1696           0 :                         SCTP_BUF_RESV_UF(m_err, sizeof(struct sctp_chunkhdr));
    1697             :                         /* fill in the error */
    1698           0 :                         err = mtod(m_err, struct sctp_auth_invalid_hmac *);
    1699           0 :                         bzero(err, sizeof(*err));
    1700           0 :                         err->ph.param_type = htons(SCTP_CAUSE_UNSUPPORTED_HMACID);
    1701           0 :                         err->ph.param_length = htons(sizeof(*err));
    1702           0 :                         err->hmac_id = ntohs(hmac_id);
    1703           0 :                         SCTP_BUF_LEN(m_err) = sizeof(*err);
    1704             :                         /* queue it */
    1705           0 :                         sctp_queue_op_err(stcb, m_err);
    1706             :                 }
    1707           0 :                 return (-1);
    1708             :         }
    1709             :         /* get the indicated shared key, if available */
    1710           0 :         if ((stcb->asoc.authinfo.recv_key == NULL) ||
    1711           0 :             (stcb->asoc.authinfo.recv_keyid != shared_key_id)) {
    1712             :                 /* find the shared key on the assoc first */
    1713           0 :                 skey = sctp_find_sharedkey(&stcb->asoc.shared_keys,
    1714             :                                            shared_key_id);
    1715             :                 /* if the shared key isn't found, discard the chunk */
    1716           0 :                 if (skey == NULL) {
    1717           0 :                         SCTP_STAT_INCR(sctps_recvivalkeyid);
    1718           0 :                         SCTPDBG(SCTP_DEBUG_AUTH1,
    1719             :                                 "SCTP Auth: unknown key id %u\n",
    1720             :                                 shared_key_id);
    1721           0 :                         return (-1);
    1722             :                 }
    1723             :                 /* generate a notification if this is a new key id */
    1724           0 :                 if (stcb->asoc.authinfo.recv_keyid != shared_key_id)
    1725             :                         /*
    1726             :                          * sctp_ulp_notify(SCTP_NOTIFY_AUTH_NEW_KEY, stcb,
    1727             :                          * shared_key_id, (void
    1728             :                          * *)stcb->asoc.authinfo.recv_keyid);
    1729             :                          */
    1730           0 :                         sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY,
    1731           0 :                             shared_key_id, stcb->asoc.authinfo.recv_keyid,
    1732             :                             SCTP_SO_NOT_LOCKED);
    1733             :                 /* compute a new recv assoc key and cache it */
    1734           0 :                 if (stcb->asoc.authinfo.recv_key != NULL)
    1735           0 :                         sctp_free_key(stcb->asoc.authinfo.recv_key);
    1736           0 :                 stcb->asoc.authinfo.recv_key =
    1737           0 :                     sctp_compute_hashkey(stcb->asoc.authinfo.random,
    1738             :                     stcb->asoc.authinfo.peer_random, skey->key);
    1739           0 :                 stcb->asoc.authinfo.recv_keyid = shared_key_id;
    1740             : #ifdef SCTP_DEBUG
    1741           0 :                 if (SCTP_AUTH_DEBUG)
    1742           0 :                         sctp_print_key(stcb->asoc.authinfo.recv_key, "Recv Key");
    1743             : #endif
    1744             :         }
    1745             :         /* validate the digest length */
    1746           0 :         digestlen = sctp_get_hmac_digest_len(hmac_id);
    1747           0 :         if (chunklen < (sizeof(*auth) + digestlen)) {
    1748             :                 /* invalid digest length */
    1749           0 :                 SCTP_STAT_INCR(sctps_recvauthfailed);
    1750           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1,
    1751             :                         "SCTP Auth: chunk too short for HMAC\n");
    1752           0 :                 return (-1);
    1753             :         }
    1754             :         /* save a copy of the digest, zero the pseudo header, and validate */
    1755           0 :         bcopy(auth->hmac, digest, digestlen);
    1756           0 :         sctp_bzero_m(m, offset + sizeof(*auth), SCTP_SIZE32(digestlen));
    1757           0 :         (void)sctp_compute_hmac_m(hmac_id, stcb->asoc.authinfo.recv_key,
    1758             :             m, offset, computed_digest);
    1759             : 
    1760             :         /* compare the computed digest with the one in the AUTH chunk */
    1761           0 :         if (memcmp(digest, computed_digest, digestlen) != 0) {
    1762           0 :                 SCTP_STAT_INCR(sctps_recvauthfailed);
    1763           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1,
    1764             :                         "SCTP Auth: HMAC digest check failed\n");
    1765           0 :                 return (-1);
    1766             :         }
    1767           0 :         return (0);
    1768             : }
    1769             : 
    1770             : /*
    1771             :  * Generate NOTIFICATION
    1772             :  */
    1773             : void
    1774           0 : sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
    1775             :                            uint16_t keyid, uint16_t alt_keyid, int so_locked
    1776             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    1777             :         SCTP_UNUSED
    1778             : #endif
    1779             : )
    1780             : {
    1781             :         struct mbuf *m_notify;
    1782             :         struct sctp_authkey_event *auth;
    1783             :         struct sctp_queued_to_read *control;
    1784             : 
    1785           0 :         if ((stcb == NULL) ||
    1786           0 :            (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
    1787           0 :            (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
    1788           0 :            (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)
    1789             :                 ) {
    1790             :                 /* If the socket is gone we are out of here */
    1791           0 :                 return;
    1792             :         }
    1793             : 
    1794           0 :         if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_AUTHEVNT))
    1795             :                 /* event not enabled */
    1796           0 :                 return;
    1797             : 
    1798           0 :         m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_authkey_event),
    1799             :                                           0, M_NOWAIT, 1, MT_HEADER);
    1800           0 :         if (m_notify == NULL)
    1801             :                 /* no space left */
    1802           0 :                 return;
    1803             : 
    1804           0 :         SCTP_BUF_LEN(m_notify) = 0;
    1805           0 :         auth = mtod(m_notify, struct sctp_authkey_event *);
    1806           0 :         memset(auth, 0, sizeof(struct sctp_authkey_event));
    1807           0 :         auth->auth_type = SCTP_AUTHENTICATION_EVENT;
    1808           0 :         auth->auth_flags = 0;
    1809           0 :         auth->auth_length = sizeof(*auth);
    1810           0 :         auth->auth_keynumber = keyid;
    1811           0 :         auth->auth_altkeynumber = alt_keyid;
    1812           0 :         auth->auth_indication = indication;
    1813           0 :         auth->auth_assoc_id = sctp_get_associd(stcb);
    1814             : 
    1815           0 :         SCTP_BUF_LEN(m_notify) = sizeof(*auth);
    1816           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    1817             : 
    1818             :         /* append to socket */
    1819           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    1820             :             0, 0, stcb->asoc.context, 0, 0, 0, m_notify);
    1821           0 :         if (control == NULL) {
    1822             :                 /* no memory */
    1823           0 :                 sctp_m_freem(m_notify);
    1824           0 :                 return;
    1825             :         }
    1826           0 :         control->spec_flags = M_NOTIFICATION;
    1827           0 :         control->length = SCTP_BUF_LEN(m_notify);
    1828             :         /* not that we need this */
    1829           0 :         control->tail_mbuf = m_notify;
    1830           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb, control,
    1831           0 :             &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
    1832             : }
    1833             : 
    1834             : 
    1835             : /*-
    1836             :  * validates the AUTHentication related parameters in an INIT/INIT-ACK
    1837             :  * Note: currently only used for INIT as INIT-ACK is handled inline
    1838             :  * with sctp_load_addresses_from_init()
    1839             :  */
    1840             : int
    1841           0 : sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
    1842             : {
    1843             :         struct sctp_paramhdr *phdr, parm_buf;
    1844             :         uint16_t ptype, plen;
    1845           0 :         int peer_supports_asconf = 0;
    1846           0 :         int peer_supports_auth = 0;
    1847           0 :         int got_random = 0, got_hmacs = 0, got_chklist = 0;
    1848           0 :         uint8_t saw_asconf = 0;
    1849           0 :         uint8_t saw_asconf_ack = 0;
    1850             : 
    1851             :         /* go through each of the params. */
    1852           0 :         phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
    1853           0 :         while (phdr) {
    1854           0 :                 ptype = ntohs(phdr->param_type);
    1855           0 :                 plen = ntohs(phdr->param_length);
    1856             : 
    1857           0 :                 if (offset + plen > limit) {
    1858           0 :                         break;
    1859             :                 }
    1860           0 :                 if (plen < sizeof(struct sctp_paramhdr)) {
    1861           0 :                         break;
    1862             :                 }
    1863           0 :                 if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
    1864             :                         /* A supported extension chunk */
    1865             :                         struct sctp_supported_chunk_types_param *pr_supported;
    1866             :                         uint8_t local_store[SCTP_PARAM_BUFFER_SIZE];
    1867             :                         int num_ent, i;
    1868             : 
    1869           0 :                         phdr = sctp_get_next_param(m, offset,
    1870             :                             (struct sctp_paramhdr *)&local_store, min(plen,sizeof(local_store)));
    1871           0 :                         if (phdr == NULL) {
    1872           0 :                                 return (-1);
    1873             :                         }
    1874           0 :                         pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
    1875           0 :                         num_ent = plen - sizeof(struct sctp_paramhdr);
    1876           0 :                         for (i = 0; i < num_ent; i++) {
    1877           0 :                                 switch (pr_supported->chunk_types[i]) {
    1878             :                                 case SCTP_ASCONF:
    1879             :                                 case SCTP_ASCONF_ACK:
    1880           0 :                                         peer_supports_asconf = 1;
    1881           0 :                                         break;
    1882             :                                 default:
    1883             :                                         /* one we don't care about */
    1884           0 :                                         break;
    1885             :                                 }
    1886             :                         }
    1887           0 :                 } else if (ptype == SCTP_RANDOM) {
    1888           0 :                         got_random = 1;
    1889             :                         /* enforce the random length */
    1890           0 :                         if (plen != (sizeof(struct sctp_auth_random) +
    1891             :                                      SCTP_AUTH_RANDOM_SIZE_REQUIRED)) {
    1892           0 :                                 SCTPDBG(SCTP_DEBUG_AUTH1,
    1893             :                                         "SCTP: invalid RANDOM len\n");
    1894           0 :                                 return (-1);
    1895             :                         }
    1896           0 :                 } else if (ptype == SCTP_HMAC_LIST) {
    1897             :                         uint8_t store[SCTP_PARAM_BUFFER_SIZE];
    1898             :                         struct sctp_auth_hmac_algo *hmacs;
    1899             :                         int num_hmacs;
    1900             : 
    1901           0 :                         if (plen > sizeof(store))
    1902           0 :                                 break;
    1903           0 :                         phdr = sctp_get_next_param(m, offset,
    1904             :                             (struct sctp_paramhdr *)store, min(plen,sizeof(store)));
    1905           0 :                         if (phdr == NULL)
    1906           0 :                                 return (-1);
    1907           0 :                         hmacs = (struct sctp_auth_hmac_algo *)phdr;
    1908           0 :                         num_hmacs = (plen - sizeof(*hmacs)) /
    1909             :                             sizeof(hmacs->hmac_ids[0]);
    1910             :                         /* validate the hmac list */
    1911           0 :                         if (sctp_verify_hmac_param(hmacs, num_hmacs)) {
    1912           0 :                                 SCTPDBG(SCTP_DEBUG_AUTH1,
    1913             :                                         "SCTP: invalid HMAC param\n");
    1914           0 :                                 return (-1);
    1915             :                         }
    1916           0 :                         got_hmacs = 1;
    1917           0 :                 } else if (ptype == SCTP_CHUNK_LIST) {
    1918             :                         int i, num_chunks;
    1919             :                         uint8_t chunks_store[SCTP_SMALL_CHUNK_STORE];
    1920             :                         /* did the peer send a non-empty chunk list? */
    1921           0 :                         struct sctp_auth_chunk_list *chunks = NULL;
    1922           0 :                         phdr = sctp_get_next_param(m, offset,
    1923             :                                                    (struct sctp_paramhdr *)chunks_store,
    1924             :                                                    min(plen,sizeof(chunks_store)));
    1925           0 :                         if (phdr == NULL)
    1926           0 :                                 return (-1);
    1927             : 
    1928             :                         /*-
    1929             :                          * Flip through the list and mark that the
    1930             :                          * peer supports asconf/asconf_ack.
    1931             :                          */
    1932           0 :                         chunks = (struct sctp_auth_chunk_list *)phdr;
    1933           0 :                         num_chunks = plen - sizeof(*chunks);
    1934           0 :                         for (i = 0; i < num_chunks; i++) {
    1935             :                                 /* record asconf/asconf-ack if listed */
    1936           0 :                                 if (chunks->chunk_types[i] == SCTP_ASCONF)
    1937           0 :                                         saw_asconf = 1;
    1938           0 :                                 if (chunks->chunk_types[i] == SCTP_ASCONF_ACK)
    1939           0 :                                         saw_asconf_ack = 1;
    1940             : 
    1941             :                         }
    1942           0 :                         if (num_chunks)
    1943           0 :                                 got_chklist = 1;
    1944             :                 }
    1945             : 
    1946           0 :                 offset += SCTP_SIZE32(plen);
    1947           0 :                 if (offset >= limit) {
    1948           0 :                         break;
    1949             :                 }
    1950           0 :                 phdr = sctp_get_next_param(m, offset, &parm_buf,
    1951             :                     sizeof(parm_buf));
    1952             :         }
    1953             :         /* validate authentication required parameters */
    1954           0 :         if (got_random && got_hmacs) {
    1955           0 :                 peer_supports_auth = 1;
    1956             :         } else {
    1957           0 :                 peer_supports_auth = 0;
    1958             :         }
    1959           0 :         if (!peer_supports_auth && got_chklist) {
    1960           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1,
    1961             :                         "SCTP: peer sent chunk list w/o AUTH\n");
    1962           0 :                 return (-1);
    1963             :         }
    1964           0 :         if (peer_supports_asconf && !peer_supports_auth) {
    1965           0 :                 SCTPDBG(SCTP_DEBUG_AUTH1,
    1966             :                         "SCTP: peer supports ASCONF but not AUTH\n");
    1967           0 :                 return (-1);
    1968           0 :         } else if ((peer_supports_asconf) && (peer_supports_auth) &&
    1969           0 :                    ((saw_asconf == 0) || (saw_asconf_ack == 0))) {
    1970           0 :                 return (-2);
    1971             :         }
    1972           0 :         return (0);
    1973             : }
    1974             : 
    1975             : void
    1976           0 : sctp_initialize_auth_params(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
    1977             : {
    1978           0 :         uint16_t chunks_len = 0;
    1979           0 :         uint16_t hmacs_len = 0;
    1980           0 :         uint16_t random_len = SCTP_AUTH_RANDOM_SIZE_DEFAULT;
    1981             :         sctp_key_t *new_key;
    1982             :         uint16_t keylen;
    1983             : 
    1984             :         /* initialize hmac list from endpoint */
    1985           0 :         stcb->asoc.local_hmacs = sctp_copy_hmaclist(inp->sctp_ep.local_hmacs);
    1986           0 :         if (stcb->asoc.local_hmacs != NULL) {
    1987           0 :                 hmacs_len = stcb->asoc.local_hmacs->num_algo *
    1988             :                     sizeof(stcb->asoc.local_hmacs->hmac[0]);
    1989             :         }
    1990             :         /* initialize auth chunks list from endpoint */
    1991           0 :         stcb->asoc.local_auth_chunks =
    1992           0 :             sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks);
    1993           0 :         if (stcb->asoc.local_auth_chunks != NULL) {
    1994             :                 int i;
    1995           0 :                 for (i = 0; i < 256; i++) {
    1996           0 :                         if (stcb->asoc.local_auth_chunks->chunks[i])
    1997           0 :                                 chunks_len++;
    1998             :                 }
    1999             :         }
    2000             :         /* copy defaults from the endpoint */
    2001           0 :         stcb->asoc.authinfo.active_keyid = inp->sctp_ep.default_keyid;
    2002             : 
    2003             :         /* copy out the shared key list (by reference) from the endpoint */
    2004           0 :         (void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys,
    2005             :                                  &stcb->asoc.shared_keys);
    2006             : 
    2007             :         /* now set the concatenated key (random + chunks + hmacs) */
    2008             :         /* key includes parameter headers */
    2009           0 :         keylen = (3 * sizeof(struct sctp_paramhdr)) + random_len + chunks_len +
    2010             :             hmacs_len;
    2011           0 :         new_key = sctp_alloc_key(keylen);
    2012           0 :         if (new_key != NULL) {
    2013             :                 struct sctp_paramhdr *ph;
    2014             :                 int plen;
    2015             :                 /* generate and copy in the RANDOM */
    2016           0 :                 ph = (struct sctp_paramhdr *)new_key->key;
    2017           0 :                 ph->param_type = htons(SCTP_RANDOM);
    2018           0 :                 plen = sizeof(*ph) + random_len;
    2019           0 :                 ph->param_length = htons(plen);
    2020           0 :                 SCTP_READ_RANDOM(new_key->key + sizeof(*ph), random_len);
    2021           0 :                 keylen = plen;
    2022             : 
    2023             :                 /* append in the AUTH chunks */
    2024             :                 /* NOTE: currently we always have chunks to list */
    2025           0 :                 ph = (struct sctp_paramhdr *)(new_key->key + keylen);
    2026           0 :                 ph->param_type = htons(SCTP_CHUNK_LIST);
    2027           0 :                 plen = sizeof(*ph) + chunks_len;
    2028           0 :                 ph->param_length = htons(plen);
    2029           0 :                 keylen += sizeof(*ph);
    2030           0 :                 if (stcb->asoc.local_auth_chunks) {
    2031             :                         int i;
    2032           0 :                         for (i = 0; i < 256; i++) {
    2033           0 :                                 if (stcb->asoc.local_auth_chunks->chunks[i])
    2034           0 :                                         new_key->key[keylen++] = i;
    2035             :                         }
    2036             :                 }
    2037             : 
    2038             :                 /* append in the HMACs */
    2039           0 :                 ph = (struct sctp_paramhdr *)(new_key->key + keylen);
    2040           0 :                 ph->param_type = htons(SCTP_HMAC_LIST);
    2041           0 :                 plen = sizeof(*ph) + hmacs_len;
    2042           0 :                 ph->param_length = htons(plen);
    2043           0 :                 keylen += sizeof(*ph);
    2044           0 :                 (void)sctp_serialize_hmaclist(stcb->asoc.local_hmacs,
    2045           0 :                                         new_key->key + keylen);
    2046             :         }
    2047           0 :         if (stcb->asoc.authinfo.random != NULL)
    2048           0 :             sctp_free_key(stcb->asoc.authinfo.random);
    2049           0 :         stcb->asoc.authinfo.random = new_key;
    2050           0 :         stcb->asoc.authinfo.random_len = random_len;
    2051           0 : }
    2052             : 
    2053             : 
    2054             : #ifdef SCTP_HMAC_TEST
    2055             : /*
    2056             :  * HMAC and key concatenation tests
    2057             :  */
    2058             : static void
    2059             : sctp_print_digest(uint8_t *digest, uint32_t digestlen, const char *str)
    2060             : {
    2061             :         uint32_t i;
    2062             : 
    2063             :         SCTP_PRINTF("\n%s: 0x", str);
    2064             :         if (digest == NULL)
    2065             :                 return;
    2066             : 
    2067             :         for (i = 0; i < digestlen; i++)
    2068             :                 SCTP_PRINTF("%02x", digest[i]);
    2069             : }
    2070             : 
    2071             : static int
    2072             : sctp_test_hmac(const char *str, uint16_t hmac_id, uint8_t *key,
    2073             :     uint32_t keylen, uint8_t *text, uint32_t textlen,
    2074             :     uint8_t *digest, uint32_t digestlen)
    2075             : {
    2076             :         uint8_t computed_digest[SCTP_AUTH_DIGEST_LEN_MAX];
    2077             : 
    2078             :         SCTP_PRINTF("\n%s:", str);
    2079             :         sctp_hmac(hmac_id, key, keylen, text, textlen, computed_digest);
    2080             :         sctp_print_digest(digest, digestlen, "Expected digest");
    2081             :         sctp_print_digest(computed_digest, digestlen, "Computed digest");
    2082             :         if (memcmp(digest, computed_digest, digestlen) != 0) {
    2083             :                 SCTP_PRINTF("\nFAILED");
    2084             :                 return (-1);
    2085             :         } else {
    2086             :                 SCTP_PRINTF("\nPASSED");
    2087             :                 return (0);
    2088             :         }
    2089             : }
    2090             : 
    2091             : 
    2092             : /*
    2093             :  * RFC 2202: HMAC-SHA1 test cases
    2094             :  */
    2095             : void
    2096             : sctp_test_hmac_sha1(void)
    2097             : {
    2098             :         uint8_t *digest;
    2099             :         uint8_t key[128];
    2100             :         uint32_t keylen;
    2101             :         uint8_t text[128];
    2102             :         uint32_t textlen;
    2103             :         uint32_t digestlen = 20;
    2104             :         int failed = 0;
    2105             : 
    2106             :         /*-
    2107             :          * test_case =     1
    2108             :          * key =           0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
    2109             :          * key_len =       20
    2110             :          * data =          "Hi There"
    2111             :          * data_len =      8
    2112             :          * digest =        0xb617318655057264e28bc0b6fb378c8ef146be00
    2113             :          */
    2114             :         keylen = 20;
    2115             :         memset(key, 0x0b, keylen);
    2116             :         textlen = 8;
    2117             :         strcpy(text, "Hi There");
    2118             :         digest = "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00";
    2119             :         if (sctp_test_hmac("SHA1 test case 1", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
    2120             :             text, textlen, digest, digestlen) < 0)
    2121             :                 failed++;
    2122             : 
    2123             :         /*-
    2124             :          * test_case =     2
    2125             :          * key =           "Jefe"
    2126             :          * key_len =       4
    2127             :          * data =          "what do ya want for nothing?"
    2128             :          * data_len =      28
    2129             :          * digest =        0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
    2130             :          */
    2131             :         keylen = 4;
    2132             :         strcpy(key, "Jefe");
    2133             :         textlen = 28;
    2134             :         strcpy(text, "what do ya want for nothing?");
    2135             :         digest = "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79";
    2136             :         if (sctp_test_hmac("SHA1 test case 2", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
    2137             :             text, textlen, digest, digestlen) < 0)
    2138             :                 failed++;
    2139             : 
    2140             :         /*-
    2141             :          * test_case =     3
    2142             :          * key =           0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    2143             :          * key_len =       20
    2144             :          * data =          0xdd repeated 50 times
    2145             :          * data_len =      50
    2146             :          * digest =        0x125d7342b9ac11cd91a39af48aa17b4f63f175d3
    2147             :          */
    2148             :         keylen = 20;
    2149             :         memset(key, 0xaa, keylen);
    2150             :         textlen = 50;
    2151             :         memset(text, 0xdd, textlen);
    2152             :         digest = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3";
    2153             :         if (sctp_test_hmac("SHA1 test case 3", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
    2154             :             text, textlen, digest, digestlen) < 0)
    2155             :                 failed++;
    2156             : 
    2157             :         /*-
    2158             :          * test_case =     4
    2159             :          * key =           0x0102030405060708090a0b0c0d0e0f10111213141516171819
    2160             :          * key_len =       25
    2161             :          * data =          0xcd repeated 50 times
    2162             :          * data_len =      50
    2163             :          * digest =        0x4c9007f4026250c6bc8414f9bf50c86c2d7235da
    2164             :          */
    2165             :         keylen = 25;
    2166             :         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);
    2167             :         textlen = 50;
    2168             :         memset(text, 0xcd, textlen);
    2169             :         digest = "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda";
    2170             :         if (sctp_test_hmac("SHA1 test case 4", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
    2171             :             text, textlen, digest, digestlen) < 0)
    2172             :                 failed++;
    2173             : 
    2174             :         /*-
    2175             :          * test_case =     5
    2176             :          * key =           0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
    2177             :          * key_len =       20
    2178             :          * data =          "Test With Truncation"
    2179             :          * data_len =      20
    2180             :          * digest =        0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
    2181             :          * digest-96 =     0x4c1a03424b55e07fe7f27be1
    2182             :          */
    2183             :         keylen = 20;
    2184             :         memset(key, 0x0c, keylen);
    2185             :         textlen = 20;
    2186             :         strcpy(text, "Test With Truncation");
    2187             :         digest = "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04";
    2188             :         if (sctp_test_hmac("SHA1 test case 5", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
    2189             :             text, textlen, digest, digestlen) < 0)
    2190             :                 failed++;
    2191             : 
    2192             :         /*-
    2193             :          * test_case =     6
    2194             :          * key =           0xaa repeated 80 times
    2195             :          * key_len =       80
    2196             :          * data =          "Test Using Larger Than Block-Size Key - Hash Key First"
    2197             :          * data_len =      54
    2198             :          * digest =        0xaa4ae5e15272d00e95705637ce8a3b55ed402112
    2199             :          */
    2200             :         keylen = 80;
    2201             :         memset(key, 0xaa, keylen);
    2202             :         textlen = 54;
    2203             :         strcpy(text, "Test Using Larger Than Block-Size Key - Hash Key First");
    2204             :         digest = "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12";
    2205             :         if (sctp_test_hmac("SHA1 test case 6", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
    2206             :             text, textlen, digest, digestlen) < 0)
    2207             :                 failed++;
    2208             : 
    2209             :         /*-
    2210             :          * test_case =     7
    2211             :          * key =           0xaa repeated 80 times
    2212             :          * key_len =       80
    2213             :          * data =          "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
    2214             :          * data_len =      73
    2215             :          * digest =        0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
    2216             :          */
    2217             :         keylen = 80;
    2218             :         memset(key, 0xaa, keylen);
    2219             :         textlen = 73;
    2220             :         strcpy(text, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data");
    2221             :         digest = "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91";
    2222             :         if (sctp_test_hmac("SHA1 test case 7", SCTP_AUTH_HMAC_ID_SHA1, key, keylen,
    2223             :             text, textlen, digest, digestlen) < 0)
    2224             :                 failed++;
    2225             : 
    2226             :         /* done with all tests */
    2227             :         if (failed)
    2228             :                 SCTP_PRINTF("\nSHA1 test results: %d cases failed", failed);
    2229             :         else
    2230             :                 SCTP_PRINTF("\nSHA1 test results: all test cases passed");
    2231             : }
    2232             : 
    2233             : /*
    2234             :  * test assoc key concatenation
    2235             :  */
    2236             : static int
    2237             : sctp_test_key_concatenation(sctp_key_t *key1, sctp_key_t *key2,
    2238             :     sctp_key_t *expected_key)
    2239             : {
    2240             :         sctp_key_t *key;
    2241             :         int ret_val;
    2242             : 
    2243             :         sctp_show_key(key1, "\nkey1");
    2244             :         sctp_show_key(key2, "\nkey2");
    2245             :         key = sctp_compute_hashkey(key1, key2, NULL);
    2246             :         sctp_show_key(expected_key, "\nExpected");
    2247             :         sctp_show_key(key, "\nComputed");
    2248             :         if (memcmp(key, expected_key, expected_key->keylen) != 0) {
    2249             :                 SCTP_PRINTF("\nFAILED");
    2250             :                 ret_val = -1;
    2251             :         } else {
    2252             :                 SCTP_PRINTF("\nPASSED");
    2253             :                 ret_val = 0;
    2254             :         }
    2255             :         sctp_free_key(key1);
    2256             :         sctp_free_key(key2);
    2257             :         sctp_free_key(expected_key);
    2258             :         sctp_free_key(key);
    2259             :         return (ret_val);
    2260             : }
    2261             : 
    2262             : 
    2263             : void
    2264             : sctp_test_authkey(void)
    2265             : {
    2266             :         sctp_key_t *key1, *key2, *expected_key;
    2267             :         int failed = 0;
    2268             : 
    2269             :         /* test case 1 */
    2270             :         key1 = sctp_set_key("\x01\x01\x01\x01", 4);
    2271             :         key2 = sctp_set_key("\x01\x02\x03\x04", 4);
    2272             :         expected_key = sctp_set_key("\x01\x01\x01\x01\x01\x02\x03\x04", 8);
    2273             :         if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
    2274             :                 failed++;
    2275             : 
    2276             :         /* test case 2 */
    2277             :         key1 = sctp_set_key("\x00\x00\x00\x01", 4);
    2278             :         key2 = sctp_set_key("\x02", 1);
    2279             :         expected_key = sctp_set_key("\x00\x00\x00\x01\x02", 5);
    2280             :         if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
    2281             :                 failed++;
    2282             : 
    2283             :         /* test case 3 */
    2284             :         key1 = sctp_set_key("\x01", 1);
    2285             :         key2 = sctp_set_key("\x00\x00\x00\x02", 4);
    2286             :         expected_key = sctp_set_key("\x01\x00\x00\x00\x02", 5);
    2287             :         if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
    2288             :                 failed++;
    2289             : 
    2290             :         /* test case 4 */
    2291             :         key1 = sctp_set_key("\x00\x00\x00\x01", 4);
    2292             :         key2 = sctp_set_key("\x01", 1);
    2293             :         expected_key = sctp_set_key("\x01\x00\x00\x00\x01", 5);
    2294             :         if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
    2295             :                 failed++;
    2296             : 
    2297             :         /* test case 5 */
    2298             :         key1 = sctp_set_key("\x01", 1);
    2299             :         key2 = sctp_set_key("\x00\x00\x00\x01", 4);
    2300             :         expected_key = sctp_set_key("\x01\x00\x00\x00\x01", 5);
    2301             :         if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
    2302             :                 failed++;
    2303             : 
    2304             :         /* test case 6 */
    2305             :         key1 = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07", 11);
    2306             :         key2 = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x08", 11);
    2307             :         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);
    2308             :         if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
    2309             :                 failed++;
    2310             : 
    2311             :         /* test case 7 */
    2312             :         key1 = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x08", 11);
    2313             :         key2 = sctp_set_key("\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07", 11);
    2314             :         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);
    2315             :         if (sctp_test_key_concatenation(key1, key2, expected_key) < 0)
    2316             :                 failed++;
    2317             : 
    2318             :         /* done with all tests */
    2319             :         if (failed)
    2320             :                 SCTP_PRINTF("\nKey concatenation test results: %d cases failed", failed);
    2321             :         else
    2322             :                 SCTP_PRINTF("\nKey concatenation test results: all test cases passed");
    2323             : }
    2324             : 
    2325             : 
    2326             : #if defined(STANDALONE_HMAC_TEST)
    2327             : int
    2328             : main(void)
    2329             : {
    2330             :         sctp_test_hmac_sha1();
    2331             :         sctp_test_authkey();
    2332             : }
    2333             : 
    2334             : #endif /* STANDALONE_HMAC_TEST */
    2335             : 
    2336             : #endif /* SCTP_HMAC_TEST */

Generated by: LCOV version 1.13