Blame view

crypto/ecdh.c 4.02 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
25
26
27
28
  };
  
  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) {
d5c3b1789   Kees Cook   crypto: ecc - Act...
29
30
  	case ECC_CURVE_NIST_P192: return ECC_CURVE_NIST_P192_DIGITS;
  	case ECC_CURVE_NIST_P256: return ECC_CURVE_NIST_P256_DIGITS;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
31
32
33
  	default: return 0;
  	}
  }
5527dfb6d   Eric Biggers   crypto: kpp - con...
34
35
  static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
  			   unsigned int len)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
36
37
38
39
  {
  	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
  	struct ecdh params;
  	unsigned int ndigits;
3f20005ab   Ard Biesheuvel   crypto: ecdh - av...
40
41
  	if (crypto_ecdh_decode_key(buf, len, &params) < 0 ||
  	    params.key_size > sizeof(ctx->private_key))
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
42
43
44
45
46
47
48
49
  		return -EINVAL;
  
  	ndigits = ecdh_supported_curve(params.curve_id);
  	if (!ndigits)
  		return -EINVAL;
  
  	ctx->curve_id = params.curve_id;
  	ctx->ndigits = ndigits;
6755fd269   Tudor-Dan Ambarus   crypto: ecdh - ad...
50
51
52
  	if (!params.key || !params.key_size)
  		return ecc_gen_privkey(ctx->curve_id, ctx->ndigits,
  				       ctx->private_key);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
53
  	memcpy(ctx->private_key, params.key, params.key_size);
c49bfdb52   Ard Biesheuvel   crypto: ecdh - av...
54
55
56
57
58
  	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...
59
60
61
62
63
  	return 0;
  }
  
  static int ecdh_compute_value(struct kpp_request *req)
  {
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
64
65
  	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
  	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
66
67
  	u64 *public_key;
  	u64 *shared_secret = NULL;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
68
  	void *buf;
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
69
70
  	size_t copied, nbytes, public_key_sz;
  	int ret = -ENOMEM;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
71
72
  
  	nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
73
74
75
76
77
78
  	/* 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...
79
80
  
  	if (req->src) {
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
81
82
83
  		shared_secret = kmalloc(nbytes, GFP_KERNEL);
  		if (!shared_secret)
  			goto free_pubkey;
95ec01ba1   James Bottomley   crypto: ecdh - fi...
84
85
86
87
88
89
90
91
92
93
94
95
  		/* 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...
96
  			goto free_all;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
97

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

952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
102
  		buf = shared_secret;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
103
  	} else {
7380c56d2   Tudor-Dan Ambarus   crypto: ecc - ren...
104
  		ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits,
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
105
106
107
  				       ctx->private_key, public_key);
  		buf = public_key;
  		nbytes = public_key_sz;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
108
109
110
  	}
  
  	if (ret < 0)
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
111
  		goto free_all;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
112

95ec01ba1   James Bottomley   crypto: ecdh - fi...
113
114
115
116
117
  	/* 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...
118
  	if (copied != nbytes)
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
119
  		ret = -EINVAL;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
120

952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
121
122
  	/* fall through */
  free_all:
453431a54   Waiman Long   mm, treewide: ren...
123
  	kfree_sensitive(shared_secret);
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
124
125
  free_pubkey:
  	kfree(public_key);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
126
127
  	return ret;
  }
d0efb48b8   Tudor-Dan Ambarus   crypto: ecdh - co...
128
  static unsigned int ecdh_max_size(struct crypto_kpp *tfm)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
129
130
  {
  	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
131

d0efb48b8   Tudor-Dan Ambarus   crypto: ecdh - co...
132
133
  	/* 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...
134
  }
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
135
136
137
138
139
  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,
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
  	.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);
  }
c4741b230   Eric Biggers   crypto: run initc...
158
  subsys_initcall(ecdh_init);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
159
160
161
162
  module_exit(ecdh_exit);
  MODULE_ALIAS_CRYPTO("ecdh");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("ECDH generic algorithm");