Skip to content

Commit 65b07e5

Browse files
Vlad YasevichDavid S. Miller
authored andcommitted
[SCTP]: API updates to suport SCTP-AUTH extensions.
Add SCTP-AUTH API. The API implemented here was agreed to between implementors at the 9th SCTP Interop. It will be documented in the next revision of the SCTP socket API spec. Signed-off-by: Vlad Yasevich <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bbd0d59 commit 65b07e5

File tree

7 files changed

+657
-0
lines changed

7 files changed

+657
-0
lines changed

include/net/sctp/auth.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
struct sctp_endpoint;
4444
struct sctp_association;
4545
struct sctp_authkey;
46+
struct sctp_hmacalgo;
4647

4748
/*
4849
* Define a generic struct that will hold all the info
@@ -109,4 +110,19 @@ int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc);
109110
void sctp_auth_calculate_hmac(const struct sctp_association *asoc,
110111
struct sk_buff *skb,
111112
struct sctp_auth_chunk *auth, gfp_t gfp);
113+
114+
/* API Helpers */
115+
int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id);
116+
int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
117+
struct sctp_hmacalgo *hmacs);
118+
int sctp_auth_set_key(struct sctp_endpoint *ep,
119+
struct sctp_association *asoc,
120+
struct sctp_authkey *auth_key);
121+
int sctp_auth_set_active_key(struct sctp_endpoint *ep,
122+
struct sctp_association *asoc,
123+
__u16 key_id);
124+
int sctp_auth_del_key_id(struct sctp_endpoint *ep,
125+
struct sctp_association *asoc,
126+
__u16 key_id);
127+
112128
#endif

include/net/sctp/ulpevent.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
128128
struct sctp_chunk *chunk,
129129
gfp_t gfp);
130130

131+
struct sctp_ulpevent *sctp_ulpevent_make_authkey(
132+
const struct sctp_association *asoc, __u16 key_id,
133+
__u32 indication, gfp_t gfp);
134+
131135
void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
132136
struct msghdr *);
133137
__u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event);

include/net/sctp/user.h

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,21 @@ enum sctp_optname {
103103
#define SCTP_PARTIAL_DELIVERY_POINT SCTP_PARTIAL_DELIVERY_POINT
104104
SCTP_MAX_BURST, /* Set/Get max burst */
105105
#define SCTP_MAX_BURST SCTP_MAX_BURST
106+
SCTP_AUTH_CHUNK, /* Set only: add a chunk type to authenticat */
107+
#define SCTP_AUTH_CHUNK SCTP_AUTH_CHUNK
108+
SCTP_HMAC_IDENT,
109+
#define SCTP_HMAC_IDENT SCTP_HMAC_IDENT
110+
SCTP_AUTH_KEY,
111+
#define SCTP_AUTH_KEY SCTP_AUTH_KEY
112+
SCTP_AUTH_ACTIVE_KEY,
113+
#define SCTP_AUTH_ACTIVE_KEY SCTP_AUTH_ACTIVE_KEY
114+
SCTP_AUTH_DELETE_KEY,
115+
#define SCTP_AUTH_DELETE_KEY SCTP_AUTH_DELETE_KEY
116+
SCTP_PEER_AUTH_CHUNKS, /* Read only */
117+
#define SCTP_PEER_AUTH_CHUNKS SCTP_PEER_AUTH_CHUNKS
118+
SCTP_LOCAL_AUTH_CHUNKS, /* Read only */
119+
#define SCTP_LOCAL_AUTH_CHUNKS SCTP_LOCAL_AUTH_CHUNKS
120+
106121

107122
/* Internal Socket Options. Some of the sctp library functions are
108123
* implemented using these socket options.
@@ -370,6 +385,19 @@ struct sctp_pdapi_event {
370385

371386
enum { SCTP_PARTIAL_DELIVERY_ABORTED=0, };
372387

388+
struct sctp_authkey_event {
389+
__u16 auth_type;
390+
__u16 auth_flags;
391+
__u32 auth_length;
392+
__u16 auth_keynumber;
393+
__u16 auth_altkeynumber;
394+
__u32 auth_indication;
395+
sctp_assoc_t auth_assoc_id;
396+
};
397+
398+
enum { SCTP_AUTH_NEWKEY = 0, };
399+
400+
373401
/*
374402
* Described in Section 7.3
375403
* Ancillary Data and Notification Interest Options
@@ -405,6 +433,7 @@ union sctp_notification {
405433
struct sctp_shutdown_event sn_shutdown_event;
406434
struct sctp_adaptation_event sn_adaptation_event;
407435
struct sctp_pdapi_event sn_pdapi_event;
436+
struct sctp_authkey_event sn_authkey_event;
408437
};
409438

410439
/* Section 5.3.1
@@ -421,6 +450,7 @@ enum sctp_sn_type {
421450
SCTP_SHUTDOWN_EVENT,
422451
SCTP_PARTIAL_DELIVERY_EVENT,
423452
SCTP_ADAPTATION_INDICATION,
453+
SCTP_AUTHENTICATION_EVENT,
424454
};
425455

426456
/* Notification error codes used to fill up the error fields in some
@@ -539,6 +569,54 @@ struct sctp_paddrparams {
539569
__u32 spp_flags;
540570
} __attribute__((packed, aligned(4)));
541571

572+
/*
573+
* 7.1.18. Add a chunk that must be authenticated (SCTP_AUTH_CHUNK)
574+
*
575+
* This set option adds a chunk type that the user is requesting to be
576+
* received only in an authenticated way. Changes to the list of chunks
577+
* will only effect future associations on the socket.
578+
*/
579+
struct sctp_authchunk {
580+
__u8 sauth_chunk;
581+
};
582+
583+
/*
584+
* 7.1.19. Get or set the list of supported HMAC Identifiers (SCTP_HMAC_IDENT)
585+
*
586+
* This option gets or sets the list of HMAC algorithms that the local
587+
* endpoint requires the peer to use.
588+
*/
589+
struct sctp_hmacalgo {
590+
__u16 shmac_num_idents;
591+
__u16 shmac_idents[];
592+
};
593+
594+
/*
595+
* 7.1.20. Set a shared key (SCTP_AUTH_KEY)
596+
*
597+
* This option will set a shared secret key which is used to build an
598+
* association shared key.
599+
*/
600+
struct sctp_authkey {
601+
sctp_assoc_t sca_assoc_id;
602+
__u16 sca_keynumber;
603+
__u16 sca_keylen;
604+
__u8 sca_key[];
605+
};
606+
607+
/*
608+
* 7.1.21. Get or set the active shared key (SCTP_AUTH_ACTIVE_KEY)
609+
*
610+
* This option will get or set the active shared key to be used to build
611+
* the association shared key.
612+
*/
613+
614+
struct sctp_authkeyid {
615+
sctp_assoc_t scact_assoc_id;
616+
__u16 scact_keynumber;
617+
};
618+
619+
542620
/* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
543621
*
544622
* This options will get or set the delayed ack timer. The time is set
@@ -607,6 +685,18 @@ struct sctp_status {
607685
struct sctp_paddrinfo sstat_primary;
608686
};
609687

688+
/*
689+
* 7.2.3. Get the list of chunks the peer requires to be authenticated
690+
* (SCTP_PEER_AUTH_CHUNKS)
691+
*
692+
* This option gets a list of chunks for a specified association that
693+
* the peer requires to be received authenticated only.
694+
*/
695+
struct sctp_authchunks {
696+
sctp_assoc_t gauth_assoc_id;
697+
uint8_t gauth_chunks[];
698+
};
699+
610700
/*
611701
* 8.3, 8.5 get all peer/local addresses in an association.
612702
* This parameter struct is used by SCTP_GET_PEER_ADDRS and

net/sctp/auth.c

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,3 +743,196 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc,
743743
if (free_key)
744744
sctp_auth_key_put(asoc_key);
745745
}
746+
747+
/* API Helpers */
748+
749+
/* Add a chunk to the endpoint authenticated chunk list */
750+
int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id)
751+
{
752+
struct sctp_chunks_param *p = ep->auth_chunk_list;
753+
__u16 nchunks;
754+
__u16 param_len;
755+
756+
/* If this chunk is already specified, we are done */
757+
if (__sctp_auth_cid(chunk_id, p))
758+
return 0;
759+
760+
/* Check if we can add this chunk to the array */
761+
param_len = ntohs(p->param_hdr.length);
762+
nchunks = param_len - sizeof(sctp_paramhdr_t);
763+
if (nchunks == SCTP_NUM_CHUNK_TYPES)
764+
return -EINVAL;
765+
766+
p->chunks[nchunks] = chunk_id;
767+
p->param_hdr.length = htons(param_len + 1);
768+
return 0;
769+
}
770+
771+
/* Add hmac identifires to the endpoint list of supported hmac ids */
772+
int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
773+
struct sctp_hmacalgo *hmacs)
774+
{
775+
int has_sha1 = 0;
776+
__u16 id;
777+
int i;
778+
779+
/* Scan the list looking for unsupported id. Also make sure that
780+
* SHA1 is specified.
781+
*/
782+
for (i = 0; i < hmacs->shmac_num_idents; i++) {
783+
id = hmacs->shmac_idents[i];
784+
785+
if (SCTP_AUTH_HMAC_ID_SHA1 == id)
786+
has_sha1 = 1;
787+
788+
if (!sctp_hmac_list[id].hmac_name)
789+
return -EOPNOTSUPP;
790+
}
791+
792+
if (!has_sha1)
793+
return -EINVAL;
794+
795+
memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0],
796+
hmacs->shmac_num_idents * sizeof(__u16));
797+
ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) +
798+
hmacs->shmac_num_idents * sizeof(__u16));
799+
return 0;
800+
}
801+
802+
/* Set a new shared key on either endpoint or association. If the
803+
* the key with a same ID already exists, replace the key (remove the
804+
* old key and add a new one).
805+
*/
806+
int sctp_auth_set_key(struct sctp_endpoint *ep,
807+
struct sctp_association *asoc,
808+
struct sctp_authkey *auth_key)
809+
{
810+
struct sctp_shared_key *cur_key = NULL;
811+
struct sctp_auth_bytes *key;
812+
struct list_head *sh_keys;
813+
int replace = 0;
814+
815+
/* Try to find the given key id to see if
816+
* we are doing a replace, or adding a new key
817+
*/
818+
if (asoc)
819+
sh_keys = &asoc->endpoint_shared_keys;
820+
else
821+
sh_keys = &ep->endpoint_shared_keys;
822+
823+
key_for_each(cur_key, sh_keys) {
824+
if (cur_key->key_id == auth_key->sca_keynumber) {
825+
replace = 1;
826+
break;
827+
}
828+
}
829+
830+
/* If we are not replacing a key id, we need to allocate
831+
* a shared key.
832+
*/
833+
if (!replace) {
834+
cur_key = sctp_auth_shkey_create(auth_key->sca_keynumber,
835+
GFP_KERNEL);
836+
if (!cur_key)
837+
return -ENOMEM;
838+
}
839+
840+
/* Create a new key data based on the info passed in */
841+
key = sctp_auth_create_key(auth_key->sca_keylen, GFP_KERNEL);
842+
if (!key)
843+
goto nomem;
844+
845+
memcpy(key->data, &auth_key->sca_key[0], auth_key->sca_keylen);
846+
847+
/* If we are replacing, remove the old keys data from the
848+
* key id. If we are adding new key id, add it to the
849+
* list.
850+
*/
851+
if (replace)
852+
sctp_auth_key_put(cur_key->key);
853+
else
854+
list_add(&cur_key->key_list, sh_keys);
855+
856+
cur_key->key = key;
857+
sctp_auth_key_hold(key);
858+
859+
return 0;
860+
nomem:
861+
if (!replace)
862+
sctp_auth_shkey_free(cur_key);
863+
864+
return -ENOMEM;
865+
}
866+
867+
int sctp_auth_set_active_key(struct sctp_endpoint *ep,
868+
struct sctp_association *asoc,
869+
__u16 key_id)
870+
{
871+
struct sctp_shared_key *key;
872+
struct list_head *sh_keys;
873+
int found = 0;
874+
875+
/* The key identifier MUST correst to an existing key */
876+
if (asoc)
877+
sh_keys = &asoc->endpoint_shared_keys;
878+
else
879+
sh_keys = &ep->endpoint_shared_keys;
880+
881+
key_for_each(key, sh_keys) {
882+
if (key->key_id == key_id) {
883+
found = 1;
884+
break;
885+
}
886+
}
887+
888+
if (!found)
889+
return -EINVAL;
890+
891+
if (asoc) {
892+
asoc->active_key_id = key_id;
893+
sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL);
894+
} else
895+
ep->active_key_id = key_id;
896+
897+
return 0;
898+
}
899+
900+
int sctp_auth_del_key_id(struct sctp_endpoint *ep,
901+
struct sctp_association *asoc,
902+
__u16 key_id)
903+
{
904+
struct sctp_shared_key *key;
905+
struct list_head *sh_keys;
906+
int found = 0;
907+
908+
/* The key identifier MUST NOT be the current active key
909+
* The key identifier MUST correst to an existing key
910+
*/
911+
if (asoc) {
912+
if (asoc->active_key_id == key_id)
913+
return -EINVAL;
914+
915+
sh_keys = &asoc->endpoint_shared_keys;
916+
} else {
917+
if (ep->active_key_id == key_id)
918+
return -EINVAL;
919+
920+
sh_keys = &ep->endpoint_shared_keys;
921+
}
922+
923+
key_for_each(key, sh_keys) {
924+
if (key->key_id == key_id) {
925+
found = 1;
926+
break;
927+
}
928+
}
929+
930+
if (!found)
931+
return -EINVAL;
932+
933+
/* Delete the shared key */
934+
list_del_init(&key->key_list);
935+
sctp_auth_shkey_free(key);
936+
937+
return 0;
938+
}

net/sctp/sm_statefuns.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3848,6 +3848,19 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
38483848
break;
38493849
}
38503850

3851+
if (asoc->active_key_id != ntohs(auth_hdr->shkey_id)) {
3852+
struct sctp_ulpevent *ev;
3853+
3854+
ev = sctp_ulpevent_make_authkey(asoc, ntohs(auth_hdr->shkey_id),
3855+
SCTP_AUTH_NEWKEY, GFP_ATOMIC);
3856+
3857+
if (!ev)
3858+
return -ENOMEM;
3859+
3860+
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
3861+
SCTP_ULPEVENT(ev));
3862+
}
3863+
38513864
return SCTP_DISPOSITION_CONSUME;
38523865
}
38533866

0 commit comments

Comments
 (0)