summaryrefslogtreecommitdiff
path: root/crypto/af_alg.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/af_alg.c')
-rw-r--r--crypto/af_alg.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 8bd288d2b089..325892ac45c1 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -202,13 +202,17 @@ unlock:
return err;
}
-static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen)
+static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen,
+ int (*setkey)(void *private, const u8 *key,
+ unsigned int keylen))
{
struct alg_sock *ask = alg_sk(sk);
- const struct af_alg_type *type = ask->type;
u8 *key;
int err;
+ if (!setkey)
+ return -ENOPROTOOPT;
+
key = sock_kmalloc(sk, keylen, GFP_KERNEL);
if (!key)
return -ENOMEM;
@@ -217,8 +221,7 @@ static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen)
if (copy_from_sockptr(key, ukey, keylen))
goto out;
- err = type->setkey(ask->private, key, keylen);
-
+ err = setkey(ask->private, key, keylen);
out:
sock_kzfree_s(sk, key, keylen);
@@ -243,18 +246,23 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
if (level != SOL_ALG || !type)
goto unlock;
+ if (sock->state == SS_CONNECTED)
+ goto unlock;
+
switch (optname) {
case ALG_SET_KEY:
- if (sock->state == SS_CONNECTED)
- goto unlock;
- if (!type->setkey)
- goto unlock;
-
- err = alg_setkey(sk, optval, optlen);
+ err = alg_setkey(sk, optval, optlen, type->setkey);
+ break;
+ case ALG_SET_PUBKEY:
+ err = alg_setkey(sk, optval, optlen, type->setpubkey);
+ break;
+ case ALG_SET_DH_PARAMETERS:
+ err = alg_setkey(sk, optval, optlen, type->dhparams);
+ break;
+ case ALG_SET_ECDH_CURVE:
+ err = alg_setkey(sk, optval, optlen, type->ecdhcurve);
break;
case ALG_SET_AEAD_AUTHSIZE:
- if (sock->state == SS_CONNECTED)
- goto unlock;
if (!type->setauthsize)
goto unlock;
err = type->setauthsize(ask->private, optlen);
@@ -836,7 +844,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
struct af_alg_tsgl *sgl;
struct af_alg_control con = {};
long copied = 0;
- bool enc = false;
+ int op = 0;
bool init = false;
int err = 0;
@@ -847,11 +855,13 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
init = true;
switch (con.op) {
+ case ALG_OP_VERIFY:
+ case ALG_OP_SIGN:
case ALG_OP_ENCRYPT:
- enc = true;
- break;
case ALG_OP_DECRYPT:
- enc = false;
+ case ALG_OP_KEYGEN:
+ case ALG_OP_SSGEN:
+ op = con.op;
break;
default:
return -EINVAL;
@@ -875,7 +885,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
ctx->init = true;
if (init) {
- ctx->enc = enc;
+ ctx->op = op;
if (con.iv)
memcpy(ctx->iv, con.iv->iv, ivsize);