dh.c 3.3 KB

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