Blame view
crypto/ecdh.c
5.7 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
3c4b23901 crypto: ecdh - Ad... |
2 3 4 5 |
/* ECDH key-agreement protocol * * Copyright (c) 2016, Intel Corporation * Authors: Salvator Benedetto <salvatore.benedetto@intel.com> |
3c4b23901 crypto: ecdh - Ad... |
6 7 8 9 10 11 12 13 14 15 16 17 18 |
*/ #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... |
19 20 21 22 23 24 |
}; static inline struct ecdh_ctx *ecdh_get_ctx(struct crypto_kpp *tfm) { return kpp_tfm_ctx(tfm); } |
5527dfb6d crypto: kpp - con... |
25 26 |
static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, unsigned int len) |
3c4b23901 crypto: ecdh - Ad... |
27 28 29 |
{ struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); struct ecdh params; |
3c4b23901 crypto: ecdh - Ad... |
30 |
|
0aa171e9b crypto: ecdh - av... |
31 |
if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0 || |
6763f5ea2 crypto: ecdh - mo... |
32 |
params.key_size > sizeof(u64) * ctx->ndigits) |
3c4b23901 crypto: ecdh - Ad... |
33 |
return -EINVAL; |
6755fd269 crypto: ecdh - ad... |
34 35 36 |
if (!params.key || !params.key_size) return ecc_gen_privkey(ctx->curve_id, ctx->ndigits, ctx->private_key); |
3c4b23901 crypto: ecdh - Ad... |
37 |
memcpy(ctx->private_key, params.key, params.key_size); |
17858b140 crypto: ecdh - av... |
38 39 40 41 42 |
if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits, ctx->private_key, params.key_size) < 0) { memzero_explicit(ctx->private_key, params.key_size); return -EINVAL; } |
3c4b23901 crypto: ecdh - Ad... |
43 44 45 46 47 |
return 0; } static int ecdh_compute_value(struct kpp_request *req) { |
3c4b23901 crypto: ecdh - Ad... |
48 49 |
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); |
952035bae crypto: ecdh - fi... |
50 51 |
u64 *public_key; u64 *shared_secret = NULL; |
3c4b23901 crypto: ecdh - Ad... |
52 |
void *buf; |
952035bae crypto: ecdh - fi... |
53 54 |
size_t copied, nbytes, public_key_sz; int ret = -ENOMEM; |
3c4b23901 crypto: ecdh - Ad... |
55 56 |
nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT; |
952035bae crypto: ecdh - fi... |
57 58 59 60 61 62 |
/* 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... |
63 64 |
if (req->src) { |
952035bae crypto: ecdh - fi... |
65 66 67 |
shared_secret = kmalloc(nbytes, GFP_KERNEL); if (!shared_secret) goto free_pubkey; |
95ec01ba1 crypto: ecdh - fi... |
68 69 70 71 72 73 74 75 76 77 78 79 |
/* from here on it's invalid parameters */ ret = -EINVAL; /* must have exactly two points to be on the curve */ if (public_key_sz != req->src_len) goto free_all; copied = sg_copy_to_buffer(req->src, sg_nents_for_len(req->src, public_key_sz), public_key, public_key_sz); if (copied != public_key_sz) |
952035bae crypto: ecdh - fi... |
80 |
goto free_all; |
3c4b23901 crypto: ecdh - Ad... |
81 |
|
8f44df154 crypto: ecdh - ma... |
82 |
ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits, |
952035bae crypto: ecdh - fi... |
83 84 |
ctx->private_key, public_key, shared_secret); |
3c4b23901 crypto: ecdh - Ad... |
85 |
|
952035bae crypto: ecdh - fi... |
86 |
buf = shared_secret; |
3c4b23901 crypto: ecdh - Ad... |
87 |
} else { |
7380c56d2 crypto: ecc - ren... |
88 |
ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits, |
952035bae crypto: ecdh - fi... |
89 90 91 |
ctx->private_key, public_key); buf = public_key; nbytes = public_key_sz; |
3c4b23901 crypto: ecdh - Ad... |
92 93 94 |
} if (ret < 0) |
952035bae crypto: ecdh - fi... |
95 |
goto free_all; |
3c4b23901 crypto: ecdh - Ad... |
96 |
|
95ec01ba1 crypto: ecdh - fi... |
97 98 99 100 101 |
/* might want less than we've got */ nbytes = min_t(size_t, nbytes, req->dst_len); copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, nbytes), buf, nbytes); |
3c4b23901 crypto: ecdh - Ad... |
102 |
if (copied != nbytes) |
952035bae crypto: ecdh - fi... |
103 |
ret = -EINVAL; |
3c4b23901 crypto: ecdh - Ad... |
104 |
|
952035bae crypto: ecdh - fi... |
105 106 |
/* fall through */ free_all: |
453431a54 mm, treewide: ren... |
107 |
kfree_sensitive(shared_secret); |
952035bae crypto: ecdh - fi... |
108 109 |
free_pubkey: kfree(public_key); |
3c4b23901 crypto: ecdh - Ad... |
110 111 |
return ret; } |
d0efb48b8 crypto: ecdh - co... |
112 |
static unsigned int ecdh_max_size(struct crypto_kpp *tfm) |
3c4b23901 crypto: ecdh - Ad... |
113 114 |
{ struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); |
3c4b23901 crypto: ecdh - Ad... |
115 |
|
d0efb48b8 crypto: ecdh - co... |
116 117 |
/* 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... |
118 |
} |
6763f5ea2 crypto: ecdh - mo... |
119 120 121 122 123 124 125 126 127 128 129 |
static int ecdh_nist_p192_init_tfm(struct crypto_kpp *tfm) { struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); ctx->curve_id = ECC_CURVE_NIST_P192; ctx->ndigits = ECC_CURVE_NIST_P192_DIGITS; return 0; } static struct kpp_alg ecdh_nist_p192 = { |
3c4b23901 crypto: ecdh - Ad... |
130 131 132 133 |
.set_secret = ecdh_set_secret, .generate_public_key = ecdh_compute_value, .compute_shared_secret = ecdh_compute_value, .max_size = ecdh_max_size, |
6763f5ea2 crypto: ecdh - mo... |
134 |
.init = ecdh_nist_p192_init_tfm, |
3c4b23901 crypto: ecdh - Ad... |
135 |
.base = { |
6763f5ea2 crypto: ecdh - mo... |
136 |
.cra_name = "ecdh-nist-p192", |
c5ae16f5c crypto: ecdh - ex... |
137 |
.cra_driver_name = "ecdh-nist-p192-generic", |
3c4b23901 crypto: ecdh - Ad... |
138 139 140 141 142 |
.cra_priority = 100, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ecdh_ctx), }, }; |
6763f5ea2 crypto: ecdh - mo... |
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
static int ecdh_nist_p256_init_tfm(struct crypto_kpp *tfm) { struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); ctx->curve_id = ECC_CURVE_NIST_P256; ctx->ndigits = ECC_CURVE_NIST_P256_DIGITS; return 0; } static struct kpp_alg ecdh_nist_p256 = { .set_secret = ecdh_set_secret, .generate_public_key = ecdh_compute_value, .compute_shared_secret = ecdh_compute_value, .max_size = ecdh_max_size, .init = ecdh_nist_p256_init_tfm, .base = { .cra_name = "ecdh-nist-p256", |
c5ae16f5c crypto: ecdh - ex... |
161 |
.cra_driver_name = "ecdh-nist-p256-generic", |
6763f5ea2 crypto: ecdh - mo... |
162 163 164 165 166 |
.cra_priority = 100, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ecdh_ctx), }, }; |
815413252 crypto: ecdh - re... |
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
static int ecdh_nist_p384_init_tfm(struct crypto_kpp *tfm) { struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); ctx->curve_id = ECC_CURVE_NIST_P384; ctx->ndigits = ECC_CURVE_NIST_P384_DIGITS; return 0; } static struct kpp_alg ecdh_nist_p384 = { .set_secret = ecdh_set_secret, .generate_public_key = ecdh_compute_value, .compute_shared_secret = ecdh_compute_value, .max_size = ecdh_max_size, .init = ecdh_nist_p384_init_tfm, .base = { .cra_name = "ecdh-nist-p384", .cra_driver_name = "ecdh-nist-p384-generic", .cra_priority = 100, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ecdh_ctx), }, }; |
6763f5ea2 crypto: ecdh - mo... |
191 |
static bool ecdh_nist_p192_registered; |
3c4b23901 crypto: ecdh - Ad... |
192 193 |
static int ecdh_init(void) { |
6763f5ea2 crypto: ecdh - mo... |
194 |
int ret; |
6889fc210 crypto: ecdh - fi... |
195 |
/* NIST p192 will fail to register in FIPS mode */ |
6763f5ea2 crypto: ecdh - mo... |
196 197 |
ret = crypto_register_kpp(&ecdh_nist_p192); ecdh_nist_p192_registered = ret == 0; |
8fd28fa50 crypto: ecdh - fi... |
198 199 200 |
ret = crypto_register_kpp(&ecdh_nist_p256); if (ret) goto nist_p256_error; |
815413252 crypto: ecdh - re... |
201 202 203 |
ret = crypto_register_kpp(&ecdh_nist_p384); if (ret) goto nist_p384_error; |
8fd28fa50 crypto: ecdh - fi... |
204 |
return 0; |
815413252 crypto: ecdh - re... |
205 206 |
nist_p384_error: crypto_unregister_kpp(&ecdh_nist_p256); |
8fd28fa50 crypto: ecdh - fi... |
207 208 209 210 |
nist_p256_error: if (ecdh_nist_p192_registered) crypto_unregister_kpp(&ecdh_nist_p192); return ret; |
3c4b23901 crypto: ecdh - Ad... |
211 212 213 214 |
} static void ecdh_exit(void) { |
6763f5ea2 crypto: ecdh - mo... |
215 216 217 |
if (ecdh_nist_p192_registered) crypto_unregister_kpp(&ecdh_nist_p192); crypto_unregister_kpp(&ecdh_nist_p256); |
815413252 crypto: ecdh - re... |
218 |
crypto_unregister_kpp(&ecdh_nist_p384); |
3c4b23901 crypto: ecdh - Ad... |
219 |
} |
c4741b230 crypto: run initc... |
220 |
subsys_initcall(ecdh_init); |
3c4b23901 crypto: ecdh - Ad... |
221 222 223 224 |
module_exit(ecdh_exit); MODULE_ALIAS_CRYPTO("ecdh"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("ECDH generic algorithm"); |