From: Andreas Steffen <andreas.steffen@strongswan.org>
To: linux-crypto@vger.kernel.org
Subject: Linux 2.6.28 and AEAD initialization
Date: Wed, 21 Jan 2009 03:29:48 +0100 [thread overview]
Message-ID: <4976889C.3090602@strongswan.org> (raw)
Hi,
with the Linux 2.6.28 kernel the first time xfrm_user.c:xfrm_add_sa()
is called with either "rfc4106(gcm(aes))" or "rfc4309(ccm(aes))",
an EEXIST error is returned and the installation of the IPsec SA fails.
A detailed analysis of the function calls (see trace added below) shows
that aead.c:crypto_lookup_aead() first loads
name : rfc4106(gcm(aes))
driver : rfc4106(gcm_base(ctr(aes-generic)))
module : kernel
priority : 100
refcnt : 1
selftest : passed
type : nivaead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
Because of type=nivaead
if (alg->cra_type == &crypto_aead_type)
return alg;
crypto_lookup_aead() does not return the algorithm and falls through
to the statement
return ERR_PTR(crypto_nivaead_default(alg, type, mask));
which makes another call to algapi.c;__crypto_register_alg().
Because the driver has already been installed
ret = -EEXIST;
...
if (crypto_is_larval(q)) {
if (!strcmp(alg->cra_driver_name, q->cra_driver_name))
goto err;
continue;
}
__crypto_register_alg() exits with the EEXIST error code.
The second time around the type=aead algorithm is additionally loaded
name : rfc4106(gcm(aes))
driver : rfc4106(gcm_base(ctr(aes-generic)))
module : kernel
priority : 100
refcnt : 1
selftest : passed
type : aead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
name : rfc4106(gcm(aes))
driver : rfc4106(gcm_base(ctr(aes-generic)))
module : kernel
priority : 100
refcnt : 1
selftest : passed
type : nivaead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
and the IPsec SAs can be set up successfully.
With the Linux 2.6.27.10 and earlier kernels the aead type is
loaded right at the beginning and no problems occur:
name : rfc4106(gcm(aes))
driver : rfc4106(gcm_base(ctr(aes-asm)))
module : kernel
priority : 200
refcnt : 1
type : aead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
name : rfc4106(gcm(aes))
driver : rfc4106(gcm_base(ctr(aes-asm)))
module : kernel
priority : 200
refcnt : 1
type : nivaead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
Best regards
Andreas
Trace of function calls returning EEXIST:
-----------------------------------------------------------------------------
net/xfrm/xfrm_user.c:xfrm_add_sa()
{
x = xfrm_state_construct(p, attrs, &err);
if (!x)
return err;
}
-----------------------------------------------------------------------------
net/xfrm/xfrm_user.c:xfrm_state_construct()
{
err = xfrm_init_state(x);
if (err)
goto error;
...
error:
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
error_no_put:
*errp = err;
return NULL;
}
-----------------------------------------------------------------------------
net/xfrm/xfrm_state.c:xfrm_init_state()
{
x->type = xfrm_get_type(x->id.proto, family);
if (x->type == NULL)
goto error;
err = x->type->init_state(x);
if (err)
goto error;
...
error:
return err;
}
-----------------------------------------------------------------------------
linux/net/xfrm.h:struct xfrm_type
{
char *description;
struct module *owner;
__u8 proto;
__u8 flags;
#define XFRM_TYPE_NON_FRAGMENT 1
#define XFRM_TYPE_REPLAY_PROT 2
#define XFRM_TYPE_LOCAL_COADDR 4
#define XFRM_TYPE_REMOTE_COADDR 8
int (*init_state)(struct xfrm_state *x);
void (*destructor)(struct xfrm_state *);
int (*input)(struct xfrm_state *, struct sk_buff *skb);
int (*output)(struct xfrm_state *, struct sk_buff *pskb);
int (*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *);
int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
/* Estimate maximal size of result of transformation of a dgram */
u32 (*get_mtu)(struct xfrm_state *, int size);
};
-----------------------------------------------------------------------------
net/ipv4/esp4.c:esp_init_state()
{
if (x->aead)
err = esp_init_aead(x);
}
else
err = esp_init_authenc(x);
if (err)
goto error;
}
-----------------------------------------------------------------------------
net/ipv4/esp4.c:esp_init_aead()
{
struct esp_data *esp = x->data;
struct crypto_aead *aead;
int err;
aead = crypto_alloc_aead(x->aead->alg_name, 0, 0);
err = PTR_ERR(aead);
if (IS_ERR(aead))
goto error;
error:
return err;
}
-----------------------------------------------------------------------------
crypto/aead.c:crypto_alloc_aead()
{
alg = crypto_lookup_aead(alg_name, type, mask);
if (IS_ERR(alg)) {
err = PTR_ERR(alg);
goto err;
}
err:
if (err != -EAGAIN)
break;
if (signal_pending(current)) {
err = -EINTR;
break;
}
}
return ERR_PTR(err);
}
-----------------------------------------------------------------------------
crypto/aead.c:crypto_lookup_aead()
{
struct crypto_alg *alg;
alg = crypto_alg_mod_lookup(name, type, mask);
if (IS_ERR(alg))
return alg;
/* after the first call alg->cra_type is &crypto_nivaead_type */
if (alg->cra_type == &crypto_aead_type)
return alg;
if (!alg->cra_aead.ivsize)
return alg;
return ERR_PTR(crypto_nivaead_default(alg, type, mask));
}
-----------------------------------------------------------------------------
crypto/aead.c:crypto_nivaead_default()
{
if ((err = crypto_register_instance(tmpl, inst))) {
tmpl->free(inst);
goto put_tmpl;
}
/* Redo the lookup to use the instance we just registered. */
err = -EAGAIN;
put_tmpl:
crypto_tmpl_put(tmpl);
kill_larval:
crypto_larval_kill(larval);
drop_larval:
crypto_mod_put(larval);
out:
crypto_mod_put(alg);
return err;
}
-----------------------------------------------------------------------------
crypto/algapi.c:crypto_register_instance()
{
larval = __crypto_register_alg(&inst->alg);
if (IS_ERR(larval))
goto unlock;
hlist_add_head(&inst->list, &tmpl->instances);
inst->tmpl = tmpl;
unlock:
up_write(&crypto_alg_sem);
err = PTR_ERR(larval);
if (IS_ERR(larval))
goto err;
crypto_wait_for_test(larval);
err = 0;
err:
return err;
}
-----------------------------------------------------------------------------
crypto/algapi.c:__crypto_register_alg()
{
ret = -EEXIST;
...
if (crypto_is_larval(q)) {
if (!strcmp(alg->cra_driver_name, q->cra_driver_name))
goto err;
continue;
}
}
Uff!
======================================================================
Andreas Steffen andreas.steffen@strongswan.org
strongSwan - the Linux VPN Solution! www.strongswan.org
Institute for Internet Technologies and Applications
University of Applied Sciences Rapperswil
CH-8640 Rapperswil (Switzerland)
===========================================================[ITA-HSR]==
next reply other threads:[~2009-01-21 2:52 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-21 2:29 Andreas Steffen [this message]
2009-01-27 7:01 ` Linux 2.6.28 and AEAD initialization Herbert Xu
2009-01-28 0:18 ` Andreas Steffen
2009-01-28 3:10 ` Herbert Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4976889C.3090602@strongswan.org \
--to=andreas.steffen@strongswan.org \
--cc=linux-crypto@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.