esph->seq_no = htonl(++x->replay.oseq);
xfrm_aevent_doreplay(x);
- if (esp->conf.ivlen)
+ if (esp->conf.ivlen) {
+ if (unlikely(!esp->conf.ivinitted)) {
+ get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
+ esp->conf.ivinitted = 1;
+ }
crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
+ }
do {
struct scatterlist *sg = &esp->sgbuf[0];
}
if (esp->auth.icv_full_len) {
- esp->auth.icv(esp, skb, (u8*)esph-skb->data,
- sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail);
- pskb_put(skb, trailer, alen);
+ err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
+ sizeof(*esph) + esp->conf.ivlen + clen);
+ memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
}
error:
/* If integrity check is required, do this. */
if (esp->auth.icv_full_len) {
- u8 sum[esp->auth.icv_full_len];
- u8 sum1[alen];
+ u8 sum[alen];
- esp->auth.icv(esp, skb, 0, skb->len-alen, sum);
+ ret = esp_mac_digest(esp, skb, 0, skb->len - alen);
+ if (ret)
+ goto out;
- if (skb_copy_bits(skb, skb->len-alen, sum1, alen))
+ if (skb_copy_bits(skb, skb->len - alen, sum, alen))
BUG();
- if (unlikely(memcmp(sum, sum1, alen))) {
+ if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
x->stats.integrity_failed++;
ret = -EINVAL;
goto out;
struct esp_data *esp = x->data;
u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
- if (x->props.mode) {
+ if (x->props.mode == XFRM_MODE_TUNNEL) {
mtu = ALIGN(mtu + 2, blksize);
} else {
/* The worst case. */
esp->conf.tfm = NULL;
kfree(esp->conf.ivec);
esp->conf.ivec = NULL;
- crypto_free_tfm(esp->auth.tfm);
+ crypto_free_hash(esp->auth.tfm);
esp->auth.tfm = NULL;
kfree(esp->auth.work_icv);
esp->auth.work_icv = NULL;
if (x->aalg) {
struct xfrm_algo_desc *aalg_desc;
+ struct crypto_hash *hash;
esp->auth.key = x->aalg->alg_key;
esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
- esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
- if (esp->auth.tfm == NULL)
+ hash = crypto_alloc_hash(x->aalg->alg_name, 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(hash))
+ goto error;
+
+ esp->auth.tfm = hash;
+ if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len))
goto error;
- esp->auth.icv = esp_hmac_digest;
aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
BUG_ON(!aalg_desc);
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
- crypto_tfm_alg_digestsize(esp->auth.tfm)) {
- printk(KERN_INFO "ESP: %s digestsize %u != %hu\n",
- x->aalg->alg_name,
- crypto_tfm_alg_digestsize(esp->auth.tfm),
- aalg_desc->uinfo.auth.icv_fullbits/8);
- goto error;
+ crypto_hash_digestsize(hash)) {
+ NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
+ x->aalg->alg_name,
+ crypto_hash_digestsize(hash),
+ aalg_desc->uinfo.auth.icv_fullbits/8);
+ goto error;
}
esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
if (unlikely(esp->conf.ivec == NULL))
goto error;
- get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
+ esp->conf.ivinitted = 0;
}
if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len))
goto error;
x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
- if (x->props.mode)
+ if (x->props.mode == XFRM_MODE_TUNNEL)
x->props.header_len += sizeof(struct ipv6hdr);
x->data = esp;
return 0;
.destructor = esp6_destroy,
.get_max_size = esp6_get_max_size,
.input = esp6_input,
- .output = esp6_output
+ .output = esp6_output,
+ .hdr_offset = xfrm6_find_1stfragopt,
};
static struct inet6_protocol esp6_protocol = {