Received: with ECARTIS (v1.0.0; list netdev); Thu, 30 Dec 2004 00:47:49 -0800 (PST) Received: from smtp.knology.net (smtp.knology.net [24.214.63.101]) by oss.sgi.com (8.13.0/8.13.0) with SMTP id iBU8kNWf024566 for ; Thu, 30 Dec 2004 00:46:44 -0800 Received: (qmail 31805 invoked by uid 0); 30 Dec 2004 08:54:55 -0000 Received: from user-69-1-45-93.knology.net (HELO ori.thedillows.org) (69.1.45.93) by smtp7.knology.net with SMTP; 30 Dec 2004 08:54:55 -0000 Received: from ori.thedillows.org (localhost [127.0.0.1]) by ori.thedillows.org (8.13.1/8.13.1) with ESMTP id iBU8masC009795; Thu, 30 Dec 2004 03:48:36 -0500 Received: (from root@localhost) by ori.thedillows.org (8.13.1/8.13.1/Submit) id iBU8manA009794; Thu, 30 Dec 2004 03:48:36 -0500 Date: Thu, 30 Dec 2004 03:48:36 -0500 To: netdev@oss.sgi.com Cc: linux-kernel@vger.kernel.org, dave@thedillows.org From: David Dillow Subject: [RFC 2.6.10 10/22] AH, ESP: Add offloading of outbound packets Message-Id: <20041230035000.19@ori.thedillows.org> References: <20041230035000.18@ori.thedillows.org> X-Virus-Scanned: ClamAV 0.80/638/Tue Dec 21 14:41:34 2004 clamav-milter version 0.80j on 127.0.0.1 X-Virus-Status: Clean X-archive-position: 13209 X-ecartis-version: Ecartis v1.0.0 Sender: netdev-bounce@oss.sgi.com Errors-to: netdev-bounce@oss.sgi.com X-original-sender: dave@thedillows.org Precedence: bulk X-list: netdev # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/12/30 00:44:50-05:00 dave@thedillows.org # Add crypto processing for outbound AH and ESP xfrms (IPv4). # # Signed-off-by: David Dillow # # net/ipv4/esp4.c # 2004/12/30 00:44:32-05:00 dave@thedillows.org +35 -21 # Add crypto offload for outbound ESP (IPv4) xfrms. Note that we always # generate a random IV, as we are not guaranteed to have any state in # the software crypto engine (we may have always been offloaded), and # we cannot rely on secure IV generation by the NIC driver/hw. # # Signed-off-by: David Dillow # # net/ipv4/ah4.c # 2004/12/30 00:44:32-05:00 dave@thedillows.org +31 -21 # Add crypto offload for outbound AH (IPv4) xfrms. Note that the NIC # driver/hw is responsible for zeroing the mutable IP header fields. # # Signed-off-by: David Dillow # diff -Nru a/net/ipv4/ah4.c b/net/ipv4/ah4.c --- a/net/ipv4/ah4.c 2004-12-30 01:10:14 -05:00 +++ b/net/ipv4/ah4.c 2004-12-30 01:10:14 -05:00 @@ -83,31 +83,41 @@ ah->spi = x->id.spi; ah->seq_no = htonl(x->replay.oseq + 1); - iph->tos = top_iph->tos; - iph->ttl = top_iph->ttl; - iph->frag_off = top_iph->frag_off; - - if (top_iph->ihl != 5) { - iph->daddr = top_iph->daddr; - memcpy(iph+1, top_iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); - err = ip_clear_mutable_options(top_iph, &top_iph->daddr); - if (err) + if (dst->xfrm_offload) { + err = -ENOMEM; + xfrm_offload_hold(dst->xfrm_offload); + if (skb_push_xfrm_offload(skb, dst->xfrm_offload)) { + xfrm_offload_release(dst->xfrm_offload); goto error; - } + } + } else { + /* Not offloaded, manually calculate the auth hash */ + iph->tos = top_iph->tos; + iph->ttl = top_iph->ttl; + iph->frag_off = top_iph->frag_off; + + if (top_iph->ihl != 5) { + iph->daddr = top_iph->daddr; + memcpy(iph+1, top_iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); + err = ip_clear_mutable_options(top_iph, &top_iph->daddr); + if (err) + goto error; + } - top_iph->tos = 0; - top_iph->frag_off = 0; - top_iph->ttl = 0; - top_iph->check = 0; + top_iph->tos = 0; + top_iph->frag_off = 0; + top_iph->ttl = 0; + top_iph->check = 0; - ahp->icv(ahp, skb, ah->auth_data); + ahp->icv(ahp, skb, ah->auth_data); - top_iph->tos = iph->tos; - top_iph->ttl = iph->ttl; - top_iph->frag_off = iph->frag_off; - if (top_iph->ihl != 5) { - top_iph->daddr = iph->daddr; - memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); + top_iph->tos = iph->tos; + top_iph->ttl = iph->ttl; + top_iph->frag_off = iph->frag_off; + if (top_iph->ihl != 5) { + top_iph->daddr = iph->daddr; + memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); + } } /* Delay incrementing the replay sequence until we know we're going diff -Nru a/net/ipv4/esp4.c b/net/ipv4/esp4.c --- a/net/ipv4/esp4.c 2004-12-30 01:10:14 -05:00 +++ b/net/ipv4/esp4.c 2004-12-30 01:10:14 -05:00 @@ -98,33 +98,47 @@ esph->spi = x->id.spi; esph->seq_no = htonl(++x->replay.oseq); - if (esp->conf.ivlen) - crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + if (dst->xfrm_offload) { + xfrm_offload_hold(dst->xfrm_offload); + if (skb_push_xfrm_offload(skb, dst->xfrm_offload)) { + xfrm_offload_release(dst->xfrm_offload); + goto error; + } + + if (esp->conf.ivlen) + get_random_bytes(esph->enc_data, esp->conf.ivlen); + } else { + if (esp->conf.ivlen) + crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + + do { + struct scatterlist *sg = &esp->sgbuf[0]; - do { - struct scatterlist *sg = &esp->sgbuf[0]; + if (unlikely(nfrags > ESP_NUM_FAST_SG)) { + sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); + if (!sg) + goto error; + } + skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); + crypto_cipher_encrypt(tfm, sg, sg, clen); + if (unlikely(sg != &esp->sgbuf[0])) + kfree(sg); + } while (0); - if (unlikely(nfrags > ESP_NUM_FAST_SG)) { - sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); - if (!sg) - goto error; + if (esp->conf.ivlen) { + memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + } + + if (esp->auth.icv_full_len) { + esp->auth.icv(esp, skb, (u8*)esph-skb->data, + sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); } - skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); - crypto_cipher_encrypt(tfm, sg, sg, clen); - if (unlikely(sg != &esp->sgbuf[0])) - kfree(sg); - } while (0); - - if (esp->conf.ivlen) { - memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); - crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); } - if (esp->auth.icv_full_len) { - esp->auth.icv(esp, skb, (u8*)esph-skb->data, - sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); + /* Need to account for auth data, offloading or not... */ + if (esp->auth.icv_full_len) pskb_put(skb, trailer, alen); - } ip_send_check(top_iph);