aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/cryptodev/files/0004-Compat-versions-of-PKC-IOCTLs.patch
blob: 2f35768b20ad658adfdc00f457a97e193630b1bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
From b109fbdb64de6be0dc2f0d2ef108cead34652495 Mon Sep 17 00:00:00 2001
From: Yashpal Dutta <yashpal.dutta@freescale.com>
Date: Fri, 7 Mar 2014 06:52:13 +0545
Subject: [PATCH 04/15] Compat versions of PKC IOCTLs

Upstream-status: Pending

Signed-off-by: Yashpal Dutta <yashpal.dutta@freescale.com>
---
 cryptodev_int.h |  20 ++++++++++
 ioctl.c         | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 140 insertions(+)

diff --git a/cryptodev_int.h b/cryptodev_int.h
index fdbcc61..cf54dac 100644
--- a/cryptodev_int.h
+++ b/cryptodev_int.h
@@ -75,6 +75,24 @@ struct compat_crypt_op {
 	compat_uptr_t	iv;/* initialization vector for encryption operations */
 };
 
+/* input of CIOCKEY */
+struct compat_crparam {
+	compat_uptr_t	crp_p;
+	uint32_t	crp_nbits;
+};
+
+struct compat_crypt_kop {
+	uint32_t	crk_op;		/* cryptodev_crk_ot_t */
+	uint32_t	crk_status;
+	uint16_t	crk_iparams;
+	uint16_t	crk_oparams;
+	uint32_t	crk_pad1;
+	struct compat_crparam	crk_param[CRK_MAXPARAM];
+	enum curve_t curve_type; /* 0 == Discrete Log, 1 = EC_PRIME,
+				 2 = EC_BINARY */
+	compat_uptr_t cookie;
+};
+
  /* input of CIOCAUTHCRYPT */
 struct compat_crypt_auth_op {
 	uint32_t	ses;		/* session identifier */
@@ -111,6 +129,8 @@ struct compat_crypt_auth_op {
 #define COMPAT_CIOCASYNCCRYPT  _IOW('c', 107, struct compat_crypt_op)
 #define COMPAT_CIOCASYNCFETCH  _IOR('c', 108, struct compat_crypt_op)
 #define COMPAT_CIOCAUTHCRYPT   _IOWR('c', 109, struct compat_crypt_auth_op)
+#define COMPAT_CIOCASYMASYNCRYPT    _IOW('c', 110, struct compat_crypt_kop)
+#define COMPAT_CIOCASYMASYNFETCH    _IOR('c', 111, struct compat_crypt_kop)
 
 #endif /* CONFIG_COMPAT */
 
diff --git a/ioctl.c b/ioctl.c
index 69980e3..9431025 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -1081,6 +1081,68 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
 /* compatibility code for 32bit userlands */
 #ifdef CONFIG_COMPAT
 
+static inline void compat_to_crypt_kop(struct compat_crypt_kop *compat,
+		 struct crypt_kop *kop)
+{
+	int i;
+	kop->crk_op      = compat->crk_op;
+	kop->crk_status  = compat->crk_status;
+	kop->crk_iparams = compat->crk_iparams;
+	kop->crk_oparams = compat->crk_oparams;
+
+	for (i = 0; i < CRK_MAXPARAM; i++) {
+		kop->crk_param[i].crp_p =
+			compat_ptr(compat->crk_param[i].crp_p);
+		kop->crk_param[i].crp_nbits = compat->crk_param[i].crp_nbits;
+	}
+
+	kop->curve_type = compat->curve_type;
+	kop->cookie = compat->cookie;
+}
+
+static int compat_kop_from_user(struct kernel_crypt_kop *kop,
+	void __user *arg)
+{
+	struct compat_crypt_kop compat_kop;
+
+	if (unlikely(copy_from_user(&compat_kop, arg, sizeof(compat_kop))))
+		return -EFAULT;
+
+	compat_to_crypt_kop(&compat_kop, &kop->kop);
+	return fill_kop_from_cop(kop);
+}
+
+static inline void crypt_kop_to_compat(struct crypt_kop *kop,
+				 struct compat_crypt_kop *compat)
+{
+	int i;
+
+	compat->crk_op      = kop->crk_op;
+	compat->crk_status  = kop->crk_status;
+	compat->crk_iparams = kop->crk_iparams;
+	compat->crk_oparams = kop->crk_oparams;
+
+	for (i = 0; i < CRK_MAXPARAM; i++) {
+		compat->crk_param[i].crp_p =
+			 ptr_to_compat(kop->crk_param[i].crp_p);
+		compat->crk_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
+	}
+	compat->cookie = kop->cookie;
+	compat->curve_type = kop->curve_type;
+}
+
+static int compat_kop_to_user(struct kernel_crypt_kop *kop, void __user *arg)
+{
+	struct compat_crypt_kop compat_kop;
+
+	crypt_kop_to_compat(&kop->kop, &compat_kop);
+	if (unlikely(copy_to_user(arg, &compat_kop, sizeof(compat_kop)))) {
+		dprintk(1, KERN_ERR, "Cannot copy to userspace\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
 static inline void
 compat_to_session_op(struct compat_session_op *compat, struct session_op *sop)
 {
@@ -1208,7 +1270,26 @@ cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg_)
 			return -EFAULT;
 		}
 		return ret;
+	case COMPAT_CIOCKEY:
+	{
+		struct cryptodev_pkc *pkc =
+			 kzalloc(sizeof(struct cryptodev_pkc), GFP_KERNEL);
+
+		if (!pkc)
+			return -ENOMEM;
+
+		ret = compat_kop_from_user(&pkc->kop, arg);
+
+		if (unlikely(ret)) {
+			kfree(pkc);
+			return ret;
+		}
 
+		pkc->type = SYNCHRONOUS;
+		ret = crypto_run_asym(pkc);
+		kfree(pkc);
+	}
+	return ret;
 	case COMPAT_CIOCCRYPT:
 		ret = compat_kcop_from_user(&kcop, fcr, arg);
 		if (unlikely(ret))
@@ -1247,6 +1328,45 @@ cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg_)
 
 		return compat_kcop_to_user(&kcop, fcr, arg);
 #endif
+	case COMPAT_CIOCASYMASYNCRYPT:
+	{
+		struct cryptodev_pkc *pkc =
+			kzalloc(sizeof(struct cryptodev_pkc), GFP_KERNEL);
+
+		ret = compat_kop_from_user(&pkc->kop, arg);
+		if (unlikely(ret))
+			return -EINVAL;
+
+		/* Store associated FD priv data with asymmetric request */
+		pkc->priv = pcr;
+		pkc->type = ASYNCHRONOUS;
+		ret = crypto_run_asym(pkc);
+		if (ret == -EINPROGRESS)
+			ret = 0;
+	}
+	return ret;
+	case COMPAT_CIOCASYMASYNFETCH:
+	{
+		struct cryptodev_pkc *pkc;
+		unsigned long flags;
+
+		spin_lock_irqsave(&pcr->completion_lock, flags);
+		if (list_empty(&pcr->asym_completed_list)) {
+			spin_unlock_irqrestore(&pcr->completion_lock, flags);
+			return -ENOMEM;
+		}
+		pkc = list_first_entry(&pcr->asym_completed_list,
+			 struct cryptodev_pkc, list);
+		list_del(&pkc->list);
+		spin_unlock_irqrestore(&pcr->completion_lock, flags);
+		ret = crypto_async_fetch_asym(pkc);
+
+		/* Reflect the updated request to user-space */
+		if (!ret)
+			compat_kop_to_user(&pkc->kop, arg);
+		kfree(pkc);
+	}
+	return ret;
 	default:
 		return -EINVAL;
 	}
-- 
2.3.5