0001
0002
0003 #include <crypto/curve25519.h>
0004 #include <crypto/internal/kpp.h>
0005 #include <crypto/kpp.h>
0006 #include <linux/module.h>
0007 #include <linux/scatterlist.h>
0008
0009 static int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf,
0010 unsigned int len)
0011 {
0012 u8 *secret = kpp_tfm_ctx(tfm);
0013
0014 if (!len)
0015 curve25519_generate_secret(secret);
0016 else if (len == CURVE25519_KEY_SIZE &&
0017 crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE))
0018 memcpy(secret, buf, CURVE25519_KEY_SIZE);
0019 else
0020 return -EINVAL;
0021 return 0;
0022 }
0023
0024 static int curve25519_compute_value(struct kpp_request *req)
0025 {
0026 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
0027 const u8 *secret = kpp_tfm_ctx(tfm);
0028 u8 public_key[CURVE25519_KEY_SIZE];
0029 u8 buf[CURVE25519_KEY_SIZE];
0030 int copied, nbytes;
0031 u8 const *bp;
0032
0033 if (req->src) {
0034 copied = sg_copy_to_buffer(req->src,
0035 sg_nents_for_len(req->src,
0036 CURVE25519_KEY_SIZE),
0037 public_key, CURVE25519_KEY_SIZE);
0038 if (copied != CURVE25519_KEY_SIZE)
0039 return -EINVAL;
0040 bp = public_key;
0041 } else {
0042 bp = curve25519_base_point;
0043 }
0044
0045 curve25519_generic(buf, secret, bp);
0046
0047
0048 nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len);
0049 copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst,
0050 nbytes),
0051 buf, nbytes);
0052 if (copied != nbytes)
0053 return -EINVAL;
0054 return 0;
0055 }
0056
0057 static unsigned int curve25519_max_size(struct crypto_kpp *tfm)
0058 {
0059 return CURVE25519_KEY_SIZE;
0060 }
0061
0062 static struct kpp_alg curve25519_alg = {
0063 .base.cra_name = "curve25519",
0064 .base.cra_driver_name = "curve25519-generic",
0065 .base.cra_priority = 100,
0066 .base.cra_module = THIS_MODULE,
0067 .base.cra_ctxsize = CURVE25519_KEY_SIZE,
0068
0069 .set_secret = curve25519_set_secret,
0070 .generate_public_key = curve25519_compute_value,
0071 .compute_shared_secret = curve25519_compute_value,
0072 .max_size = curve25519_max_size,
0073 };
0074
0075 static int curve25519_init(void)
0076 {
0077 return crypto_register_kpp(&curve25519_alg);
0078 }
0079
0080 static void curve25519_exit(void)
0081 {
0082 crypto_unregister_kpp(&curve25519_alg);
0083 }
0084
0085 subsys_initcall(curve25519_init);
0086 module_exit(curve25519_exit);
0087
0088 MODULE_ALIAS_CRYPTO("curve25519");
0089 MODULE_ALIAS_CRYPTO("curve25519-generic");
0090 MODULE_LICENSE("GPL");