Blame view

crypto/rsa.c 5.31 KB
b4d0d230c   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
2
3
4
5
  /* RSA asymmetric public-key algorithm [RFC3447]
   *
   * Copyright (c) 2015, Intel Corporation
   * Authors: Tadeusz Struk <tadeusz.struk@intel.com>
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
6
7
8
   */
  
  #include <linux/module.h>
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
9
  #include <linux/mpi.h>
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
10
11
12
  #include <crypto/internal/rsa.h>
  #include <crypto/internal/akcipher.h>
  #include <crypto/akcipher.h>
3d5b1ecde   Andrzej Zaborowski   crypto: rsa - RSA...
13
  #include <crypto/algapi.h>
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
14

5a7de9730   Tudor Ambarus   crypto: rsa - ret...
15
16
17
18
19
  struct rsa_mpi_key {
  	MPI n;
  	MPI e;
  	MPI d;
  };
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
20
21
22
23
  /*
   * RSAEP function [RFC3447 sec 5.1.1]
   * c = m^e mod n;
   */
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
24
  static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
25
26
27
28
29
30
31
32
33
34
35
36
37
  {
  	/* (1) Validate 0 <= m < n */
  	if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
  		return -EINVAL;
  
  	/* (2) c = m^e mod n */
  	return mpi_powm(c, m, key->e, key->n);
  }
  
  /*
   * RSADP function [RFC3447 sec 5.1.2]
   * m = c^d mod n;
   */
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
38
  static int _rsa_dec(const struct rsa_mpi_key *key, MPI m, MPI c)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
39
40
41
42
43
44
45
46
  {
  	/* (1) Validate 0 <= c < n */
  	if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0)
  		return -EINVAL;
  
  	/* (2) m = c^d mod n */
  	return mpi_powm(m, c, key->d, key->n);
  }
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
47
  static inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher *tfm)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
48
49
50
51
52
53
54
  {
  	return akcipher_tfm_ctx(tfm);
  }
  
  static int rsa_enc(struct akcipher_request *req)
  {
  	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
55
  	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
56
57
58
59
60
61
62
63
64
65
66
  	MPI m, c = mpi_alloc(0);
  	int ret = 0;
  	int sign;
  
  	if (!c)
  		return -ENOMEM;
  
  	if (unlikely(!pkey->n || !pkey->e)) {
  		ret = -EINVAL;
  		goto err_free_c;
  	}
22287b0b5   Tadeusz Struk   crypto: akcipher ...
67
68
69
  	ret = -ENOMEM;
  	m = mpi_read_raw_from_sgl(req->src, req->src_len);
  	if (!m)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
70
  		goto err_free_c;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
71
72
73
74
  
  	ret = _rsa_enc(pkey, c, m);
  	if (ret)
  		goto err_free_m;
9b45b7bba   Herbert Xu   crypto: rsa - Gen...
75
  	ret = mpi_write_to_sgl(c, req->dst, req->dst_len, &sign);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
76
77
  	if (ret)
  		goto err_free_m;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
78
  	if (sign < 0)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
79
  		ret = -EBADMSG;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
80
81
82
83
84
85
86
87
88
89
90
  
  err_free_m:
  	mpi_free(m);
  err_free_c:
  	mpi_free(c);
  	return ret;
  }
  
  static int rsa_dec(struct akcipher_request *req)
  {
  	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
91
  	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
92
93
94
95
96
97
98
99
100
101
102
  	MPI c, m = mpi_alloc(0);
  	int ret = 0;
  	int sign;
  
  	if (!m)
  		return -ENOMEM;
  
  	if (unlikely(!pkey->n || !pkey->d)) {
  		ret = -EINVAL;
  		goto err_free_m;
  	}
22287b0b5   Tadeusz Struk   crypto: akcipher ...
103
104
105
  	ret = -ENOMEM;
  	c = mpi_read_raw_from_sgl(req->src, req->src_len);
  	if (!c)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
106
  		goto err_free_m;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
107
108
109
110
  
  	ret = _rsa_dec(pkey, m, c);
  	if (ret)
  		goto err_free_c;
9b45b7bba   Herbert Xu   crypto: rsa - Gen...
111
  	ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
112
113
  	if (ret)
  		goto err_free_c;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
114
  	if (sign < 0)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
115
  		ret = -EBADMSG;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
116
117
118
119
120
121
  err_free_c:
  	mpi_free(c);
  err_free_m:
  	mpi_free(m);
  	return ret;
  }
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
122
123
124
125
126
127
128
129
130
  static void rsa_free_mpi_key(struct rsa_mpi_key *key)
  {
  	mpi_free(key->d);
  	mpi_free(key->e);
  	mpi_free(key->n);
  	key->d = NULL;
  	key->e = NULL;
  	key->n = NULL;
  }
6e8ec66c3   Tadeusz Struk   crypto: rsa - lim...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  static int rsa_check_key_length(unsigned int len)
  {
  	switch (len) {
  	case 512:
  	case 1024:
  	case 1536:
  	case 2048:
  	case 3072:
  	case 4096:
  		return 0;
  	}
  
  	return -EINVAL;
  }
22287b0b5   Tadeusz Struk   crypto: akcipher ...
145
146
  static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
  			   unsigned int keylen)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
147
  {
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
148
149
  	struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm);
  	struct rsa_key raw_key = {0};
6e8ec66c3   Tadeusz Struk   crypto: rsa - lim...
150
  	int ret;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
151

5a7de9730   Tudor Ambarus   crypto: rsa - ret...
152
153
154
155
  	/* Free the old MPI key if any */
  	rsa_free_mpi_key(mpi_key);
  
  	ret = rsa_parse_pub_key(&raw_key, key, keylen);
6e8ec66c3   Tadeusz Struk   crypto: rsa - lim...
156
157
  	if (ret)
  		return ret;
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
158
159
160
161
162
163
164
165
166
167
168
  	mpi_key->e = mpi_read_raw_data(raw_key.e, raw_key.e_sz);
  	if (!mpi_key->e)
  		goto err;
  
  	mpi_key->n = mpi_read_raw_data(raw_key.n, raw_key.n_sz);
  	if (!mpi_key->n)
  		goto err;
  
  	if (rsa_check_key_length(mpi_get_size(mpi_key->n) << 3)) {
  		rsa_free_mpi_key(mpi_key);
  		return -EINVAL;
6e8ec66c3   Tadeusz Struk   crypto: rsa - lim...
169
  	}
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
170
171
172
173
174
175
  
  	return 0;
  
  err:
  	rsa_free_mpi_key(mpi_key);
  	return -ENOMEM;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
176
  }
22287b0b5   Tadeusz Struk   crypto: akcipher ...
177
178
179
  static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
  			    unsigned int keylen)
  {
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
180
181
  	struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm);
  	struct rsa_key raw_key = {0};
22287b0b5   Tadeusz Struk   crypto: akcipher ...
182
  	int ret;
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
183
184
185
186
  	/* Free the old MPI key if any */
  	rsa_free_mpi_key(mpi_key);
  
  	ret = rsa_parse_priv_key(&raw_key, key, keylen);
22287b0b5   Tadeusz Struk   crypto: akcipher ...
187
188
  	if (ret)
  		return ret;
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  	mpi_key->d = mpi_read_raw_data(raw_key.d, raw_key.d_sz);
  	if (!mpi_key->d)
  		goto err;
  
  	mpi_key->e = mpi_read_raw_data(raw_key.e, raw_key.e_sz);
  	if (!mpi_key->e)
  		goto err;
  
  	mpi_key->n = mpi_read_raw_data(raw_key.n, raw_key.n_sz);
  	if (!mpi_key->n)
  		goto err;
  
  	if (rsa_check_key_length(mpi_get_size(mpi_key->n) << 3)) {
  		rsa_free_mpi_key(mpi_key);
  		return -EINVAL;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
204
  	}
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
205
206
207
208
209
210
  
  	return 0;
  
  err:
  	rsa_free_mpi_key(mpi_key);
  	return -ENOMEM;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
211
  }
1c23b466e   Tudor-Dan Ambarus   crypto: rsa - com...
212
  static unsigned int rsa_max_size(struct crypto_akcipher *tfm)
22287b0b5   Tadeusz Struk   crypto: akcipher ...
213
  {
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
214
  	struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm);
22287b0b5   Tadeusz Struk   crypto: akcipher ...
215

1c23b466e   Tudor-Dan Ambarus   crypto: rsa - com...
216
  	return mpi_get_size(pkey->n);
22287b0b5   Tadeusz Struk   crypto: akcipher ...
217
  }
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
218
219
  static void rsa_exit_tfm(struct crypto_akcipher *tfm)
  {
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
220
  	struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
221

5a7de9730   Tudor Ambarus   crypto: rsa - ret...
222
  	rsa_free_mpi_key(pkey);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
223
224
225
226
227
  }
  
  static struct akcipher_alg rsa = {
  	.encrypt = rsa_enc,
  	.decrypt = rsa_dec,
22287b0b5   Tadeusz Struk   crypto: akcipher ...
228
229
230
  	.set_priv_key = rsa_set_priv_key,
  	.set_pub_key = rsa_set_pub_key,
  	.max_size = rsa_max_size,
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
231
232
233
234
235
236
  	.exit = rsa_exit_tfm,
  	.base = {
  		.cra_name = "rsa",
  		.cra_driver_name = "rsa-generic",
  		.cra_priority = 100,
  		.cra_module = THIS_MODULE,
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
237
  		.cra_ctxsize = sizeof(struct rsa_mpi_key),
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
238
239
240
241
242
  	},
  };
  
  static int rsa_init(void)
  {
3d5b1ecde   Andrzej Zaborowski   crypto: rsa - RSA...
243
244
245
246
247
248
249
250
251
252
253
254
255
  	int err;
  
  	err = crypto_register_akcipher(&rsa);
  	if (err)
  		return err;
  
  	err = crypto_register_template(&rsa_pkcs1pad_tmpl);
  	if (err) {
  		crypto_unregister_akcipher(&rsa);
  		return err;
  	}
  
  	return 0;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
256
257
258
259
  }
  
  static void rsa_exit(void)
  {
3d5b1ecde   Andrzej Zaborowski   crypto: rsa - RSA...
260
  	crypto_unregister_template(&rsa_pkcs1pad_tmpl);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
261
262
  	crypto_unregister_akcipher(&rsa);
  }
c4741b230   Eric Biggers   crypto: run initc...
263
  subsys_initcall(rsa_init);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
264
265
266
267
  module_exit(rsa_exit);
  MODULE_ALIAS_CRYPTO("rsa");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("RSA generic algorithm");