1 | /* RSA asymmetric public-key algorithm [RFC3447] |
---|---|

2 | * |

3 | * Copyright (c) 2015, Intel Corporation |

4 | * Authors: Tadeusz Struk <tadeusz.struk@intel.com> |

5 | * |

6 | * This program is free software; you can redistribute it and/or |

7 | * modify it under the terms of the GNU General Public Licence |

8 | * as published by the Free Software Foundation; either version |

9 | * 2 of the Licence, or (at your option) any later version. |

10 | */ |

11 | |

12 | #include <linux/module.h> |

13 | #include <linux/mpi.h> |

14 | #include <crypto/internal/rsa.h> |

15 | #include <crypto/internal/akcipher.h> |

16 | #include <crypto/akcipher.h> |

17 | #include <crypto/algapi.h> |

18 | |

19 | struct rsa_mpi_key { |

20 | MPI n; |

21 | MPI e; |

22 | MPI d; |

23 | }; |

24 | |

25 | /* |

26 | * RSAEP function [RFC3447 sec 5.1.1] |

27 | * c = m^e mod n; |

28 | */ |

29 | static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m) |

30 | { |

31 | /* (1) Validate 0 <= m < n */ |

32 | if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0) |

33 | return -EINVAL; |

34 | |

35 | /* (2) c = m^e mod n */ |

36 | return mpi_powm(c, m, key->e, key->n); |

37 | } |

38 | |

39 | /* |

40 | * RSADP function [RFC3447 sec 5.1.2] |

41 | * m = c^d mod n; |

42 | */ |

43 | static int _rsa_dec(const struct rsa_mpi_key *key, MPI m, MPI c) |

44 | { |

45 | /* (1) Validate 0 <= c < n */ |

46 | if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0) |

47 | return -EINVAL; |

48 | |

49 | /* (2) m = c^d mod n */ |

50 | return mpi_powm(m, c, key->d, key->n); |

51 | } |

52 | |

53 | /* |

54 | * RSASP1 function [RFC3447 sec 5.2.1] |

55 | * s = m^d mod n |

56 | */ |

57 | static int _rsa_sign(const struct rsa_mpi_key *key, MPI s, MPI m) |

58 | { |

59 | /* (1) Validate 0 <= m < n */ |

60 | if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0) |

61 | return -EINVAL; |

62 | |

63 | /* (2) s = m^d mod n */ |

64 | return mpi_powm(s, m, key->d, key->n); |

65 | } |

66 | |

67 | /* |

68 | * RSAVP1 function [RFC3447 sec 5.2.2] |

69 | * m = s^e mod n; |

70 | */ |

71 | static int _rsa_verify(const struct rsa_mpi_key *key, MPI m, MPI s) |

72 | { |

73 | /* (1) Validate 0 <= s < n */ |

74 | if (mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0) |

75 | return -EINVAL; |

76 | |

77 | /* (2) m = s^e mod n */ |

78 | return mpi_powm(m, s, key->e, key->n); |

79 | } |

80 | |

81 | static inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher *tfm) |

82 | { |

83 | return akcipher_tfm_ctx(tfm); |

84 | } |

85 | |

86 | static int rsa_enc(struct akcipher_request *req) |

87 | { |

88 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); |

89 | const struct rsa_mpi_key *pkey = rsa_get_key(tfm); |

90 | MPI m, c = mpi_alloc(0); |

91 | int ret = 0; |

92 | int sign; |

93 | |

94 | if (!c) |

95 | return -ENOMEM; |

96 | |

97 | if (unlikely(!pkey->n || !pkey->e)) { |

98 | ret = -EINVAL; |

99 | goto err_free_c; |

100 | } |

101 | |

102 | ret = -ENOMEM; |

103 | m = mpi_read_raw_from_sgl(req->src, req->src_len); |

104 | if (!m) |

105 | goto err_free_c; |

106 | |

107 | ret = _rsa_enc(pkey, c, m); |

108 | if (ret) |

109 | goto err_free_m; |

110 | |

111 | ret = mpi_write_to_sgl(c, req->dst, req->dst_len, &sign); |

112 | if (ret) |

113 | goto err_free_m; |

114 | |

115 | if (sign < 0) |

116 | ret = -EBADMSG; |

117 | |

118 | err_free_m: |

119 | mpi_free(m); |

120 | err_free_c: |

121 | mpi_free(c); |

122 | return ret; |

123 | } |

124 | |

125 | static int rsa_dec(struct akcipher_request *req) |

126 | { |

127 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); |

128 | const struct rsa_mpi_key *pkey = rsa_get_key(tfm); |

129 | MPI c, m = mpi_alloc(0); |

130 | int ret = 0; |

131 | int sign; |

132 | |

133 | if (!m) |

134 | return -ENOMEM; |

135 | |

136 | if (unlikely(!pkey->n || !pkey->d)) { |

137 | ret = -EINVAL; |

138 | goto err_free_m; |

139 | } |

140 | |

141 | ret = -ENOMEM; |

142 | c = mpi_read_raw_from_sgl(req->src, req->src_len); |

143 | if (!c) |

144 | goto err_free_m; |

145 | |

146 | ret = _rsa_dec(pkey, m, c); |

147 | if (ret) |

148 | goto err_free_c; |

149 | |

150 | ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign); |

151 | if (ret) |

152 | goto err_free_c; |

153 | |

154 | if (sign < 0) |

155 | ret = -EBADMSG; |

156 | err_free_c: |

157 | mpi_free(c); |

158 | err_free_m: |

159 | mpi_free(m); |

160 | return ret; |

161 | } |

162 | |

163 | static int rsa_sign(struct akcipher_request *req) |

164 | { |

165 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); |

166 | const struct rsa_mpi_key *pkey = rsa_get_key(tfm); |

167 | MPI m, s = mpi_alloc(0); |

168 | int ret = 0; |

169 | int sign; |

170 | |

171 | if (!s) |

172 | return -ENOMEM; |

173 | |

174 | if (unlikely(!pkey->n || !pkey->d)) { |

175 | ret = -EINVAL; |

176 | goto err_free_s; |

177 | } |

178 | |

179 | ret = -ENOMEM; |

180 | m = mpi_read_raw_from_sgl(req->src, req->src_len); |

181 | if (!m) |

182 | goto err_free_s; |

183 | |

184 | ret = _rsa_sign(pkey, s, m); |

185 | if (ret) |

186 | goto err_free_m; |

187 | |

188 | ret = mpi_write_to_sgl(s, req->dst, req->dst_len, &sign); |

189 | if (ret) |

190 | goto err_free_m; |

191 | |

192 | if (sign < 0) |

193 | ret = -EBADMSG; |

194 | |

195 | err_free_m: |

196 | mpi_free(m); |

197 | err_free_s: |

198 | mpi_free(s); |

199 | return ret; |

200 | } |

201 | |

202 | static int rsa_verify(struct akcipher_request *req) |

203 | { |

204 | struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); |

205 | const struct rsa_mpi_key *pkey = rsa_get_key(tfm); |

206 | MPI s, m = mpi_alloc(0); |

207 | int ret = 0; |

208 | int sign; |

209 | |

210 | if (!m) |

211 | return -ENOMEM; |

212 | |

213 | if (unlikely(!pkey->n || !pkey->e)) { |

214 | ret = -EINVAL; |

215 | goto err_free_m; |

216 | } |

217 | |

218 | s = mpi_read_raw_from_sgl(req->src, req->src_len); |

219 | if (!s) { |

220 | ret = -ENOMEM; |

221 | goto err_free_m; |

222 | } |

223 | |

224 | ret = _rsa_verify(pkey, m, s); |

225 | if (ret) |

226 | goto err_free_s; |

227 | |

228 | ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign); |

229 | if (ret) |

230 | goto err_free_s; |

231 | |

232 | if (sign < 0) |

233 | ret = -EBADMSG; |

234 | |

235 | err_free_s: |

236 | mpi_free(s); |

237 | err_free_m: |

238 | mpi_free(m); |

239 | return ret; |

240 | } |

241 | |

242 | static void rsa_free_mpi_key(struct rsa_mpi_key *key) |

243 | { |

244 | mpi_free(key->d); |

245 | mpi_free(key->e); |

246 | mpi_free(key->n); |

247 | key->d = NULL; |

248 | key->e = NULL; |

249 | key->n = NULL; |

250 | } |

251 | |

252 | static int rsa_check_key_length(unsigned int len) |

253 | { |

254 | switch (len) { |

255 | case 512: |

256 | case 1024: |

257 | case 1536: |

258 | case 2048: |

259 | case 3072: |

260 | case 4096: |

261 | return 0; |

262 | } |

263 | |

264 | return -EINVAL; |

265 | } |

266 | |

267 | static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, |

268 | unsigned int keylen) |

269 | { |

270 | struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm); |

271 | struct rsa_key raw_key = {0}; |

272 | int ret; |

273 | |

274 | /* Free the old MPI key if any */ |

275 | rsa_free_mpi_key(mpi_key); |

276 | |

277 | ret = rsa_parse_pub_key(&raw_key, key, keylen); |

278 | if (ret) |

279 | return ret; |

280 | |

281 | mpi_key->e = mpi_read_raw_data(raw_key.e, raw_key.e_sz); |

282 | if (!mpi_key->e) |

283 | goto err; |

284 | |

285 | mpi_key->n = mpi_read_raw_data(raw_key.n, raw_key.n_sz); |

286 | if (!mpi_key->n) |

287 | goto err; |

288 | |

289 | if (rsa_check_key_length(mpi_get_size(mpi_key->n) << 3)) { |

290 | rsa_free_mpi_key(mpi_key); |

291 | return -EINVAL; |

292 | } |

293 | |

294 | return 0; |

295 | |

296 | err: |

297 | rsa_free_mpi_key(mpi_key); |

298 | return -ENOMEM; |

299 | } |

300 | |

301 | static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key, |

302 | unsigned int keylen) |

303 | { |

304 | struct rsa_mpi_key *mpi_key = akcipher_tfm_ctx(tfm); |

305 | struct rsa_key raw_key = {0}; |

306 | int ret; |

307 | |

308 | /* Free the old MPI key if any */ |

309 | rsa_free_mpi_key(mpi_key); |

310 | |

311 | ret = rsa_parse_priv_key(&raw_key, key, keylen); |

312 | if (ret) |

313 | return ret; |

314 | |

315 | mpi_key->d = mpi_read_raw_data(raw_key.d, raw_key.d_sz); |

316 | if (!mpi_key->d) |

317 | goto err; |

318 | |

319 | mpi_key->e = mpi_read_raw_data(raw_key.e, raw_key.e_sz); |

320 | if (!mpi_key->e) |

321 | goto err; |

322 | |

323 | mpi_key->n = mpi_read_raw_data(raw_key.n, raw_key.n_sz); |

324 | if (!mpi_key->n) |

325 | goto err; |

326 | |

327 | if (rsa_check_key_length(mpi_get_size(mpi_key->n) << 3)) { |

328 | rsa_free_mpi_key(mpi_key); |

329 | return -EINVAL; |

330 | } |

331 | |

332 | return 0; |

333 | |

334 | err: |

335 | rsa_free_mpi_key(mpi_key); |

336 | return -ENOMEM; |

337 | } |

338 | |

339 | static unsigned int rsa_max_size(struct crypto_akcipher *tfm) |

340 | { |

341 | struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm); |

342 | |

343 | return mpi_get_size(pkey->n); |

344 | } |

345 | |

346 | static void rsa_exit_tfm(struct crypto_akcipher *tfm) |

347 | { |

348 | struct rsa_mpi_key *pkey = akcipher_tfm_ctx(tfm); |

349 | |

350 | rsa_free_mpi_key(pkey); |

351 | } |

352 | |

353 | static struct akcipher_alg rsa = { |

354 | .encrypt = rsa_enc, |

355 | .decrypt = rsa_dec, |

356 | .sign = rsa_sign, |

357 | .verify = rsa_verify, |

358 | .set_priv_key = rsa_set_priv_key, |

359 | .set_pub_key = rsa_set_pub_key, |

360 | .max_size = rsa_max_size, |

361 | .exit = rsa_exit_tfm, |

362 | .base = { |

363 | .cra_name = "rsa", |

364 | .cra_driver_name = "rsa-generic", |

365 | .cra_priority = 100, |

366 | .cra_module = THIS_MODULE, |

367 | .cra_ctxsize = sizeof(struct rsa_mpi_key), |

368 | }, |

369 | }; |

370 | |

371 | static int rsa_init(void) |

372 | { |

373 | int err; |

374 | |

375 | err = crypto_register_akcipher(&rsa); |

376 | if (err) |

377 | return err; |

378 | |

379 | err = crypto_register_template(&rsa_pkcs1pad_tmpl); |

380 | if (err) { |

381 | crypto_unregister_akcipher(&rsa); |

382 | return err; |

383 | } |

384 | |

385 | return 0; |

386 | } |

387 | |

388 | static void rsa_exit(void) |

389 | { |

390 | crypto_unregister_template(&rsa_pkcs1pad_tmpl); |

391 | crypto_unregister_akcipher(&rsa); |

392 | } |

393 | |

394 | module_init(rsa_init); |

395 | module_exit(rsa_exit); |

396 | MODULE_ALIAS_CRYPTO("rsa"); |

397 | MODULE_LICENSE("GPL"); |

398 | MODULE_DESCRIPTION("RSA generic algorithm"); |

399 |