ecdh.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 Licence
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the Licence, 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, void *buf, unsigned int len)
  37. {
  38. struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
  39. struct ecdh params;
  40. unsigned int ndigits;
  41. if (crypto_ecdh_decode_key(buf, len, &params) < 0)
  42. return -EINVAL;
  43. ndigits = ecdh_supported_curve(params.curve_id);
  44. if (!ndigits)
  45. return -EINVAL;
  46. ctx->curve_id = params.curve_id;
  47. ctx->ndigits = ndigits;
  48. if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
  49. (const u8 *)params.key, params.key_size) < 0)
  50. return -EINVAL;
  51. memcpy(ctx->private_key, params.key, params.key_size);
  52. return 0;
  53. }
  54. static int ecdh_compute_value(struct kpp_request *req)
  55. {
  56. int ret = 0;
  57. struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
  58. struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
  59. size_t copied, nbytes;
  60. void *buf;
  61. nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
  62. if (req->src) {
  63. copied = sg_copy_to_buffer(req->src, 1, ctx->public_key,
  64. 2 * nbytes);
  65. if (copied != 2 * nbytes)
  66. return -EINVAL;
  67. ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits,
  68. (const u8 *)ctx->private_key, nbytes,
  69. (const u8 *)ctx->public_key, 2 * nbytes,
  70. (u8 *)ctx->shared_secret, nbytes);
  71. buf = ctx->shared_secret;
  72. } else {
  73. ret = ecdh_make_pub_key(ctx->curve_id, ctx->ndigits,
  74. (const u8 *)ctx->private_key, nbytes,
  75. (u8 *)ctx->public_key,
  76. sizeof(ctx->public_key));
  77. buf = ctx->public_key;
  78. /* Public part is a point thus it has both coordinates */
  79. nbytes *= 2;
  80. }
  81. if (ret < 0)
  82. return ret;
  83. copied = sg_copy_from_buffer(req->dst, 1, buf, nbytes);
  84. if (copied != nbytes)
  85. return -EINVAL;
  86. return ret;
  87. }
  88. static int ecdh_max_size(struct crypto_kpp *tfm)
  89. {
  90. struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
  91. int nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
  92. /* Public key is made of two coordinates */
  93. return 2 * nbytes;
  94. }
  95. static void no_exit_tfm(struct crypto_kpp *tfm)
  96. {
  97. return;
  98. }
  99. static struct kpp_alg ecdh = {
  100. .set_secret = ecdh_set_secret,
  101. .generate_public_key = ecdh_compute_value,
  102. .compute_shared_secret = ecdh_compute_value,
  103. .max_size = ecdh_max_size,
  104. .exit = no_exit_tfm,
  105. .base = {
  106. .cra_name = "ecdh",
  107. .cra_driver_name = "ecdh-generic",
  108. .cra_priority = 100,
  109. .cra_module = THIS_MODULE,
  110. .cra_ctxsize = sizeof(struct ecdh_ctx),
  111. },
  112. };
  113. static int ecdh_init(void)
  114. {
  115. return crypto_register_kpp(&ecdh);
  116. }
  117. static void ecdh_exit(void)
  118. {
  119. crypto_unregister_kpp(&ecdh);
  120. }
  121. module_init(ecdh_init);
  122. module_exit(ecdh_exit);
  123. MODULE_ALIAS_CRYPTO("ecdh");
  124. MODULE_LICENSE("GPL");
  125. MODULE_DESCRIPTION("ECDH generic algorithm");