aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-09-16 22:32:45 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:31 -0400
commit4cd57c8078fae0a4b1bf421191e94626d0cba92a (patch)
treee17a54c65a7859b6283a341e0124d200da64ee3a /net
parent730fc3d05cd4ba4c9ce2de91f3d43349e95dbbf5 (diff)
[SCTP]: Enable the sending of the AUTH chunk.
SCTP-AUTH, Section 6.2: Endpoints MUST send all requested chunks authenticated where this has been requested by the peer. The other chunks MAY be sent authenticated or not. If endpoint pair shared keys are used, one of them MUST be selected for authentication. To send chunks in an authenticated way, the sender MUST include these chunks after an AUTH chunk. This means that a sender MUST bundle chunks in order to authenticate them. If the endpoint has no endpoint pair shared key for the peer, it MUST use Shared Key Identifier 0 with an empty endpoint pair shared key. If there are multiple endpoint shared keys the sender selects one and uses the corresponding Shared Key Identifier Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sctp/chunk.c12
-rw-r--r--net/sctp/output.c131
-rw-r--r--net/sctp/sm_make_chunk.c39
3 files changed, 155 insertions, 27 deletions
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 77fb7b06a9c4..619d0f2dee51 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -194,6 +194,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
194 194
195 max = asoc->frag_point; 195 max = asoc->frag_point;
196 196
197 /* If the the peer requested that we authenticate DATA chunks
198 * we need to accound for bundling of the AUTH chunks along with
199 * DATA.
200 */
201 if (sctp_auth_send_cid(SCTP_CID_DATA, asoc)) {
202 struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc);
203
204 if (hmac_desc)
205 max -= WORD_ROUND(sizeof(sctp_auth_chunk_t) +
206 hmac_desc->hmac_len);
207 }
208
197 whole = 0; 209 whole = 0;
198 first_len = max; 210 first_len = max;
199 211
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 49b9f5f031a4..847639d542c0 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -80,6 +80,7 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet,
80 packet->has_cookie_echo = 0; 80 packet->has_cookie_echo = 0;
81 packet->has_sack = 0; 81 packet->has_sack = 0;
82 packet->has_auth = 0; 82 packet->has_auth = 0;
83 packet->has_data = 0;
83 packet->ipfragok = 0; 84 packet->ipfragok = 0;
84 packet->auth = NULL; 85 packet->auth = NULL;
85 86
@@ -124,6 +125,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
124 packet->has_cookie_echo = 0; 125 packet->has_cookie_echo = 0;
125 packet->has_sack = 0; 126 packet->has_sack = 0;
126 packet->has_auth = 0; 127 packet->has_auth = 0;
128 packet->has_data = 0;
127 packet->ipfragok = 0; 129 packet->ipfragok = 0;
128 packet->malloced = 0; 130 packet->malloced = 0;
129 packet->auth = NULL; 131 packet->auth = NULL;
@@ -185,6 +187,39 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
185 return retval; 187 return retval;
186} 188}
187 189
190/* Try to bundle an auth chunk into the packet. */
191static sctp_xmit_t sctp_packet_bundle_auth(struct sctp_packet *pkt,
192 struct sctp_chunk *chunk)
193{
194 struct sctp_association *asoc = pkt->transport->asoc;
195 struct sctp_chunk *auth;
196 sctp_xmit_t retval = SCTP_XMIT_OK;
197
198 /* if we don't have an association, we can't do authentication */
199 if (!asoc)
200 return retval;
201
202 /* See if this is an auth chunk we are bundling or if
203 * auth is already bundled.
204 */
205 if (chunk->chunk_hdr->type == SCTP_CID_AUTH || pkt->auth)
206 return retval;
207
208 /* if the peer did not request this chunk to be authenticated,
209 * don't do it
210 */
211 if (!chunk->auth)
212 return retval;
213
214 auth = sctp_make_auth(asoc);
215 if (!auth)
216 return retval;
217
218 retval = sctp_packet_append_chunk(pkt, auth);
219
220 return retval;
221}
222
188/* Try to bundle a SACK with the packet. */ 223/* Try to bundle a SACK with the packet. */
189static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, 224static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt,
190 struct sctp_chunk *chunk) 225 struct sctp_chunk *chunk)
@@ -231,12 +266,17 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
231 SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet, 266 SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet,
232 chunk); 267 chunk);
233 268
234 retval = sctp_packet_bundle_sack(packet, chunk); 269 /* Try to bundle AUTH chunk */
235 psize = packet->size; 270 retval = sctp_packet_bundle_auth(packet, chunk);
271 if (retval != SCTP_XMIT_OK)
272 goto finish;
236 273
274 /* Try to bundle SACK chunk */
275 retval = sctp_packet_bundle_sack(packet, chunk);
237 if (retval != SCTP_XMIT_OK) 276 if (retval != SCTP_XMIT_OK)
238 goto finish; 277 goto finish;
239 278
279 psize = packet->size;
240 pmtu = ((packet->transport->asoc) ? 280 pmtu = ((packet->transport->asoc) ?
241 (packet->transport->asoc->pathmtu) : 281 (packet->transport->asoc->pathmtu) :
242 (packet->transport->pathmtu)); 282 (packet->transport->pathmtu));
@@ -245,10 +285,16 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
245 285
246 /* Decide if we need to fragment or resubmit later. */ 286 /* Decide if we need to fragment or resubmit later. */
247 if (too_big) { 287 if (too_big) {
248 /* Both control chunks and data chunks with TSNs are 288 /* It's OK to fragmet at IP level if any one of the following
249 * non-fragmentable. 289 * is true:
290 * 1. The packet is empty (meaning this chunk is greater
291 * the MTU)
292 * 2. The chunk we are adding is a control chunk
293 * 3. The packet doesn't have any data in it yet and data
294 * requires authentication.
250 */ 295 */
251 if (sctp_packet_empty(packet) || !sctp_chunk_is_data(chunk)) { 296 if (sctp_packet_empty(packet) || !sctp_chunk_is_data(chunk) ||
297 (!packet->has_data && chunk->auth)) {
252 /* We no longer do re-fragmentation. 298 /* We no longer do re-fragmentation.
253 * Just fragment at the IP layer, if we 299 * Just fragment at the IP layer, if we
254 * actually hit this condition 300 * actually hit this condition
@@ -270,16 +316,31 @@ append:
270 /* DATA is a special case since we must examine both rwnd and cwnd 316 /* DATA is a special case since we must examine both rwnd and cwnd
271 * before we send DATA. 317 * before we send DATA.
272 */ 318 */
273 if (sctp_chunk_is_data(chunk)) { 319 switch (chunk->chunk_hdr->type) {
320 case SCTP_CID_DATA:
274 retval = sctp_packet_append_data(packet, chunk); 321 retval = sctp_packet_append_data(packet, chunk);
275 /* Disallow SACK bundling after DATA. */ 322 /* Disallow SACK bundling after DATA. */
276 packet->has_sack = 1; 323 packet->has_sack = 1;
324 /* Disallow AUTH bundling after DATA */
325 packet->has_auth = 1;
326 /* Let it be knows that packet has DATA in it */
327 packet->has_data = 1;
277 if (SCTP_XMIT_OK != retval) 328 if (SCTP_XMIT_OK != retval)
278 goto finish; 329 goto finish;
279 } else if (SCTP_CID_COOKIE_ECHO == chunk->chunk_hdr->type) 330 break;
331 case SCTP_CID_COOKIE_ECHO:
280 packet->has_cookie_echo = 1; 332 packet->has_cookie_echo = 1;
281 else if (SCTP_CID_SACK == chunk->chunk_hdr->type) 333 break;
334
335 case SCTP_CID_SACK:
282 packet->has_sack = 1; 336 packet->has_sack = 1;
337 break;
338
339 case SCTP_CID_AUTH:
340 packet->has_auth = 1;
341 packet->auth = chunk;
342 break;
343 }
283 344
284 /* It is OK to send this chunk. */ 345 /* It is OK to send this chunk. */
285 list_add_tail(&chunk->list, &packet->chunk_list); 346 list_add_tail(&chunk->list, &packet->chunk_list);
@@ -307,6 +368,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
307 int padding; /* How much padding do we need? */ 368 int padding; /* How much padding do we need? */
308 __u8 has_data = 0; 369 __u8 has_data = 0;
309 struct dst_entry *dst = tp->dst; 370 struct dst_entry *dst = tp->dst;
371 unsigned char *auth = NULL; /* pointer to auth in skb data */
372 __u32 cksum_buf_len = sizeof(struct sctphdr);
310 373
311 SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet); 374 SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
312 375
@@ -360,16 +423,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
360 sh->vtag = htonl(packet->vtag); 423 sh->vtag = htonl(packet->vtag);
361 sh->checksum = 0; 424 sh->checksum = 0;
362 425
363 /* 2) Calculate the Adler-32 checksum of the whole packet,
364 * including the SCTP common header and all the
365 * chunks.
366 *
367 * Note: Adler-32 is no longer applicable, as has been replaced
368 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
369 */
370 if (!(dst->dev->features & NETIF_F_NO_CSUM))
371 crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
372
373 /** 426 /**
374 * 6.10 Bundling 427 * 6.10 Bundling
375 * 428 *
@@ -420,14 +473,16 @@ int sctp_packet_transmit(struct sctp_packet *packet)
420 if (padding) 473 if (padding)
421 memset(skb_put(chunk->skb, padding), 0, padding); 474 memset(skb_put(chunk->skb, padding), 0, padding);
422 475
423 if (dst->dev->features & NETIF_F_NO_CSUM) 476 /* if this is the auth chunk that we are adding,
424 memcpy(skb_put(nskb, chunk->skb->len), 477 * store pointer where it will be added and put
478 * the auth into the packet.
479 */
480 if (chunk == packet->auth)
481 auth = skb_tail_pointer(nskb);
482
483 cksum_buf_len += chunk->skb->len;
484 memcpy(skb_put(nskb, chunk->skb->len),
425 chunk->skb->data, chunk->skb->len); 485 chunk->skb->data, chunk->skb->len);
426 else
427 crc32 = sctp_update_copy_cksum(skb_put(nskb,
428 chunk->skb->len),
429 chunk->skb->data,
430 chunk->skb->len, crc32);
431 486
432 SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n", 487 SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
433 "*** Chunk", chunk, 488 "*** Chunk", chunk,
@@ -449,9 +504,31 @@ int sctp_packet_transmit(struct sctp_packet *packet)
449 sctp_chunk_free(chunk); 504 sctp_chunk_free(chunk);
450 } 505 }
451 506
452 /* Perform final transformation on checksum. */ 507 /* SCTP-AUTH, Section 6.2
453 if (!(dst->dev->features & NETIF_F_NO_CSUM)) 508 * The sender MUST calculate the MAC as described in RFC2104 [2]
509 * using the hash function H as described by the MAC Identifier and
510 * the shared association key K based on the endpoint pair shared key
511 * described by the shared key identifier. The 'data' used for the
512 * computation of the AUTH-chunk is given by the AUTH chunk with its
513 * HMAC field set to zero (as shown in Figure 6) followed by all
514 * chunks that are placed after the AUTH chunk in the SCTP packet.
515 */
516 if (auth)
517 sctp_auth_calculate_hmac(asoc, nskb,
518 (struct sctp_auth_chunk *)auth,
519 GFP_ATOMIC);
520
521 /* 2) Calculate the Adler-32 checksum of the whole packet,
522 * including the SCTP common header and all the
523 * chunks.
524 *
525 * Note: Adler-32 is no longer applicable, as has been replaced
526 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
527 */
528 if (!(dst->dev->features & NETIF_F_NO_CSUM)) {
529 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
454 crc32 = sctp_end_cksum(crc32); 530 crc32 = sctp_end_cksum(crc32);
531 }
455 532
456 /* 3) Put the resultant value into the checksum field in the 533 /* 3) Put the resultant value into the checksum field in the
457 * common header, and leave the rest of the bits unchanged. 534 * common header, and leave the rest of the bits unchanged.
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 4c02875786ac..fa2ba543183d 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1111,6 +1111,41 @@ nodata:
1111 return retval; 1111 return retval;
1112} 1112}
1113 1113
1114struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc)
1115{
1116 struct sctp_chunk *retval;
1117 struct sctp_hmac *hmac_desc;
1118 struct sctp_authhdr auth_hdr;
1119 __u8 *hmac;
1120
1121 /* Get the first hmac that the peer told us to use */
1122 hmac_desc = sctp_auth_asoc_get_hmac(asoc);
1123 if (unlikely(!hmac_desc))
1124 return NULL;
1125
1126 retval = sctp_make_chunk(asoc, SCTP_CID_AUTH, 0,
1127 hmac_desc->hmac_len + sizeof(sctp_authhdr_t));
1128 if (!retval)
1129 return NULL;
1130
1131 auth_hdr.hmac_id = htons(hmac_desc->hmac_id);
1132 auth_hdr.shkey_id = htons(asoc->active_key_id);
1133
1134 retval->subh.auth_hdr = sctp_addto_chunk(retval, sizeof(sctp_authhdr_t),
1135 &auth_hdr);
1136
1137 hmac = skb_put(retval->skb, hmac_desc->hmac_len);
1138 memset(hmac, 0, hmac_desc->hmac_len);
1139
1140 /* Adjust the chunk header to include the empty MAC */
1141 retval->chunk_hdr->length =
1142 htons(ntohs(retval->chunk_hdr->length) + hmac_desc->hmac_len);
1143 retval->chunk_end = skb_tail_pointer(retval->skb);
1144
1145 return retval;
1146}
1147
1148
1114/******************************************************************** 1149/********************************************************************
1115 * 2nd Level Abstractions 1150 * 2nd Level Abstractions
1116 ********************************************************************/ 1151 ********************************************************************/
@@ -1225,6 +1260,10 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
1225 retval->chunk_hdr = chunk_hdr; 1260 retval->chunk_hdr = chunk_hdr;
1226 retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr); 1261 retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr);
1227 1262
1263 /* Determine if the chunk needs to be authenticated */
1264 if (sctp_auth_send_cid(type, asoc))
1265 retval->auth = 1;
1266
1228 /* Set the skb to the belonging sock for accounting. */ 1267 /* Set the skb to the belonging sock for accounting. */
1229 skb->sk = sk; 1268 skb->sk = sk;
1230 1269