Blame view
crypto/ecdh.c
3.86 KB
3c4b23901 crypto: ecdh - Ad... |
1 2 3 4 5 6 |
/* ECDH key-agreement protocol * * Copyright (c) 2016, Intel Corporation * Authors: Salvator Benedetto <salvatore.benedetto@intel.com> * * This program is free software; you can redistribute it and/or |
c0ca1215d crypto: kpp, (ec)... |
7 |
* modify it under the terms of the GNU General Public License |
3c4b23901 crypto: ecdh - Ad... |
8 |
* as published by the Free Software Foundation; either version |
c0ca1215d crypto: kpp, (ec)... |
9 |
* 2 of the License, or (at your option) any later version. |
3c4b23901 crypto: ecdh - Ad... |
10 11 12 13 14 15 16 17 18 19 20 21 22 |
*/ #include <linux/module.h> #include <crypto/internal/kpp.h> #include <crypto/kpp.h> #include <crypto/ecdh.h> #include <linux/scatterlist.h> #include "ecc.h" struct ecdh_ctx { unsigned int curve_id; unsigned int ndigits; u64 private_key[ECC_MAX_DIGITS]; |
3c4b23901 crypto: ecdh - Ad... |
23 24 25 26 27 28 29 30 31 32 |
}; static inline struct ecdh_ctx *ecdh_get_ctx(struct crypto_kpp *tfm) { return kpp_tfm_ctx(tfm); } static unsigned int ecdh_supported_curve(unsigned int curve_id) { switch (curve_id) { |
6ff380da9 crypto: ecc - Act... |
33 34 |
case ECC_CURVE_NIST_P192: return ECC_CURVE_NIST_P192_DIGITS; case ECC_CURVE_NIST_P256: return ECC_CURVE_NIST_P256_DIGITS; |
3c4b23901 crypto: ecdh - Ad... |
35 36 37 |
default: return 0; } } |
5527dfb6d crypto: kpp - con... |
38 39 |
static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, unsigned int len) |
3c4b23901 crypto: ecdh - Ad... |
40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
{ struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); struct ecdh params; unsigned int ndigits; if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) return -EINVAL; ndigits = ecdh_supported_curve(params.curve_id); if (!ndigits) return -EINVAL; ctx->curve_id = params.curve_id; ctx->ndigits = ndigits; |
6755fd269 crypto: ecdh - ad... |
54 55 56 |
if (!params.key || !params.key_size) return ecc_gen_privkey(ctx->curve_id, ctx->ndigits, ctx->private_key); |
3c4b23901 crypto: ecdh - Ad... |
57 |
if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits, |
ad2695971 crypto: ecc - rem... |
58 |
(const u64 *)params.key, params.key_size) < 0) |
3c4b23901 crypto: ecdh - Ad... |
59 60 61 62 63 64 65 66 67 |
return -EINVAL; memcpy(ctx->private_key, params.key, params.key_size); return 0; } static int ecdh_compute_value(struct kpp_request *req) { |
3c4b23901 crypto: ecdh - Ad... |
68 69 |
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); |
952035bae crypto: ecdh - fi... |
70 71 |
u64 *public_key; u64 *shared_secret = NULL; |
3c4b23901 crypto: ecdh - Ad... |
72 |
void *buf; |
952035bae crypto: ecdh - fi... |
73 74 |
size_t copied, nbytes, public_key_sz; int ret = -ENOMEM; |
3c4b23901 crypto: ecdh - Ad... |
75 76 |
nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT; |
952035bae crypto: ecdh - fi... |
77 78 79 80 81 82 |
/* Public part is a point thus it has both coordinates */ public_key_sz = 2 * nbytes; public_key = kmalloc(public_key_sz, GFP_KERNEL); if (!public_key) return -ENOMEM; |
3c4b23901 crypto: ecdh - Ad... |
83 84 |
if (req->src) { |
952035bae crypto: ecdh - fi... |
85 86 87 88 89 90 91 92 93 94 |
shared_secret = kmalloc(nbytes, GFP_KERNEL); if (!shared_secret) goto free_pubkey; copied = sg_copy_to_buffer(req->src, 1, public_key, public_key_sz); if (copied != public_key_sz) { ret = -EINVAL; goto free_all; } |
3c4b23901 crypto: ecdh - Ad... |
95 |
|
8f44df154 crypto: ecdh - ma... |
96 |
ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits, |
952035bae crypto: ecdh - fi... |
97 98 |
ctx->private_key, public_key, shared_secret); |
3c4b23901 crypto: ecdh - Ad... |
99 |
|
952035bae crypto: ecdh - fi... |
100 |
buf = shared_secret; |
3c4b23901 crypto: ecdh - Ad... |
101 |
} else { |
7380c56d2 crypto: ecc - ren... |
102 |
ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits, |
952035bae crypto: ecdh - fi... |
103 104 105 |
ctx->private_key, public_key); buf = public_key; nbytes = public_key_sz; |
3c4b23901 crypto: ecdh - Ad... |
106 107 108 |
} if (ret < 0) |
952035bae crypto: ecdh - fi... |
109 |
goto free_all; |
3c4b23901 crypto: ecdh - Ad... |
110 111 112 |
copied = sg_copy_from_buffer(req->dst, 1, buf, nbytes); if (copied != nbytes) |
952035bae crypto: ecdh - fi... |
113 |
ret = -EINVAL; |
3c4b23901 crypto: ecdh - Ad... |
114 |
|
952035bae crypto: ecdh - fi... |
115 116 117 118 119 |
/* fall through */ free_all: kzfree(shared_secret); free_pubkey: kfree(public_key); |
3c4b23901 crypto: ecdh - Ad... |
120 121 |
return ret; } |
d0efb48b8 crypto: ecdh - co... |
122 |
static unsigned int ecdh_max_size(struct crypto_kpp *tfm) |
3c4b23901 crypto: ecdh - Ad... |
123 124 |
{ struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); |
3c4b23901 crypto: ecdh - Ad... |
125 |
|
d0efb48b8 crypto: ecdh - co... |
126 127 |
/* Public key is made of two coordinates, add one to the left shift */ return ctx->ndigits << (ECC_DIGITS_TO_BYTES_SHIFT + 1); |
3c4b23901 crypto: ecdh - Ad... |
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
} static void no_exit_tfm(struct crypto_kpp *tfm) { return; } static struct kpp_alg ecdh = { .set_secret = ecdh_set_secret, .generate_public_key = ecdh_compute_value, .compute_shared_secret = ecdh_compute_value, .max_size = ecdh_max_size, .exit = no_exit_tfm, .base = { .cra_name = "ecdh", .cra_driver_name = "ecdh-generic", .cra_priority = 100, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ecdh_ctx), }, }; static int ecdh_init(void) { return crypto_register_kpp(&ecdh); } static void ecdh_exit(void) { crypto_unregister_kpp(&ecdh); } module_init(ecdh_init); module_exit(ecdh_exit); MODULE_ALIAS_CRYPTO("ecdh"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("ECDH generic algorithm"); |