Blame view

crypto/ecdh.c 5.7 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
2
3
4
5
  /* ECDH key-agreement protocol
   *
   * Copyright (c) 2016, Intel Corporation
   * Authors: Salvator Benedetto <salvatore.benedetto@intel.com>
3c4b23901   Salvatore Benedetto   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   Salvatore Benedetto   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   Eric Biggers   crypto: kpp - con...
25
26
  static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
  			   unsigned int len)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
27
28
29
  {
  	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
  	struct ecdh params;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
30

0aa171e9b   Ard Biesheuvel   crypto: ecdh - av...
31
  	if (crypto_ecdh_decode_key(buf, len, &params) < 0 ||
6763f5ea2   Meng Yu   crypto: ecdh - mo...
32
  	    params.key_size > sizeof(u64) * ctx->ndigits)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
33
  		return -EINVAL;
6755fd269   Tudor-Dan Ambarus   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   Salvatore Benedetto   crypto: ecdh - Ad...
37
  	memcpy(ctx->private_key, params.key, params.key_size);
17858b140   Ard Biesheuvel   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   Salvatore Benedetto   crypto: ecdh - Ad...
43
44
45
46
47
  	return 0;
  }
  
  static int ecdh_compute_value(struct kpp_request *req)
  {
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
48
49
  	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
  	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
50
51
  	u64 *public_key;
  	u64 *shared_secret = NULL;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
52
  	void *buf;
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
53
54
  	size_t copied, nbytes, public_key_sz;
  	int ret = -ENOMEM;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
55
56
  
  	nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
952035bae   Tudor-Dan Ambarus   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   Salvatore Benedetto   crypto: ecdh - Ad...
63
64
  
  	if (req->src) {
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
65
66
67
  		shared_secret = kmalloc(nbytes, GFP_KERNEL);
  		if (!shared_secret)
  			goto free_pubkey;
95ec01ba1   James Bottomley   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   Tudor-Dan Ambarus   crypto: ecdh - fi...
80
  			goto free_all;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
81

8f44df154   Stephen Rothwell   crypto: ecdh - ma...
82
  		ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits,
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
83
84
  						ctx->private_key, public_key,
  						shared_secret);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
85

952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
86
  		buf = shared_secret;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
87
  	} else {
7380c56d2   Tudor-Dan Ambarus   crypto: ecc - ren...
88
  		ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits,
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
89
90
91
  				       ctx->private_key, public_key);
  		buf = public_key;
  		nbytes = public_key_sz;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
92
93
94
  	}
  
  	if (ret < 0)
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
95
  		goto free_all;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
96

95ec01ba1   James Bottomley   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   Salvatore Benedetto   crypto: ecdh - Ad...
102
  	if (copied != nbytes)
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
103
  		ret = -EINVAL;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
104

952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
105
106
  	/* fall through */
  free_all:
453431a54   Waiman Long   mm, treewide: ren...
107
  	kfree_sensitive(shared_secret);
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
108
109
  free_pubkey:
  	kfree(public_key);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
110
111
  	return ret;
  }
d0efb48b8   Tudor-Dan Ambarus   crypto: ecdh - co...
112
  static unsigned int ecdh_max_size(struct crypto_kpp *tfm)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
113
114
  {
  	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
115

d0efb48b8   Tudor-Dan Ambarus   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   Salvatore Benedetto   crypto: ecdh - Ad...
118
  }
6763f5ea2   Meng Yu   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   Salvatore Benedetto   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   Meng Yu   crypto: ecdh - mo...
134
  	.init = ecdh_nist_p192_init_tfm,
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
135
  	.base = {
6763f5ea2   Meng Yu   crypto: ecdh - mo...
136
  		.cra_name = "ecdh-nist-p192",
c5ae16f5c   Hui Tang   crypto: ecdh - ex...
137
  		.cra_driver_name = "ecdh-nist-p192-generic",
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
138
139
140
141
142
  		.cra_priority = 100,
  		.cra_module = THIS_MODULE,
  		.cra_ctxsize = sizeof(struct ecdh_ctx),
  	},
  };
6763f5ea2   Meng Yu   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   Hui Tang   crypto: ecdh - ex...
161
  		.cra_driver_name = "ecdh-nist-p256-generic",
6763f5ea2   Meng Yu   crypto: ecdh - mo...
162
163
164
165
166
  		.cra_priority = 100,
  		.cra_module = THIS_MODULE,
  		.cra_ctxsize = sizeof(struct ecdh_ctx),
  	},
  };
815413252   Hui Tang   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   Meng Yu   crypto: ecdh - mo...
191
  static bool ecdh_nist_p192_registered;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
192
193
  static int ecdh_init(void)
  {
6763f5ea2   Meng Yu   crypto: ecdh - mo...
194
  	int ret;
6889fc210   Hui Tang   crypto: ecdh - fi...
195
  	/* NIST p192 will fail to register in FIPS mode */
6763f5ea2   Meng Yu   crypto: ecdh - mo...
196
197
  	ret = crypto_register_kpp(&ecdh_nist_p192);
  	ecdh_nist_p192_registered = ret == 0;
8fd28fa50   Hui Tang   crypto: ecdh - fi...
198
199
200
  	ret = crypto_register_kpp(&ecdh_nist_p256);
  	if (ret)
  		goto nist_p256_error;
815413252   Hui Tang   crypto: ecdh - re...
201
202
203
  	ret = crypto_register_kpp(&ecdh_nist_p384);
  	if (ret)
  		goto nist_p384_error;
8fd28fa50   Hui Tang   crypto: ecdh - fi...
204
  	return 0;
815413252   Hui Tang   crypto: ecdh - re...
205
206
  nist_p384_error:
  	crypto_unregister_kpp(&ecdh_nist_p256);
8fd28fa50   Hui Tang   crypto: ecdh - fi...
207
208
209
210
  nist_p256_error:
  	if (ecdh_nist_p192_registered)
  		crypto_unregister_kpp(&ecdh_nist_p192);
  	return ret;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
211
212
213
214
  }
  
  static void ecdh_exit(void)
  {
6763f5ea2   Meng Yu   crypto: ecdh - mo...
215
216
217
  	if (ecdh_nist_p192_registered)
  		crypto_unregister_kpp(&ecdh_nist_p192);
  	crypto_unregister_kpp(&ecdh_nist_p256);
815413252   Hui Tang   crypto: ecdh - re...
218
  	crypto_unregister_kpp(&ecdh_nist_p384);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
219
  }
c4741b230   Eric Biggers   crypto: run initc...
220
  subsys_initcall(ecdh_init);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
221
222
223
224
  module_exit(ecdh_exit);
  MODULE_ALIAS_CRYPTO("ecdh");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("ECDH generic algorithm");