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> 14 #include <keys/user-type.h> 15 #include "internal.h" 16 17 /* 18 * Public key or shared secret generation function [RFC2631 sec 2.1.1] 19 * 20 * ya = g^xa mod p; 21 * or 22 * ZZ = yb^xa mod p; 23 * 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. 27 * 28 * Both are the same calculation, so g or yb are the "base" and ya or 29 * ZZ are the "result". 30 */ 31 static int do_dh(MPI result, MPI base, MPI xa, MPI p) 32 { 33 return mpi_powm(result, base, xa, p); 34 } 35 36 static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) 37 { 38 struct key *key; 39 key_ref_t key_ref; 40 long status; 41 ssize_t ret; 42 43 key_ref = lookup_user_key(keyid, 0, KEY_NEED_READ); 44 if (IS_ERR(key_ref)) { 45 ret = -ENOKEY; 46 goto error; 47 } 48 49 key = key_ref_to_ptr(key_ref); 50 51 ret = -EOPNOTSUPP; 52 if (key->type == &key_type_user) { 53 down_read(&key->sem); 54 status = key_validate(key); 55 if (status == 0) { 56 const struct user_key_payload *payload; 57 58 payload = user_key_payload(key); 59 60 if (maxlen == 0) { 61 *mpi = NULL; 62 ret = payload->datalen; 63 } else if (payload->datalen <= maxlen) { 64 *mpi = mpi_read_raw_data(payload->data, 65 payload->datalen); 66 if (*mpi) 67 ret = payload->datalen; 68 } else { 69 ret = -EINVAL; 70 } 71 } 72 up_read(&key->sem); 73 } 74 75 key_put(key); 76 error: 77 return ret; 78 } 79 80 long keyctl_dh_compute(struct keyctl_dh_params __user *params, 81 char __user *buffer, size_t buflen) 82 { 83 long ret; 84 MPI base, private, prime, result; 85 unsigned nbytes; 86 struct keyctl_dh_params pcopy; 87 uint8_t *kbuf; 88 ssize_t keylen; 89 size_t resultlen; 90 91 if (!params || (!buffer && buflen)) { 92 ret = -EINVAL; 93 goto out; 94 } 95 if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { 96 ret = -EFAULT; 97 goto out; 98 } 99 100 keylen = mpi_from_key(pcopy.prime, buflen, &prime); 101 if (keylen < 0 || !prime) { 102 /* buflen == 0 may be used to query the required buffer size, 103 * which is the prime key length. 104 */ 105 ret = keylen; 106 goto out; 107 } 108 109 /* The result is never longer than the prime */ 110 resultlen = keylen; 111 112 keylen = mpi_from_key(pcopy.base, SIZE_MAX, &base); 113 if (keylen < 0 || !base) { 114 ret = keylen; 115 goto error1; 116 } 117 118 keylen = mpi_from_key(pcopy.private, SIZE_MAX, &private); 119 if (keylen < 0 || !private) { 120 ret = keylen; 121 goto error2; 122 } 123 124 result = mpi_alloc(0); 125 if (!result) { 126 ret = -ENOMEM; 127 goto error3; 128 } 129 130 kbuf = kmalloc(resultlen, GFP_KERNEL); 131 if (!kbuf) { 132 ret = -ENOMEM; 133 goto error4; 134 } 135 136 ret = do_dh(result, base, private, prime); 137 if (ret) 138 goto error5; 139 140 ret = mpi_read_buffer(result, kbuf, resultlen, &nbytes, NULL); 141 if (ret != 0) 142 goto error5; 143 144 ret = nbytes; 145 if (copy_to_user(buffer, kbuf, nbytes) != 0) 146 ret = -EFAULT; 147 148 error5: 149 kfree(kbuf); 150 error4: 151 mpi_free(result); 152 error3: 153 mpi_free(private); 154 error2: 155 mpi_free(base); 156 error1: 157 mpi_free(prime); 158 out: 159 return ret; 160 } 161