.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* SCTP kernel implementation |
---|
2 | 3 | * (C) Copyright 2007 Hewlett-Packard Development Company, L.P. |
---|
3 | 4 | * |
---|
4 | 5 | * This file is part of the SCTP kernel implementation |
---|
5 | | - * |
---|
6 | | - * This SCTP implementation is free software; |
---|
7 | | - * you can redistribute it and/or modify it under the terms of |
---|
8 | | - * the GNU General Public License as published by |
---|
9 | | - * the Free Software Foundation; either version 2, or (at your option) |
---|
10 | | - * any later version. |
---|
11 | | - * |
---|
12 | | - * This SCTP implementation is distributed in the hope that it |
---|
13 | | - * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
---|
14 | | - * ************************ |
---|
15 | | - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
---|
16 | | - * See the GNU General Public License for more details. |
---|
17 | | - * |
---|
18 | | - * You should have received a copy of the GNU General Public License |
---|
19 | | - * along with GNU CC; see the file COPYING. If not, see |
---|
20 | | - * <http://www.gnu.org/licenses/>. |
---|
21 | 6 | * |
---|
22 | 7 | * Please send any bug reports or fixes you make to the |
---|
23 | 8 | * email address(es): |
---|
.. | .. |
---|
64 | 49 | return; |
---|
65 | 50 | |
---|
66 | 51 | if (refcount_dec_and_test(&key->refcnt)) { |
---|
67 | | - kzfree(key); |
---|
| 52 | + kfree_sensitive(key); |
---|
68 | 53 | SCTP_DBG_OBJCNT_DEC(keys); |
---|
69 | 54 | } |
---|
70 | 55 | } |
---|
.. | .. |
---|
404 | 389 | /* If we don't support AUTH, or peer is not capable |
---|
405 | 390 | * we don't need to do anything. |
---|
406 | 391 | */ |
---|
407 | | - if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) |
---|
| 392 | + if (!asoc->peer.auth_capable) |
---|
408 | 393 | return 0; |
---|
409 | 394 | |
---|
410 | 395 | /* If the key_id is non-zero and we couldn't find an |
---|
.. | .. |
---|
460 | 445 | } |
---|
461 | 446 | |
---|
462 | 447 | /* |
---|
463 | | - * Initialize all the possible digest transforms that we can use. Right now |
---|
| 448 | + * Initialize all the possible digest transforms that we can use. Right |
---|
464 | 449 | * now, the supported digests are SHA1 and SHA256. We do this here once |
---|
465 | 450 | * because of the restrictiong that transforms may only be allocated in |
---|
466 | 451 | * user context. This forces us to pre-allocated all possible transforms |
---|
.. | .. |
---|
470 | 455 | { |
---|
471 | 456 | struct crypto_shash *tfm = NULL; |
---|
472 | 457 | __u16 id; |
---|
473 | | - |
---|
474 | | - /* If AUTH extension is disabled, we are done */ |
---|
475 | | - if (!ep->auth_enable) { |
---|
476 | | - ep->auth_hmacs = NULL; |
---|
477 | | - return 0; |
---|
478 | | - } |
---|
479 | 458 | |
---|
480 | 459 | /* If the transforms are already allocated, we are done */ |
---|
481 | 460 | if (ep->auth_hmacs) |
---|
.. | .. |
---|
697 | 676 | if (!asoc) |
---|
698 | 677 | return 0; |
---|
699 | 678 | |
---|
700 | | - if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) |
---|
| 679 | + if (!asoc->peer.auth_capable) |
---|
701 | 680 | return 0; |
---|
702 | 681 | |
---|
703 | 682 | return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); |
---|
.. | .. |
---|
709 | 688 | if (!asoc) |
---|
710 | 689 | return 0; |
---|
711 | 690 | |
---|
712 | | - if (!asoc->ep->auth_enable) |
---|
| 691 | + if (!asoc->peer.auth_capable) |
---|
713 | 692 | return 0; |
---|
714 | 693 | |
---|
715 | 694 | return __sctp_auth_cid(chunk, |
---|
.. | .. |
---|
763 | 742 | if (crypto_shash_setkey(tfm, &asoc_key->data[0], asoc_key->len)) |
---|
764 | 743 | goto free; |
---|
765 | 744 | |
---|
766 | | - { |
---|
767 | | - SHASH_DESC_ON_STACK(desc, tfm); |
---|
768 | | - |
---|
769 | | - desc->tfm = tfm; |
---|
770 | | - desc->flags = 0; |
---|
771 | | - crypto_shash_digest(desc, (u8 *)auth, |
---|
772 | | - end - (unsigned char *)auth, digest); |
---|
773 | | - shash_desc_zero(desc); |
---|
774 | | - } |
---|
| 745 | + crypto_shash_tfm_digest(tfm, (u8 *)auth, end - (unsigned char *)auth, |
---|
| 746 | + digest); |
---|
775 | 747 | |
---|
776 | 748 | free: |
---|
777 | 749 | if (free_key) |
---|
.. | .. |
---|
839 | 811 | } |
---|
840 | 812 | |
---|
841 | 813 | /* Set a new shared key on either endpoint or association. If the |
---|
842 | | - * the key with a same ID already exists, replace the key (remove the |
---|
| 814 | + * key with a same ID already exists, replace the key (remove the |
---|
843 | 815 | * old key and add a new one). |
---|
844 | 816 | */ |
---|
845 | 817 | int sctp_auth_set_key(struct sctp_endpoint *ep, |
---|
.. | .. |
---|
854 | 826 | /* Try to find the given key id to see if |
---|
855 | 827 | * we are doing a replace, or adding a new key |
---|
856 | 828 | */ |
---|
857 | | - if (asoc) |
---|
| 829 | + if (asoc) { |
---|
| 830 | + if (!asoc->peer.auth_capable) |
---|
| 831 | + return -EACCES; |
---|
858 | 832 | sh_keys = &asoc->endpoint_shared_keys; |
---|
859 | | - else |
---|
| 833 | + } else { |
---|
| 834 | + if (!ep->auth_enable) |
---|
| 835 | + return -EACCES; |
---|
860 | 836 | sh_keys = &ep->endpoint_shared_keys; |
---|
| 837 | + } |
---|
861 | 838 | |
---|
862 | 839 | key_for_each(shkey, sh_keys) { |
---|
863 | 840 | if (shkey->key_id == auth_key->sca_keynumber) { |
---|
.. | .. |
---|
886 | 863 | } |
---|
887 | 864 | |
---|
888 | 865 | list_del_init(&shkey->key_list); |
---|
889 | | - sctp_auth_shkey_release(shkey); |
---|
890 | 866 | list_add(&cur_key->key_list, sh_keys); |
---|
891 | 867 | |
---|
892 | | - if (asoc && asoc->active_key_id == auth_key->sca_keynumber) |
---|
893 | | - sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); |
---|
| 868 | + if (asoc && asoc->active_key_id == auth_key->sca_keynumber && |
---|
| 869 | + sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL)) { |
---|
| 870 | + list_del_init(&cur_key->key_list); |
---|
| 871 | + sctp_auth_shkey_release(cur_key); |
---|
| 872 | + list_add(&shkey->key_list, sh_keys); |
---|
| 873 | + return -ENOMEM; |
---|
| 874 | + } |
---|
894 | 875 | |
---|
| 876 | + sctp_auth_shkey_release(shkey); |
---|
895 | 877 | return 0; |
---|
896 | 878 | } |
---|
897 | 879 | |
---|
.. | .. |
---|
904 | 886 | int found = 0; |
---|
905 | 887 | |
---|
906 | 888 | /* The key identifier MUST correst to an existing key */ |
---|
907 | | - if (asoc) |
---|
| 889 | + if (asoc) { |
---|
| 890 | + if (!asoc->peer.auth_capable) |
---|
| 891 | + return -EACCES; |
---|
908 | 892 | sh_keys = &asoc->endpoint_shared_keys; |
---|
909 | | - else |
---|
| 893 | + } else { |
---|
| 894 | + if (!ep->auth_enable) |
---|
| 895 | + return -EACCES; |
---|
910 | 896 | sh_keys = &ep->endpoint_shared_keys; |
---|
| 897 | + } |
---|
911 | 898 | |
---|
912 | 899 | key_for_each(key, sh_keys) { |
---|
913 | 900 | if (key->key_id == key_id) { |
---|
.. | .. |
---|
920 | 907 | return -EINVAL; |
---|
921 | 908 | |
---|
922 | 909 | if (asoc) { |
---|
| 910 | + __u16 active_key_id = asoc->active_key_id; |
---|
| 911 | + |
---|
923 | 912 | asoc->active_key_id = key_id; |
---|
924 | | - sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); |
---|
| 913 | + if (sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL)) { |
---|
| 914 | + asoc->active_key_id = active_key_id; |
---|
| 915 | + return -ENOMEM; |
---|
| 916 | + } |
---|
925 | 917 | } else |
---|
926 | 918 | ep->active_key_id = key_id; |
---|
927 | 919 | |
---|
.. | .. |
---|
940 | 932 | * The key identifier MUST correst to an existing key |
---|
941 | 933 | */ |
---|
942 | 934 | if (asoc) { |
---|
| 935 | + if (!asoc->peer.auth_capable) |
---|
| 936 | + return -EACCES; |
---|
943 | 937 | if (asoc->active_key_id == key_id) |
---|
944 | 938 | return -EINVAL; |
---|
945 | 939 | |
---|
946 | 940 | sh_keys = &asoc->endpoint_shared_keys; |
---|
947 | 941 | } else { |
---|
| 942 | + if (!ep->auth_enable) |
---|
| 943 | + return -EACCES; |
---|
948 | 944 | if (ep->active_key_id == key_id) |
---|
949 | 945 | return -EINVAL; |
---|
950 | 946 | |
---|
.. | .. |
---|
979 | 975 | * The key identifier MUST correst to an existing key |
---|
980 | 976 | */ |
---|
981 | 977 | if (asoc) { |
---|
| 978 | + if (!asoc->peer.auth_capable) |
---|
| 979 | + return -EACCES; |
---|
982 | 980 | if (asoc->active_key_id == key_id) |
---|
983 | 981 | return -EINVAL; |
---|
984 | 982 | |
---|
985 | 983 | sh_keys = &asoc->endpoint_shared_keys; |
---|
986 | 984 | } else { |
---|
| 985 | + if (!ep->auth_enable) |
---|
| 986 | + return -EACCES; |
---|
987 | 987 | if (ep->active_key_id == key_id) |
---|
988 | 988 | return -EINVAL; |
---|
989 | 989 | |
---|
.. | .. |
---|
1018 | 1018 | |
---|
1019 | 1019 | return 0; |
---|
1020 | 1020 | } |
---|
| 1021 | + |
---|
| 1022 | +int sctp_auth_init(struct sctp_endpoint *ep, gfp_t gfp) |
---|
| 1023 | +{ |
---|
| 1024 | + int err = -ENOMEM; |
---|
| 1025 | + |
---|
| 1026 | + /* Allocate space for HMACS and CHUNKS authentication |
---|
| 1027 | + * variables. There are arrays that we encode directly |
---|
| 1028 | + * into parameters to make the rest of the operations easier. |
---|
| 1029 | + */ |
---|
| 1030 | + if (!ep->auth_hmacs_list) { |
---|
| 1031 | + struct sctp_hmac_algo_param *auth_hmacs; |
---|
| 1032 | + |
---|
| 1033 | + auth_hmacs = kzalloc(struct_size(auth_hmacs, hmac_ids, |
---|
| 1034 | + SCTP_AUTH_NUM_HMACS), gfp); |
---|
| 1035 | + if (!auth_hmacs) |
---|
| 1036 | + goto nomem; |
---|
| 1037 | + /* Initialize the HMACS parameter. |
---|
| 1038 | + * SCTP-AUTH: Section 3.3 |
---|
| 1039 | + * Every endpoint supporting SCTP chunk authentication MUST |
---|
| 1040 | + * support the HMAC based on the SHA-1 algorithm. |
---|
| 1041 | + */ |
---|
| 1042 | + auth_hmacs->param_hdr.type = SCTP_PARAM_HMAC_ALGO; |
---|
| 1043 | + auth_hmacs->param_hdr.length = |
---|
| 1044 | + htons(sizeof(struct sctp_paramhdr) + 2); |
---|
| 1045 | + auth_hmacs->hmac_ids[0] = htons(SCTP_AUTH_HMAC_ID_SHA1); |
---|
| 1046 | + ep->auth_hmacs_list = auth_hmacs; |
---|
| 1047 | + } |
---|
| 1048 | + |
---|
| 1049 | + if (!ep->auth_chunk_list) { |
---|
| 1050 | + struct sctp_chunks_param *auth_chunks; |
---|
| 1051 | + |
---|
| 1052 | + auth_chunks = kzalloc(sizeof(*auth_chunks) + |
---|
| 1053 | + SCTP_NUM_CHUNK_TYPES, gfp); |
---|
| 1054 | + if (!auth_chunks) |
---|
| 1055 | + goto nomem; |
---|
| 1056 | + /* Initialize the CHUNKS parameter */ |
---|
| 1057 | + auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; |
---|
| 1058 | + auth_chunks->param_hdr.length = |
---|
| 1059 | + htons(sizeof(struct sctp_paramhdr)); |
---|
| 1060 | + ep->auth_chunk_list = auth_chunks; |
---|
| 1061 | + } |
---|
| 1062 | + |
---|
| 1063 | + /* Allocate and initialize transorms arrays for supported |
---|
| 1064 | + * HMACs. |
---|
| 1065 | + */ |
---|
| 1066 | + err = sctp_auth_init_hmacs(ep, gfp); |
---|
| 1067 | + if (err) |
---|
| 1068 | + goto nomem; |
---|
| 1069 | + |
---|
| 1070 | + return 0; |
---|
| 1071 | + |
---|
| 1072 | +nomem: |
---|
| 1073 | + /* Free all allocations */ |
---|
| 1074 | + kfree(ep->auth_hmacs_list); |
---|
| 1075 | + kfree(ep->auth_chunk_list); |
---|
| 1076 | + ep->auth_hmacs_list = NULL; |
---|
| 1077 | + ep->auth_chunk_list = NULL; |
---|
| 1078 | + return err; |
---|
| 1079 | +} |
---|
| 1080 | + |
---|
| 1081 | +void sctp_auth_free(struct sctp_endpoint *ep) |
---|
| 1082 | +{ |
---|
| 1083 | + kfree(ep->auth_hmacs_list); |
---|
| 1084 | + kfree(ep->auth_chunk_list); |
---|
| 1085 | + ep->auth_hmacs_list = NULL; |
---|
| 1086 | + ep->auth_chunk_list = NULL; |
---|
| 1087 | + sctp_auth_destroy_hmacs(ep->auth_hmacs); |
---|
| 1088 | + ep->auth_hmacs = NULL; |
---|
| 1089 | +} |
---|