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 */
|