ecdh.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* ECDH key-agreement protocol
  2. *
  3. * Copyright (c) 2016, Intel Corporation
  4. * Authors: Salvator Benedetto <salvatore.benedetto@intel.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <crypto/internal/kpp.h>
  13. #include <crypto/kpp.h>
  14. #include <crypto/ecdh.h>
  15. #include <linux/scatterlist.h>
  16. #include "ecc.h"
  17. struct ecdh_ctx {
  18. unsigned int curve_id;
  19. unsigned int ndigits;
  20. u64 private_key[ECC_MAX_DIGITS];
  21. u64 public_key[2 * ECC_MAX_DIGITS];
  22. u64 shared_secret[ECC_MAX_DIGITS];
  23. };
  24. static inline struct ecdh_ctx *ecdh_get_ctx(struct crypto_kpp *tfm)
  25. {
  26. return kpp_tfm_ctx(tfm);
  27. }
  28. static unsigned int ecdh_supported_curve(unsigned int curve_id)
  29. {
  30. switch (curve_id) {
  31. case ECC_CURVE_NIST_P192: return 3;
  32. case ECC_CURVE_NIST_P256: return 4;
  33. default: return 0;
  34. }
  35. }
  36. static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
  37. unsigned int len)
  38. {
  39. struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
  40. struct ecdh params;
  41. unsigned int ndigits;
  42. if (crypto_ecdh_decode_key(buf, len, &params) < 0)
  43. return -EINVAL;
  44. ndigits = ecdh_supported_curve(params.curve_id);
  45. if (!ndigits)
  46. return -EINVAL;
  47. ctx->curve_id = params.curve_id;
  48. ctx->ndigits = ndigits;
  49. if (!params.key || !params.key_size)
  50. return ecc_gen_privkey(ctx->curve_id, ctx->ndigits,
  51. ctx->private_key);
  52. if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
  53. (const u64 *)params.key, params.key_size) < 0)
  54. return -EINVAL;
  55. memcpy(ctx->private_key, params.key, params.key_size);
  56. return 0;
  57. }
  58. static int ecdh_compute_value(struct kpp_request *req)
  59. {
  60. int ret = 0;
  61. struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
  62. struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
  63. size_t copied, nbytes;
  64. void *buf;
  65. nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
  66. if (req->src) {
  67. copied = sg_copy_to_buffer(req->src, 1, ctx->public_key,
  68. 2 * nbytes);
  69. if (copied != 2 * nbytes)
  70. return -EINVAL;
  71. ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits,
  72. ctx->private_key,
  73. ctx->public_key,
  74. ctx->shared_secret);
  75. buf = ctx->shared_secret;
  76. } else {
  77. ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits,
  78. ctx->private_key, ctx->public_key);
  79. buf = ctx->public_key;
  80. /* Public part is a point thus it has both coordinates */
  81. nbytes *= 2;
  82. }
  83. if (ret < 0)
  84. return ret;
  85. copied = sg_copy_from_buffer(req->dst, 1, buf, nbytes);
  86. if (copied != nbytes)
  87. return -EINVAL;
  88. return ret;
  89. }
  90. static unsigned int ecdh_max_size(struct crypto_kpp *tfm)
  91. {
  92. struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
  93. /* Public key is made of two coordinates, add one to the left shift */
  94. return ctx->ndigits << (ECC_DIGITS_TO_BYTES_SHIFT + 1);
  95. }
  96. static void no_exit_tfm(struct crypto_kpp *tfm)
  97. {
  98. return;
  99. }
  100. static struct kpp_alg ecdh = {
  101. .set_secret = ecdh_set_secret,
  102. .generate_public_key = ecdh_compute_value,
  103. .compute_shared_secret = ecdh_compute_value,
  104. .max_size = ecdh_max_size,
  105. .exit = no_exit_tfm,
  106. .base = {
  107. .cra_name = "ecdh",
  108. .cra_driver_name = "ecdh-generic",
  109. .cra_priority = 100,
  110. .cra_module = THIS_MODULE,
  111. .cra_ctxsize = sizeof(struct ecdh_ctx),
  112. },
  113. };
  114. static int ecdh_init(void)
  115. {
  116. return crypto_register_kpp(&ecdh);
  117. }
  118. static void ecdh_exit(void)
  119. {
  120. crypto_unregister_kpp(&ecdh);
  121. }
  122. module_init(ecdh_init);
  123. module_exit(ecdh_exit);
  124. MODULE_ALIAS_CRYPTO("ecdh");
  125. MODULE_LICENSE("GPL");
  126. MODULE_DESCRIPTION("ECDH generic algorithm");