ecdh_helper.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * ECDH helper functions - KPP wrappings
  3. *
  4. * Copyright (C) 2017 Intel Corporation
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation;
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  11. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
  13. * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
  14. * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. *
  19. * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
  20. * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
  21. * SOFTWARE IS DISCLAIMED.
  22. */
  23. #include "ecdh_helper.h"
  24. #include <linux/scatterlist.h>
  25. #include <crypto/kpp.h>
  26. #include <crypto/ecdh.h>
  27. struct ecdh_completion {
  28. struct completion completion;
  29. int err;
  30. };
  31. static void ecdh_complete(struct crypto_async_request *req, int err)
  32. {
  33. struct ecdh_completion *res = req->data;
  34. if (err == -EINPROGRESS)
  35. return;
  36. res->err = err;
  37. complete(&res->completion);
  38. }
  39. static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits)
  40. {
  41. int i;
  42. for (i = 0; i < ndigits; i++)
  43. out[i] = __swab64(in[ndigits - 1 - i]);
  44. }
  45. bool compute_ecdh_secret(const u8 public_key[64], const u8 private_key[32],
  46. u8 secret[32])
  47. {
  48. struct crypto_kpp *tfm;
  49. struct kpp_request *req;
  50. struct ecdh p;
  51. struct ecdh_completion result;
  52. struct scatterlist src, dst;
  53. u8 *tmp, *buf;
  54. unsigned int buf_len;
  55. int err = -ENOMEM;
  56. tmp = kmalloc(64, GFP_KERNEL);
  57. if (!tmp)
  58. return false;
  59. tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
  60. if (IS_ERR(tfm)) {
  61. pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n",
  62. PTR_ERR(tfm));
  63. goto free_tmp;
  64. }
  65. req = kpp_request_alloc(tfm, GFP_KERNEL);
  66. if (!req)
  67. goto free_kpp;
  68. init_completion(&result.completion);
  69. /* Security Manager Protocol holds digits in litte-endian order
  70. * while ECC API expect big-endian data
  71. */
  72. swap_digits((u64 *)private_key, (u64 *)tmp, 4);
  73. p.key = (char *)tmp;
  74. p.key_size = 32;
  75. /* Set curve_id */
  76. p.curve_id = ECC_CURVE_NIST_P256;
  77. buf_len = crypto_ecdh_key_len(&p);
  78. buf = kmalloc(buf_len, GFP_KERNEL);
  79. if (!buf)
  80. goto free_req;
  81. crypto_ecdh_encode_key(buf, buf_len, &p);
  82. /* Set A private Key */
  83. err = crypto_kpp_set_secret(tfm, (void *)buf, buf_len);
  84. if (err)
  85. goto free_all;
  86. swap_digits((u64 *)public_key, (u64 *)tmp, 4); /* x */
  87. swap_digits((u64 *)&public_key[32], (u64 *)&tmp[32], 4); /* y */
  88. sg_init_one(&src, tmp, 64);
  89. sg_init_one(&dst, secret, 32);
  90. kpp_request_set_input(req, &src, 64);
  91. kpp_request_set_output(req, &dst, 32);
  92. kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
  93. ecdh_complete, &result);
  94. err = crypto_kpp_compute_shared_secret(req);
  95. if (err == -EINPROGRESS) {
  96. wait_for_completion(&result.completion);
  97. err = result.err;
  98. }
  99. if (err < 0) {
  100. pr_err("alg: ecdh: compute shared secret failed. err %d\n",
  101. err);
  102. goto free_all;
  103. }
  104. swap_digits((u64 *)secret, (u64 *)tmp, 4);
  105. memcpy(secret, tmp, 32);
  106. free_all:
  107. kzfree(buf);
  108. free_req:
  109. kpp_request_free(req);
  110. free_kpp:
  111. crypto_free_kpp(tfm);
  112. free_tmp:
  113. kfree(tmp);
  114. return (err == 0);
  115. }
  116. bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32])
  117. {
  118. struct crypto_kpp *tfm;
  119. struct kpp_request *req;
  120. struct ecdh p;
  121. struct ecdh_completion result;
  122. struct scatterlist dst;
  123. u8 *tmp, *buf;
  124. unsigned int buf_len;
  125. int err = -ENOMEM;
  126. const unsigned short max_tries = 16;
  127. unsigned short tries = 0;
  128. tmp = kmalloc(64, GFP_KERNEL);
  129. if (!tmp)
  130. return false;
  131. tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
  132. if (IS_ERR(tfm)) {
  133. pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n",
  134. PTR_ERR(tfm));
  135. goto free_tmp;
  136. }
  137. req = kpp_request_alloc(tfm, GFP_KERNEL);
  138. if (!req)
  139. goto free_kpp;
  140. init_completion(&result.completion);
  141. /* Set curve_id */
  142. p.curve_id = ECC_CURVE_NIST_P256;
  143. p.key_size = 32;
  144. buf_len = crypto_ecdh_key_len(&p);
  145. buf = kmalloc(buf_len, GFP_KERNEL);
  146. if (!buf)
  147. goto free_req;
  148. do {
  149. if (tries++ >= max_tries)
  150. goto free_all;
  151. /* Set private Key */
  152. p.key = (char *)private_key;
  153. crypto_ecdh_encode_key(buf, buf_len, &p);
  154. err = crypto_kpp_set_secret(tfm, buf, buf_len);
  155. if (err)
  156. goto free_all;
  157. sg_init_one(&dst, tmp, 64);
  158. kpp_request_set_input(req, NULL, 0);
  159. kpp_request_set_output(req, &dst, 64);
  160. kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
  161. ecdh_complete, &result);
  162. err = crypto_kpp_generate_public_key(req);
  163. if (err == -EINPROGRESS) {
  164. wait_for_completion(&result.completion);
  165. err = result.err;
  166. }
  167. /* Private key is not valid. Regenerate */
  168. if (err == -EINVAL)
  169. continue;
  170. if (err < 0)
  171. goto free_all;
  172. else
  173. break;
  174. } while (true);
  175. /* Keys are handed back in little endian as expected by Security
  176. * Manager Protocol
  177. */
  178. swap_digits((u64 *)tmp, (u64 *)public_key, 4); /* x */
  179. swap_digits((u64 *)&tmp[32], (u64 *)&public_key[32], 4); /* y */
  180. swap_digits((u64 *)private_key, (u64 *)tmp, 4);
  181. memcpy(private_key, tmp, 32);
  182. free_all:
  183. kzfree(buf);
  184. free_req:
  185. kpp_request_free(req);
  186. free_kpp:
  187. crypto_free_kpp(tfm);
  188. free_tmp:
  189. kfree(tmp);
  190. return (err == 0);
  191. }