1 /* Crypto operations using stored keys
3 * Copyright (c) 2016, Intel Corporation
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.
11 #include <linux/mpi.h>
12 #include <linux/slab.h>
13 #include <linux/uaccess.h>
14 #include <keys/user-type.h>
18 * Public key or shared secret generation function [RFC2631 sec 2.1.1]
24 * where xa is the local private key, ya is the local public key, g is
25 * the generator, p is the prime, yb is the remote public key, and ZZ
26 * is the shared secret.
28 * Both are the same calculation, so g or yb are the "base" and ya or
29 * ZZ are the "result".
31 static int do_dh(MPI result
, MPI base
, MPI xa
, MPI p
)
33 return mpi_powm(result
, base
, xa
, p
);
36 static ssize_t
mpi_from_key(key_serial_t keyid
, size_t maxlen
, MPI
*mpi
)
43 key_ref
= lookup_user_key(keyid
, 0, KEY_NEED_READ
);
44 if (IS_ERR(key_ref
)) {
49 key
= key_ref_to_ptr(key_ref
);
52 if (key
->type
== &key_type_user
) {
54 status
= key_validate(key
);
56 const struct user_key_payload
*payload
;
58 payload
= user_key_payload_locked(key
);
62 ret
= payload
->datalen
;
63 } else if (payload
->datalen
<= maxlen
) {
64 *mpi
= mpi_read_raw_data(payload
->data
,
67 ret
= payload
->datalen
;
80 long keyctl_dh_compute(struct keyctl_dh_params __user
*params
,
81 char __user
*buffer
, size_t buflen
,
82 void __user
*reserved
)
85 MPI base
, private, prime
, result
;
87 struct keyctl_dh_params pcopy
;
92 if (!params
|| (!buffer
&& buflen
)) {
96 if (copy_from_user(&pcopy
, params
, sizeof(pcopy
)) != 0) {
106 keylen
= mpi_from_key(pcopy
.prime
, buflen
, &prime
);
107 if (keylen
< 0 || !prime
) {
108 /* buflen == 0 may be used to query the required buffer size,
109 * which is the prime key length.
115 /* The result is never longer than the prime */
118 keylen
= mpi_from_key(pcopy
.base
, SIZE_MAX
, &base
);
119 if (keylen
< 0 || !base
) {
124 keylen
= mpi_from_key(pcopy
.private, SIZE_MAX
, &private);
125 if (keylen
< 0 || !private) {
130 result
= mpi_alloc(0);
136 kbuf
= kmalloc(resultlen
, GFP_KERNEL
);
142 ret
= do_dh(result
, base
, private, prime
);
146 ret
= mpi_read_buffer(result
, kbuf
, resultlen
, &nbytes
, NULL
);
151 if (copy_to_user(buffer
, kbuf
, nbytes
) != 0)