@@ -101,20 +101,32 @@ struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp)
101101 return NULL ;
102102
103103 INIT_LIST_HEAD (& new -> key_list );
104+ refcount_set (& new -> refcnt , 1 );
104105 new -> key_id = key_id ;
105106
106107 return new ;
107108}
108109
109110/* Free the shared key structure */
110- static void sctp_auth_shkey_free (struct sctp_shared_key * sh_key )
111+ static void sctp_auth_shkey_destroy (struct sctp_shared_key * sh_key )
111112{
112113 BUG_ON (!list_empty (& sh_key -> key_list ));
113114 sctp_auth_key_put (sh_key -> key );
114115 sh_key -> key = NULL ;
115116 kfree (sh_key );
116117}
117118
119+ void sctp_auth_shkey_release (struct sctp_shared_key * sh_key )
120+ {
121+ if (refcount_dec_and_test (& sh_key -> refcnt ))
122+ sctp_auth_shkey_destroy (sh_key );
123+ }
124+
125+ void sctp_auth_shkey_hold (struct sctp_shared_key * sh_key )
126+ {
127+ refcount_inc (& sh_key -> refcnt );
128+ }
129+
118130/* Destroy the entire key list. This is done during the
119131 * associon and endpoint free process.
120132 */
@@ -128,7 +140,7 @@ void sctp_auth_destroy_keys(struct list_head *keys)
128140
129141 key_for_each_safe (ep_key , tmp , keys ) {
130142 list_del_init (& ep_key -> key_list );
131- sctp_auth_shkey_free (ep_key );
143+ sctp_auth_shkey_release (ep_key );
132144 }
133145}
134146
@@ -409,13 +421,19 @@ int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp)
409421
410422 sctp_auth_key_put (asoc -> asoc_shared_key );
411423 asoc -> asoc_shared_key = secret ;
424+ asoc -> shkey = ep_key ;
412425
413426 /* Update send queue in case any chunk already in there now
414427 * needs authenticating
415428 */
416429 list_for_each_entry (chunk , & asoc -> outqueue .out_chunk_list , list ) {
417- if (sctp_auth_send_cid (chunk -> chunk_hdr -> type , asoc ))
430+ if (sctp_auth_send_cid (chunk -> chunk_hdr -> type , asoc )) {
418431 chunk -> auth = 1 ;
432+ if (!chunk -> shkey ) {
433+ chunk -> shkey = asoc -> shkey ;
434+ sctp_auth_shkey_hold (chunk -> shkey );
435+ }
436+ }
419437 }
420438
421439 return 0 ;
@@ -703,16 +721,15 @@ int sctp_auth_recv_cid(enum sctp_cid chunk, const struct sctp_association *asoc)
703721 * after the AUTH chunk in the SCTP packet.
704722 */
705723void sctp_auth_calculate_hmac (const struct sctp_association * asoc ,
706- struct sk_buff * skb ,
707- struct sctp_auth_chunk * auth ,
708- gfp_t gfp )
724+ struct sk_buff * skb , struct sctp_auth_chunk * auth ,
725+ struct sctp_shared_key * ep_key , gfp_t gfp )
709726{
710- struct crypto_shash * tfm ;
711727 struct sctp_auth_bytes * asoc_key ;
728+ struct crypto_shash * tfm ;
712729 __u16 key_id , hmac_id ;
713- __u8 * digest ;
714730 unsigned char * end ;
715731 int free_key = 0 ;
732+ __u8 * digest ;
716733
717734 /* Extract the info we need:
718735 * - hmac id
@@ -724,12 +741,7 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc,
724741 if (key_id == asoc -> active_key_id )
725742 asoc_key = asoc -> asoc_shared_key ;
726743 else {
727- struct sctp_shared_key * ep_key ;
728-
729- ep_key = sctp_auth_get_shkey (asoc , key_id );
730- if (!ep_key )
731- return ;
732-
744+ /* ep_key can't be NULL here */
733745 asoc_key = sctp_auth_asoc_create_secret (asoc , ep_key , gfp );
734746 if (!asoc_key )
735747 return ;
@@ -829,7 +841,7 @@ int sctp_auth_set_key(struct sctp_endpoint *ep,
829841 struct sctp_association * asoc ,
830842 struct sctp_authkey * auth_key )
831843{
832- struct sctp_shared_key * cur_key = NULL ;
844+ struct sctp_shared_key * cur_key , * shkey ;
833845 struct sctp_auth_bytes * key ;
834846 struct list_head * sh_keys ;
835847 int replace = 0 ;
@@ -842,46 +854,34 @@ int sctp_auth_set_key(struct sctp_endpoint *ep,
842854 else
843855 sh_keys = & ep -> endpoint_shared_keys ;
844856
845- key_for_each (cur_key , sh_keys ) {
846- if (cur_key -> key_id == auth_key -> sca_keynumber ) {
857+ key_for_each (shkey , sh_keys ) {
858+ if (shkey -> key_id == auth_key -> sca_keynumber ) {
847859 replace = 1 ;
848860 break ;
849861 }
850862 }
851863
852- /* If we are not replacing a key id, we need to allocate
853- * a shared key.
854- */
855- if (!replace ) {
856- cur_key = sctp_auth_shkey_create (auth_key -> sca_keynumber ,
857- GFP_KERNEL );
858- if (!cur_key )
859- return - ENOMEM ;
860- }
864+ cur_key = sctp_auth_shkey_create (auth_key -> sca_keynumber , GFP_KERNEL );
865+ if (!cur_key )
866+ return - ENOMEM ;
861867
862868 /* Create a new key data based on the info passed in */
863869 key = sctp_auth_create_key (auth_key -> sca_keylength , GFP_KERNEL );
864- if (!key )
865- goto nomem ;
870+ if (!key ) {
871+ kfree (cur_key );
872+ return - ENOMEM ;
873+ }
866874
867875 memcpy (key -> data , & auth_key -> sca_key [0 ], auth_key -> sca_keylength );
876+ cur_key -> key = key ;
868877
869- /* If we are replacing, remove the old keys data from the
870- * key id. If we are adding new key id, add it to the
871- * list.
872- */
873- if (replace )
874- sctp_auth_key_put (cur_key -> key );
875- else
876- list_add (& cur_key -> key_list , sh_keys );
878+ if (replace ) {
879+ list_del_init (& shkey -> key_list );
880+ sctp_auth_shkey_release (shkey );
881+ }
882+ list_add (& cur_key -> key_list , sh_keys );
877883
878- cur_key -> key = key ;
879884 return 0 ;
880- nomem :
881- if (!replace )
882- sctp_auth_shkey_free (cur_key );
883-
884- return - ENOMEM ;
885885}
886886
887887int sctp_auth_set_active_key (struct sctp_endpoint * ep ,
@@ -952,7 +952,7 @@ int sctp_auth_del_key_id(struct sctp_endpoint *ep,
952952
953953 /* Delete the shared key */
954954 list_del_init (& key -> key_list );
955- sctp_auth_shkey_free (key );
955+ sctp_auth_shkey_release (key );
956956
957957 return 0 ;
958958}
0 commit comments