Commit c30f66b4 authored by David S. Miller's avatar David S. Miller

[IPSEC/CRYPTO]: Allocate work buffers instead of using kstack.

parent 63ba5a82
......@@ -108,6 +108,8 @@ struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
if (tfm == NULL)
goto out_put;
memset(tfm, 0, sizeof(*tfm));
if (alg->cra_ctxsize) {
tfm->crt_ctx = kmalloc(alg->cra_ctxsize, GFP_KERNEL);
if (tfm->crt_ctx == NULL)
......@@ -116,13 +118,24 @@ struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
tfm->__crt_alg = alg;
if (alg->cra_blocksize) {
tfm->crt_work_block = kmalloc(alg->cra_blocksize + 1,
GFP_KERNEL);
if (tfm->crt_work_block == NULL)
goto out_free_ctx;
}
if (crypto_init_flags(tfm, flags))
goto out_free_ctx;
goto out_free_work_block;
crypto_init_ops(tfm);
goto out;
out_free_work_block:
if (tfm->__crt_alg->cra_blocksize)
kfree(tfm->crt_work_block);
out_free_ctx:
if (tfm->__crt_alg->cra_ctxsize)
kfree(tfm->crt_ctx);
......@@ -140,6 +153,9 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
if (tfm->__crt_alg->cra_ctxsize)
kfree(tfm->crt_ctx);
if (tfm->__crt_alg->cra_blocksize)
kfree(tfm->crt_work_block);
if (crypto_tfm_alg_type(tfm) == CRYPTO_ALG_TYPE_CIPHER)
if (tfm->crt_cipher.cit_iv)
kfree(tfm->crt_cipher.cit_iv);
......
......@@ -35,14 +35,14 @@ void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen)
{
unsigned int i;
struct scatterlist tmp;
char ipad[crypto_tfm_alg_blocksize(tfm) + 1];
char *ipad = tfm->crt_work_block;
if (*keylen > crypto_tfm_alg_blocksize(tfm)) {
hash_key(tfm, key, *keylen);
*keylen = crypto_tfm_alg_digestsize(tfm);
}
memset(ipad, 0, sizeof(ipad));
memset(ipad, 0, crypto_tfm_alg_blocksize(tfm) + 1);
memcpy(ipad, key, *keylen);
for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
......@@ -67,7 +67,7 @@ void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
{
unsigned int i;
struct scatterlist tmp;
char opad[crypto_tfm_alg_blocksize(tfm) + 1];
char *opad = tfm->crt_work_block;
if (*keylen > crypto_tfm_alg_blocksize(tfm)) {
hash_key(tfm, key, *keylen);
......@@ -76,7 +76,7 @@ void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
crypto_digest_final(tfm, out);
memset(opad, 0, sizeof(opad));
memset(opad, 0, crypto_tfm_alg_blocksize(tfm) + 1);
memcpy(opad, key, *keylen);
for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
......
......@@ -157,6 +157,7 @@ struct compress_tfm {
struct crypto_tfm {
void *crt_ctx;
void *crt_work_block;
u32 crt_flags;
union {
......
......@@ -11,6 +11,7 @@ struct ah_data
{
u8 *key;
int key_len;
u8 *work_digest;
int digest_len;
void (*digest)(struct ah_data*,
......@@ -142,13 +143,12 @@ static void
ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data)
{
struct crypto_tfm *tfm = ahp->tfm;
char digest[crypto_tfm_alg_digestsize(tfm)];
memset(auth_data, 0, ahp->digest_len);
crypto_hmac_init(tfm, ahp->key, &ahp->key_len);
skb_ah_walk(skb, tfm);
crypto_hmac_final(tfm, ahp->key, &ahp->key_len, digest);
memcpy(auth_data, digest, ahp->digest_len);
crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_digest);
memcpy(auth_data, ahp->work_digest, ahp->digest_len);
}
int ah_output(struct sk_buff *skb)
......@@ -335,11 +335,19 @@ int ah_init_state(struct xfrm_state *x, void *args)
if (ahp == NULL)
return -ENOMEM;
memset(ahp, 0, sizeof(*ahp));
ahp->key = x->aalg->alg_key;
ahp->key_len = (x->aalg->alg_key_len+7)/8;
ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0);
if (!ahp->tfm)
goto error;
ahp->digest = ah_hmac_digest;
ahp->digest_len = 12;
ahp->work_digest = kmalloc(crypto_tfm_alg_digestsize(ahp->tfm),
GFP_KERNEL);
if (!ahp->work_digest)
goto error;
x->props.header_len = (12 + ahp->digest_len + 7)&~7;
if (x->props.mode)
x->props.header_len += 20;
......@@ -349,6 +357,8 @@ int ah_init_state(struct xfrm_state *x, void *args)
error:
if (ahp) {
if (ahp->work_digest)
kfree(ahp->work_digest);
if (ahp->tfm)
crypto_free_tfm(ahp->tfm);
kfree(ahp);
......@@ -360,6 +370,10 @@ void ah_destroy(struct xfrm_state *x)
{
struct ah_data *ahp = x->data;
if (ahp->work_digest) {
kfree(ahp->work_digest);
ahp->work_digest = NULL;
}
if (ahp->tfm) {
crypto_free_tfm(ahp->tfm);
ahp->tfm = NULL;
......
......@@ -34,6 +34,7 @@ struct esp_data
struct {
u8 *key; /* Key */
int key_len; /* Length of the key */
u8 *work_digest;
/* authlen is length of trailer containing auth token.
* If it is not zero it is assumed to be
* >= crypto_tfm_alg_digestsize(atfm) */
......@@ -187,7 +188,7 @@ esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
int len, u8 *auth_data)
{
struct crypto_tfm *tfm = esp->auth.tfm;
char digest[crypto_tfm_alg_digestsize(tfm)];
char *digest = esp->auth.work_digest;
memset(auth_data, 0, esp->auth.authlen);
crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len);
......@@ -579,6 +580,10 @@ void esp_destroy(struct xfrm_state *x)
crypto_free_tfm(esp->auth.tfm);
esp->auth.tfm = NULL;
}
if (esp->auth.work_digest) {
kfree(esp->auth.work_digest);
esp->auth.work_digest = NULL;
}
}
int esp_init_state(struct xfrm_state *x, void *args)
......@@ -596,6 +601,8 @@ int esp_init_state(struct xfrm_state *x, void *args)
if (esp == NULL)
return -ENOMEM;
memset(esp, 0, sizeof(*esp));
if (x->aalg) {
esp->auth.key = x->aalg->alg_key;
esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
......@@ -604,6 +611,9 @@ int esp_init_state(struct xfrm_state *x, void *args)
goto error;
esp->auth.digest = esp_hmac_digest;
esp->auth.authlen = crypto_tfm_alg_digestsize(esp->auth.tfm);
esp->auth.work_digest = kmalloc(esp->auth.authlen, GFP_KERNEL);
if (!esp->auth.work_digest)
goto error;
}
esp->conf.key = x->ealg->alg_key;
esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
......@@ -628,6 +638,8 @@ int esp_init_state(struct xfrm_state *x, void *args)
if (esp) {
if (esp->auth.tfm)
crypto_free_tfm(esp->auth.tfm);
if (esp->auth.work_digest)
kfree(esp->auth.work_digest);
if (esp->conf.tfm)
crypto_free_tfm(esp->conf.tfm);
kfree(esp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment