Blame view

crypto/ecdh.c 3.86 KB
3c4b23901   Salvatore Benedetto   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   Tudor-Dan Ambarus   crypto: kpp, (ec)...
7
   * modify it under the terms of the GNU General Public License
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
8
   * as published by the Free Software Foundation; either version
c0ca1215d   Tudor-Dan Ambarus   crypto: kpp, (ec)...
9
   * 2 of the License, or (at your option) any later version.
3c4b23901   Salvatore Benedetto   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   Salvatore Benedetto   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   Kees Cook   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   Salvatore Benedetto   crypto: ecdh - Ad...
35
36
37
  	default: return 0;
  	}
  }
5527dfb6d   Eric Biggers   crypto: kpp - con...
38
39
  static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
  			   unsigned int len)
3c4b23901   Salvatore Benedetto   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, &params) < 0)
  		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...
54
55
56
  	if (!params.key || !params.key_size)
  		return ecc_gen_privkey(ctx->curve_id, ctx->ndigits,
  				       ctx->private_key);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
57
  	if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
ad2695971   Tudor-Dan Ambarus   crypto: ecc - rem...
58
  			     (const u64 *)params.key, params.key_size) < 0)
3c4b23901   Salvatore Benedetto   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   Salvatore Benedetto   crypto: ecdh - Ad...
68
69
  	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
  	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
70
71
  	u64 *public_key;
  	u64 *shared_secret = NULL;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
72
  	void *buf;
952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
73
74
  	size_t copied, nbytes, public_key_sz;
  	int ret = -ENOMEM;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
75
76
  
  	nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
952035bae   Tudor-Dan Ambarus   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   Salvatore Benedetto   crypto: ecdh - Ad...
83
84
  
  	if (req->src) {
952035bae   Tudor-Dan Ambarus   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   Salvatore Benedetto   crypto: ecdh - Ad...
95

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

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

952035bae   Tudor-Dan Ambarus   crypto: ecdh - fi...
115
116
117
118
119
  	/* fall through */
  free_all:
  	kzfree(shared_secret);
  free_pubkey:
  	kfree(public_key);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
120
121
  	return ret;
  }
d0efb48b8   Tudor-Dan Ambarus   crypto: ecdh - co...
122
  static unsigned int ecdh_max_size(struct crypto_kpp *tfm)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
123
124
  {
  	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
125

d0efb48b8   Tudor-Dan Ambarus   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   Salvatore Benedetto   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");