]>
Commit | Line | Data |
---|---|---|
ddbb4114 MM |
1 | /* Crypto operations using stored keys |
2 | * | |
3 | * Copyright (c) 2016, Intel Corporation | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License | |
7 | * as published by the Free Software Foundation; either version | |
8 | * 2 of the License, or (at your option) any later version. | |
9 | */ | |
10 | ||
11 | #include <linux/mpi.h> | |
12 | #include <linux/slab.h> | |
13 | #include <linux/uaccess.h> | |
f1c316a3 SM |
14 | #include <linux/crypto.h> |
15 | #include <crypto/hash.h> | |
ddbb4114 MM |
16 | #include <keys/user-type.h> |
17 | #include "internal.h" | |
18 | ||
19 | /* | |
20 | * Public key or shared secret generation function [RFC2631 sec 2.1.1] | |
21 | * | |
22 | * ya = g^xa mod p; | |
23 | * or | |
24 | * ZZ = yb^xa mod p; | |
25 | * | |
26 | * where xa is the local private key, ya is the local public key, g is | |
27 | * the generator, p is the prime, yb is the remote public key, and ZZ | |
28 | * is the shared secret. | |
29 | * | |
30 | * Both are the same calculation, so g or yb are the "base" and ya or | |
31 | * ZZ are the "result". | |
32 | */ | |
33 | static int do_dh(MPI result, MPI base, MPI xa, MPI p) | |
34 | { | |
35 | return mpi_powm(result, base, xa, p); | |
36 | } | |
37 | ||
38 | static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) | |
39 | { | |
40 | struct key *key; | |
41 | key_ref_t key_ref; | |
42 | long status; | |
43 | ssize_t ret; | |
44 | ||
45 | key_ref = lookup_user_key(keyid, 0, KEY_NEED_READ); | |
46 | if (IS_ERR(key_ref)) { | |
47 | ret = -ENOKEY; | |
48 | goto error; | |
49 | } | |
50 | ||
51 | key = key_ref_to_ptr(key_ref); | |
52 | ||
53 | ret = -EOPNOTSUPP; | |
54 | if (key->type == &key_type_user) { | |
55 | down_read(&key->sem); | |
56 | status = key_validate(key); | |
57 | if (status == 0) { | |
58 | const struct user_key_payload *payload; | |
59 | ||
0837e49a | 60 | payload = user_key_payload_locked(key); |
ddbb4114 MM |
61 | |
62 | if (maxlen == 0) { | |
63 | *mpi = NULL; | |
64 | ret = payload->datalen; | |
65 | } else if (payload->datalen <= maxlen) { | |
66 | *mpi = mpi_read_raw_data(payload->data, | |
67 | payload->datalen); | |
68 | if (*mpi) | |
69 | ret = payload->datalen; | |
70 | } else { | |
71 | ret = -EINVAL; | |
72 | } | |
73 | } | |
74 | up_read(&key->sem); | |
75 | } | |
76 | ||
77 | key_put(key); | |
78 | error: | |
79 | return ret; | |
80 | } | |
81 | ||
f1c316a3 SM |
82 | struct kdf_sdesc { |
83 | struct shash_desc shash; | |
84 | char ctx[]; | |
85 | }; | |
86 | ||
87 | static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname) | |
88 | { | |
89 | struct crypto_shash *tfm; | |
90 | struct kdf_sdesc *sdesc; | |
91 | int size; | |
92 | ||
93 | /* allocate synchronous hash */ | |
94 | tfm = crypto_alloc_shash(hashname, 0, 0); | |
95 | if (IS_ERR(tfm)) { | |
96 | pr_info("could not allocate digest TFM handle %s\n", hashname); | |
97 | return PTR_ERR(tfm); | |
98 | } | |
99 | ||
100 | size = sizeof(struct shash_desc) + crypto_shash_descsize(tfm); | |
101 | sdesc = kmalloc(size, GFP_KERNEL); | |
102 | if (!sdesc) | |
103 | return -ENOMEM; | |
104 | sdesc->shash.tfm = tfm; | |
105 | sdesc->shash.flags = 0x0; | |
106 | ||
107 | *sdesc_ret = sdesc; | |
108 | ||
109 | return 0; | |
110 | } | |
111 | ||
112 | static void kdf_dealloc(struct kdf_sdesc *sdesc) | |
113 | { | |
114 | if (!sdesc) | |
115 | return; | |
116 | ||
117 | if (sdesc->shash.tfm) | |
118 | crypto_free_shash(sdesc->shash.tfm); | |
119 | ||
120 | kzfree(sdesc); | |
121 | } | |
122 | ||
123 | /* convert 32 bit integer into its string representation */ | |
124 | static inline void crypto_kw_cpu_to_be32(u32 val, u8 *buf) | |
125 | { | |
126 | __be32 *a = (__be32 *)buf; | |
127 | ||
128 | *a = cpu_to_be32(val); | |
129 | } | |
130 | ||
131 | /* | |
132 | * Implementation of the KDF in counter mode according to SP800-108 section 5.1 | |
133 | * as well as SP800-56A section 5.8.1 (Single-step KDF). | |
134 | * | |
135 | * SP800-56A: | |
136 | * The src pointer is defined as Z || other info where Z is the shared secret | |
137 | * from DH and other info is an arbitrary string (see SP800-56A section | |
138 | * 5.8.1.2). | |
139 | */ | |
140 | static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, | |
141 | u8 *dst, unsigned int dlen) | |
142 | { | |
143 | struct shash_desc *desc = &sdesc->shash; | |
144 | unsigned int h = crypto_shash_digestsize(desc->tfm); | |
145 | int err = 0; | |
146 | u8 *dst_orig = dst; | |
147 | u32 i = 1; | |
148 | u8 iteration[sizeof(u32)]; | |
149 | ||
150 | while (dlen) { | |
151 | err = crypto_shash_init(desc); | |
152 | if (err) | |
153 | goto err; | |
154 | ||
155 | crypto_kw_cpu_to_be32(i, iteration); | |
156 | err = crypto_shash_update(desc, iteration, sizeof(u32)); | |
157 | if (err) | |
158 | goto err; | |
159 | ||
160 | if (src && slen) { | |
161 | err = crypto_shash_update(desc, src, slen); | |
162 | if (err) | |
163 | goto err; | |
164 | } | |
165 | ||
166 | if (dlen < h) { | |
167 | u8 tmpbuffer[h]; | |
168 | ||
169 | err = crypto_shash_final(desc, tmpbuffer); | |
170 | if (err) | |
171 | goto err; | |
172 | memcpy(dst, tmpbuffer, dlen); | |
173 | memzero_explicit(tmpbuffer, h); | |
174 | return 0; | |
175 | } else { | |
176 | err = crypto_shash_final(desc, dst); | |
177 | if (err) | |
178 | goto err; | |
179 | ||
180 | dlen -= h; | |
181 | dst += h; | |
182 | i++; | |
183 | } | |
184 | } | |
185 | ||
186 | return 0; | |
187 | ||
188 | err: | |
189 | memzero_explicit(dst_orig, dlen); | |
190 | return err; | |
191 | } | |
192 | ||
193 | static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, | |
194 | char __user *buffer, size_t buflen, | |
195 | uint8_t *kbuf, size_t kbuflen) | |
196 | { | |
197 | uint8_t *outbuf = NULL; | |
198 | int ret; | |
199 | ||
200 | outbuf = kmalloc(buflen, GFP_KERNEL); | |
201 | if (!outbuf) { | |
202 | ret = -ENOMEM; | |
203 | goto err; | |
204 | } | |
205 | ||
206 | ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen); | |
207 | if (ret) | |
208 | goto err; | |
209 | ||
210 | ret = buflen; | |
211 | if (copy_to_user(buffer, outbuf, buflen) != 0) | |
212 | ret = -EFAULT; | |
213 | ||
214 | err: | |
215 | kzfree(outbuf); | |
216 | return ret; | |
217 | } | |
218 | ||
219 | long __keyctl_dh_compute(struct keyctl_dh_params __user *params, | |
220 | char __user *buffer, size_t buflen, | |
221 | struct keyctl_kdf_params *kdfcopy) | |
ddbb4114 MM |
222 | { |
223 | long ret; | |
224 | MPI base, private, prime, result; | |
225 | unsigned nbytes; | |
226 | struct keyctl_dh_params pcopy; | |
227 | uint8_t *kbuf; | |
228 | ssize_t keylen; | |
229 | size_t resultlen; | |
f1c316a3 | 230 | struct kdf_sdesc *sdesc = NULL; |
ddbb4114 MM |
231 | |
232 | if (!params || (!buffer && buflen)) { | |
233 | ret = -EINVAL; | |
234 | goto out; | |
235 | } | |
236 | if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { | |
237 | ret = -EFAULT; | |
238 | goto out; | |
239 | } | |
240 | ||
f1c316a3 SM |
241 | if (kdfcopy) { |
242 | char *hashname; | |
243 | ||
244 | if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN || | |
245 | kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) { | |
246 | ret = -EMSGSIZE; | |
247 | goto out; | |
248 | } | |
249 | ||
250 | /* get KDF name string */ | |
251 | hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); | |
252 | if (IS_ERR(hashname)) { | |
253 | ret = PTR_ERR(hashname); | |
254 | goto out; | |
255 | } | |
256 | ||
257 | /* allocate KDF from the kernel crypto API */ | |
258 | ret = kdf_alloc(&sdesc, hashname); | |
259 | kfree(hashname); | |
260 | if (ret) | |
261 | goto out; | |
4693fc73 SM |
262 | } |
263 | ||
f1c316a3 SM |
264 | /* |
265 | * If the caller requests postprocessing with a KDF, allow an | |
266 | * arbitrary output buffer size since the KDF ensures proper truncation. | |
267 | */ | |
268 | keylen = mpi_from_key(pcopy.prime, kdfcopy ? SIZE_MAX : buflen, &prime); | |
ddbb4114 MM |
269 | if (keylen < 0 || !prime) { |
270 | /* buflen == 0 may be used to query the required buffer size, | |
271 | * which is the prime key length. | |
272 | */ | |
273 | ret = keylen; | |
274 | goto out; | |
275 | } | |
276 | ||
277 | /* The result is never longer than the prime */ | |
278 | resultlen = keylen; | |
279 | ||
280 | keylen = mpi_from_key(pcopy.base, SIZE_MAX, &base); | |
281 | if (keylen < 0 || !base) { | |
282 | ret = keylen; | |
283 | goto error1; | |
284 | } | |
285 | ||
286 | keylen = mpi_from_key(pcopy.private, SIZE_MAX, &private); | |
287 | if (keylen < 0 || !private) { | |
288 | ret = keylen; | |
289 | goto error2; | |
290 | } | |
291 | ||
292 | result = mpi_alloc(0); | |
293 | if (!result) { | |
294 | ret = -ENOMEM; | |
295 | goto error3; | |
296 | } | |
297 | ||
f1c316a3 SM |
298 | /* allocate space for DH shared secret and SP800-56A otherinfo */ |
299 | kbuf = kmalloc(kdfcopy ? (resultlen + kdfcopy->otherinfolen) : resultlen, | |
300 | GFP_KERNEL); | |
ddbb4114 MM |
301 | if (!kbuf) { |
302 | ret = -ENOMEM; | |
303 | goto error4; | |
304 | } | |
305 | ||
f1c316a3 SM |
306 | /* |
307 | * Concatenate SP800-56A otherinfo past DH shared secret -- the | |
308 | * input to the KDF is (DH shared secret || otherinfo) | |
309 | */ | |
310 | if (kdfcopy && kdfcopy->otherinfo && | |
311 | copy_from_user(kbuf + resultlen, kdfcopy->otherinfo, | |
312 | kdfcopy->otherinfolen) != 0) { | |
313 | ret = -EFAULT; | |
314 | goto error5; | |
315 | } | |
316 | ||
ddbb4114 MM |
317 | ret = do_dh(result, base, private, prime); |
318 | if (ret) | |
319 | goto error5; | |
320 | ||
321 | ret = mpi_read_buffer(result, kbuf, resultlen, &nbytes, NULL); | |
322 | if (ret != 0) | |
323 | goto error5; | |
324 | ||
f1c316a3 SM |
325 | if (kdfcopy) { |
326 | ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, kbuf, | |
327 | resultlen + kdfcopy->otherinfolen); | |
328 | } else { | |
329 | ret = nbytes; | |
330 | if (copy_to_user(buffer, kbuf, nbytes) != 0) | |
331 | ret = -EFAULT; | |
332 | } | |
ddbb4114 MM |
333 | |
334 | error5: | |
f1c316a3 | 335 | kzfree(kbuf); |
ddbb4114 MM |
336 | error4: |
337 | mpi_free(result); | |
338 | error3: | |
339 | mpi_free(private); | |
340 | error2: | |
341 | mpi_free(base); | |
342 | error1: | |
343 | mpi_free(prime); | |
344 | out: | |
f1c316a3 | 345 | kdf_dealloc(sdesc); |
ddbb4114 MM |
346 | return ret; |
347 | } | |
f1c316a3 SM |
348 | |
349 | long keyctl_dh_compute(struct keyctl_dh_params __user *params, | |
350 | char __user *buffer, size_t buflen, | |
351 | struct keyctl_kdf_params __user *kdf) | |
352 | { | |
353 | struct keyctl_kdf_params kdfcopy; | |
354 | ||
355 | if (!kdf) | |
356 | return __keyctl_dh_compute(params, buffer, buflen, NULL); | |
357 | ||
358 | if (copy_from_user(&kdfcopy, kdf, sizeof(kdfcopy)) != 0) | |
359 | return -EFAULT; | |
360 | ||
361 | return __keyctl_dh_compute(params, buffer, buflen, &kdfcopy); | |
362 | } |