Blame view

crypto/rsa.c 7.49 KB
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
1
2
3
4
5
6
7
8
9
10
11
12
  /* RSA asymmetric public-key algorithm [RFC3447]
   *
   * Copyright (c) 2015, Intel Corporation
   * Authors: Tadeusz Struk <tadeusz.struk@intel.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public Licence
   * as published by the Free Software Foundation; either version
   * 2 of the Licence, or (at your option) any later version.
   */
  
  #include <linux/module.h>
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
13
  #include <linux/mpi.h>
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
14
15
16
  #include <crypto/internal/rsa.h>
  #include <crypto/internal/akcipher.h>
  #include <crypto/akcipher.h>
3d5b1ecde   Andrzej Zaborowski   crypto: rsa - RSA...
17
  #include <crypto/algapi.h>
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
18

5a7de9730   Tudor Ambarus   crypto: rsa - ret...
19
20
21
22
23
  struct rsa_mpi_key {
  	MPI n;
  	MPI e;
  	MPI d;
  };
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
24
25
26
27
  /*
   * RSAEP function [RFC3447 sec 5.1.1]
   * c = m^e mod n;
   */
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
28
  static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
29
30
31
32
33
34
35
36
37
38
39
40
41
  {
  	/* (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...
42
  static int _rsa_dec(const struct rsa_mpi_key *key, MPI m, MPI c)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
43
44
45
46
47
48
49
50
51
52
53
54
55
  {
  	/* (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);
  }
  
  /*
   * RSASP1 function [RFC3447 sec 5.2.1]
   * s = m^d mod n
   */
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
56
  static int _rsa_sign(const struct rsa_mpi_key *key, MPI s, MPI m)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
57
58
59
60
61
62
63
64
65
66
67
68
69
  {
  	/* (1) Validate 0 <= m < n */
  	if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
  		return -EINVAL;
  
  	/* (2) s = m^d mod n */
  	return mpi_powm(s, m, key->d, key->n);
  }
  
  /*
   * RSAVP1 function [RFC3447 sec 5.2.2]
   * m = s^e mod n;
   */
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
70
  static int _rsa_verify(const struct rsa_mpi_key *key, MPI m, MPI s)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
71
72
73
74
75
76
77
78
  {
  	/* (1) Validate 0 <= s < n */
  	if (mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0)
  		return -EINVAL;
  
  	/* (2) m = s^e mod n */
  	return mpi_powm(m, s, key->e, key->n);
  }
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
79
  static inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher *tfm)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
80
81
82
83
84
85
86
  {
  	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...
87
  	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
88
89
90
91
92
93
94
95
96
97
98
  	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 ...
99
100
101
  	ret = -ENOMEM;
  	m = mpi_read_raw_from_sgl(req->src, req->src_len);
  	if (!m)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
102
  		goto err_free_c;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
103
104
105
106
  
  	ret = _rsa_enc(pkey, c, m);
  	if (ret)
  		goto err_free_m;
9b45b7bba   Herbert Xu   crypto: rsa - Gen...
107
  	ret = mpi_write_to_sgl(c, req->dst, req->dst_len, &sign);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
108
109
  	if (ret)
  		goto err_free_m;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
110
  	if (sign < 0)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
111
  		ret = -EBADMSG;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
112
113
114
115
116
117
118
119
120
121
122
  
  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...
123
  	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
124
125
126
127
128
129
130
131
132
133
134
  	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 ...
135
136
137
  	ret = -ENOMEM;
  	c = mpi_read_raw_from_sgl(req->src, req->src_len);
  	if (!c)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
138
  		goto err_free_m;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
139
140
141
142
  
  	ret = _rsa_dec(pkey, m, c);
  	if (ret)
  		goto err_free_c;
9b45b7bba   Herbert Xu   crypto: rsa - Gen...
143
  	ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
144
145
  	if (ret)
  		goto err_free_c;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
146
  	if (sign < 0)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
147
  		ret = -EBADMSG;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
148
149
150
151
152
153
154
155
156
157
  err_free_c:
  	mpi_free(c);
  err_free_m:
  	mpi_free(m);
  	return ret;
  }
  
  static int rsa_sign(struct akcipher_request *req)
  {
  	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
158
  	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
159
160
161
162
163
164
165
166
167
168
169
  	MPI m, s = mpi_alloc(0);
  	int ret = 0;
  	int sign;
  
  	if (!s)
  		return -ENOMEM;
  
  	if (unlikely(!pkey->n || !pkey->d)) {
  		ret = -EINVAL;
  		goto err_free_s;
  	}
22287b0b5   Tadeusz Struk   crypto: akcipher ...
170
171
172
  	ret = -ENOMEM;
  	m = mpi_read_raw_from_sgl(req->src, req->src_len);
  	if (!m)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
173
  		goto err_free_s;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
174
175
176
177
  
  	ret = _rsa_sign(pkey, s, m);
  	if (ret)
  		goto err_free_m;
9b45b7bba   Herbert Xu   crypto: rsa - Gen...
178
  	ret = mpi_write_to_sgl(s, req->dst, req->dst_len, &sign);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
179
180
  	if (ret)
  		goto err_free_m;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
181
  	if (sign < 0)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
182
  		ret = -EBADMSG;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
183
184
185
186
187
188
189
190
191
192
193
  
  err_free_m:
  	mpi_free(m);
  err_free_s:
  	mpi_free(s);
  	return ret;
  }
  
  static int rsa_verify(struct akcipher_request *req)
  {
  	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
194
  	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
195
196
197
198
199
200
201
202
203
204
205
  	MPI s, m = mpi_alloc(0);
  	int ret = 0;
  	int sign;
  
  	if (!m)
  		return -ENOMEM;
  
  	if (unlikely(!pkey->n || !pkey->e)) {
  		ret = -EINVAL;
  		goto err_free_m;
  	}
22287b0b5   Tadeusz Struk   crypto: akcipher ...
206
207
  	ret = -ENOMEM;
  	s = mpi_read_raw_from_sgl(req->src, req->src_len);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
208
209
210
211
212
213
214
215
  	if (!s) {
  		ret = -ENOMEM;
  		goto err_free_m;
  	}
  
  	ret = _rsa_verify(pkey, m, s);
  	if (ret)
  		goto err_free_s;
9b45b7bba   Herbert Xu   crypto: rsa - Gen...
216
  	ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
217
218
  	if (ret)
  		goto err_free_s;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
219
  	if (sign < 0)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
220
  		ret = -EBADMSG;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
221
222
223
224
225
226
227
  
  err_free_s:
  	mpi_free(s);
  err_free_m:
  	mpi_free(m);
  	return ret;
  }
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
228
229
230
231
232
233
234
235
236
  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...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  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 ...
251
252
  static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
  			   unsigned int keylen)
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
253
  {
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
254
255
  	struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm);
  	struct rsa_key raw_key = {0};
6e8ec66c3   Tadeusz Struk   crypto: rsa - lim...
256
  	int ret;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
257

5a7de9730   Tudor Ambarus   crypto: rsa - ret...
258
259
260
261
  	/* 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...
262
263
  	if (ret)
  		return ret;
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
264
265
266
267
268
269
270
271
272
273
274
  	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...
275
  	}
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
276
277
278
279
280
281
  
  	return 0;
  
  err:
  	rsa_free_mpi_key(mpi_key);
  	return -ENOMEM;
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
282
  }
22287b0b5   Tadeusz Struk   crypto: akcipher ...
283
284
285
  static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
  			    unsigned int keylen)
  {
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
286
287
  	struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm);
  	struct rsa_key raw_key = {0};
22287b0b5   Tadeusz Struk   crypto: akcipher ...
288
  	int ret;
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
289
290
291
292
  	/* 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 ...
293
294
  	if (ret)
  		return ret;
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  	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 ...
310
  	}
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
311
312
313
314
315
316
  
  	return 0;
  
  err:
  	rsa_free_mpi_key(mpi_key);
  	return -ENOMEM;
22287b0b5   Tadeusz Struk   crypto: akcipher ...
317
318
319
320
  }
  
  static int rsa_max_size(struct crypto_akcipher *tfm)
  {
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
321
  	struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm);
22287b0b5   Tadeusz Struk   crypto: akcipher ...
322
323
324
  
  	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
  }
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
325
326
  static void rsa_exit_tfm(struct crypto_akcipher *tfm)
  {
5a7de9730   Tudor Ambarus   crypto: rsa - ret...
327
  	struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
328

5a7de9730   Tudor Ambarus   crypto: rsa - ret...
329
  	rsa_free_mpi_key(pkey);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
330
331
332
333
334
335
336
  }
  
  static struct akcipher_alg rsa = {
  	.encrypt = rsa_enc,
  	.decrypt = rsa_dec,
  	.sign = rsa_sign,
  	.verify = rsa_verify,
22287b0b5   Tadeusz Struk   crypto: akcipher ...
337
338
339
  	.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...
340
341
342
343
344
345
  	.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...
346
  		.cra_ctxsize = sizeof(struct rsa_mpi_key),
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
347
348
349
350
351
  	},
  };
  
  static int rsa_init(void)
  {
3d5b1ecde   Andrzej Zaborowski   crypto: rsa - RSA...
352
353
354
355
356
357
358
359
360
361
362
363
364
  	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...
365
366
367
368
  }
  
  static void rsa_exit(void)
  {
3d5b1ecde   Andrzej Zaborowski   crypto: rsa - RSA...
369
  	crypto_unregister_template(&rsa_pkcs1pad_tmpl);
cfc2bb32b   Tadeusz Struk   crypto: rsa - add...
370
371
372
373
374
375
376
377
  	crypto_unregister_akcipher(&rsa);
  }
  
  module_init(rsa_init);
  module_exit(rsa_exit);
  MODULE_ALIAS_CRYPTO("rsa");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("RSA generic algorithm");