1 | /* |
2 | * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at |
7 | * https://www.openssl.org/source/license.html |
8 | */ |
9 | |
10 | #include <openssl/crypto.h> |
11 | #include <openssl/evp.h> |
12 | #include <openssl/core_numbers.h> |
13 | #include <openssl/core_names.h> |
14 | #include <openssl/rsa.h> |
15 | #include <openssl/params.h> |
16 | #include <openssl/err.h> |
17 | /* Just for SSL_MAX_MASTER_KEY_LENGTH */ |
18 | #include <openssl/ssl.h> |
19 | #include "internal/constant_time.h" |
20 | #include "crypto/rsa.h" |
21 | #include "prov/providercommonerr.h" |
22 | #include "prov/provider_ctx.h" |
23 | #include "prov/implementations.h" |
24 | |
25 | #include <stdlib.h> |
26 | |
27 | static OSSL_OP_asym_cipher_newctx_fn rsa_newctx; |
28 | static OSSL_OP_asym_cipher_encrypt_init_fn rsa_init; |
29 | static OSSL_OP_asym_cipher_encrypt_fn rsa_encrypt; |
30 | static OSSL_OP_asym_cipher_decrypt_init_fn rsa_init; |
31 | static OSSL_OP_asym_cipher_decrypt_fn rsa_decrypt; |
32 | static OSSL_OP_asym_cipher_freectx_fn rsa_freectx; |
33 | static OSSL_OP_asym_cipher_dupctx_fn rsa_dupctx; |
34 | static OSSL_OP_asym_cipher_get_ctx_params_fn rsa_get_ctx_params; |
35 | static OSSL_OP_asym_cipher_gettable_ctx_params_fn rsa_gettable_ctx_params; |
36 | static OSSL_OP_asym_cipher_set_ctx_params_fn rsa_set_ctx_params; |
37 | static OSSL_OP_asym_cipher_settable_ctx_params_fn rsa_settable_ctx_params; |
38 | |
39 | |
40 | /* |
41 | * What's passed as an actual key is defined by the KEYMGMT interface. |
42 | * We happen to know that our KEYMGMT simply passes RSA structures, so |
43 | * we use that here too. |
44 | */ |
45 | |
46 | typedef struct { |
47 | OPENSSL_CTX *libctx; |
48 | RSA *rsa; |
49 | int pad_mode; |
50 | /* OAEP message digest */ |
51 | EVP_MD *oaep_md; |
52 | /* message digest for MGF1 */ |
53 | EVP_MD *mgf1_md; |
54 | /* OAEP label */ |
55 | unsigned char *oaep_label; |
56 | size_t oaep_labellen; |
57 | /* TLS padding */ |
58 | unsigned int client_version; |
59 | unsigned int alt_version; |
60 | } PROV_RSA_CTX; |
61 | |
62 | static void *rsa_newctx(void *provctx) |
63 | { |
64 | PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX)); |
65 | |
66 | if (prsactx == NULL) |
67 | return NULL; |
68 | prsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); |
69 | |
70 | return prsactx; |
71 | } |
72 | |
73 | static int rsa_init(void *vprsactx, void *vrsa) |
74 | { |
75 | PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; |
76 | |
77 | if (prsactx == NULL || vrsa == NULL || !RSA_up_ref(vrsa)) |
78 | return 0; |
79 | RSA_free(prsactx->rsa); |
80 | prsactx->rsa = vrsa; |
81 | prsactx->pad_mode = RSA_PKCS1_PADDING; |
82 | return 1; |
83 | } |
84 | |
85 | static int rsa_encrypt(void *vprsactx, unsigned char *out, size_t *outlen, |
86 | size_t outsize, const unsigned char *in, size_t inlen) |
87 | { |
88 | PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; |
89 | int ret; |
90 | |
91 | if (out == NULL) { |
92 | size_t len = RSA_size(prsactx->rsa); |
93 | |
94 | if (len == 0) { |
95 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); |
96 | return 0; |
97 | } |
98 | *outlen = len; |
99 | return 1; |
100 | } |
101 | |
102 | if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING) { |
103 | int rsasize = RSA_size(prsactx->rsa); |
104 | unsigned char *tbuf; |
105 | |
106 | if ((tbuf = OPENSSL_malloc(rsasize)) == NULL) { |
107 | PROVerr(0, ERR_R_MALLOC_FAILURE); |
108 | return 0; |
109 | } |
110 | ret = RSA_padding_add_PKCS1_OAEP_mgf1(tbuf, rsasize, in, inlen, |
111 | prsactx->oaep_label, |
112 | prsactx->oaep_labellen, |
113 | prsactx->oaep_md, |
114 | prsactx->mgf1_md); |
115 | |
116 | if (!ret) { |
117 | OPENSSL_free(tbuf); |
118 | return 0; |
119 | } |
120 | ret = RSA_public_encrypt(rsasize, tbuf, out, prsactx->rsa, |
121 | RSA_NO_PADDING); |
122 | OPENSSL_free(tbuf); |
123 | } else { |
124 | ret = RSA_public_encrypt(inlen, in, out, prsactx->rsa, |
125 | prsactx->pad_mode); |
126 | } |
127 | /* A ret value of 0 is not an error */ |
128 | if (ret < 0) |
129 | return ret; |
130 | *outlen = ret; |
131 | return 1; |
132 | } |
133 | |
134 | static int rsa_decrypt(void *vprsactx, unsigned char *out, size_t *outlen, |
135 | size_t outsize, const unsigned char *in, size_t inlen) |
136 | { |
137 | PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; |
138 | int ret; |
139 | size_t len = RSA_size(prsactx->rsa); |
140 | |
141 | if (prsactx->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) { |
142 | if (out == NULL) { |
143 | *outlen = SSL_MAX_MASTER_KEY_LENGTH; |
144 | return 1; |
145 | } |
146 | if (outsize < SSL_MAX_MASTER_KEY_LENGTH) { |
147 | ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH); |
148 | return 0; |
149 | } |
150 | } else { |
151 | if (out == NULL) { |
152 | if (len == 0) { |
153 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); |
154 | return 0; |
155 | } |
156 | *outlen = len; |
157 | return 1; |
158 | } |
159 | |
160 | if (outsize < len) { |
161 | ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH); |
162 | return 0; |
163 | } |
164 | } |
165 | |
166 | if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING |
167 | || prsactx->pad_mode == RSA_PKCS1_WITH_TLS_PADDING) { |
168 | unsigned char *tbuf; |
169 | |
170 | if ((tbuf = OPENSSL_malloc(len)) == NULL) { |
171 | PROVerr(0, ERR_R_MALLOC_FAILURE); |
172 | return 0; |
173 | } |
174 | ret = RSA_private_decrypt(inlen, in, tbuf, prsactx->rsa, |
175 | RSA_NO_PADDING); |
176 | /* |
177 | * With no padding then, on success ret should be len, otherwise an |
178 | * error occurred (non-constant time) |
179 | */ |
180 | if (ret != (int)len) { |
181 | OPENSSL_free(tbuf); |
182 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_DECRYPT); |
183 | return 0; |
184 | } |
185 | if (prsactx->pad_mode == RSA_PKCS1_OAEP_PADDING) { |
186 | ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, outsize, tbuf, |
187 | len, len, |
188 | prsactx->oaep_label, |
189 | prsactx->oaep_labellen, |
190 | prsactx->oaep_md, |
191 | prsactx->mgf1_md); |
192 | } else { |
193 | /* RSA_PKCS1_WITH_TLS_PADDING */ |
194 | if (prsactx->client_version <= 0) { |
195 | ERR_raise(ERR_LIB_PROV, PROV_R_BAD_TLS_CLIENT_VERSION); |
196 | return 0; |
197 | } |
198 | ret = rsa_padding_check_PKCS1_type_2_TLS(out, outsize, |
199 | tbuf, len, |
200 | prsactx->client_version, |
201 | prsactx->alt_version); |
202 | } |
203 | OPENSSL_free(tbuf); |
204 | } else { |
205 | ret = RSA_private_decrypt(inlen, in, out, prsactx->rsa, |
206 | prsactx->pad_mode); |
207 | } |
208 | *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret); |
209 | ret = constant_time_select_int(constant_time_msb(ret), 0, 1); |
210 | return ret; |
211 | } |
212 | |
213 | static void rsa_freectx(void *vprsactx) |
214 | { |
215 | PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; |
216 | |
217 | RSA_free(prsactx->rsa); |
218 | |
219 | EVP_MD_free(prsactx->oaep_md); |
220 | EVP_MD_free(prsactx->mgf1_md); |
221 | |
222 | OPENSSL_free(prsactx); |
223 | } |
224 | |
225 | static void *rsa_dupctx(void *vprsactx) |
226 | { |
227 | PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx; |
228 | PROV_RSA_CTX *dstctx; |
229 | |
230 | dstctx = OPENSSL_zalloc(sizeof(*srcctx)); |
231 | if (dstctx == NULL) |
232 | return NULL; |
233 | |
234 | *dstctx = *srcctx; |
235 | if (dstctx->rsa != NULL && !RSA_up_ref(dstctx->rsa)) { |
236 | OPENSSL_free(dstctx); |
237 | return NULL; |
238 | } |
239 | |
240 | if (dstctx->oaep_md != NULL && !EVP_MD_up_ref(dstctx->oaep_md)) { |
241 | RSA_free(dstctx->rsa); |
242 | OPENSSL_free(dstctx); |
243 | return NULL; |
244 | } |
245 | |
246 | if (dstctx->mgf1_md != NULL && !EVP_MD_up_ref(dstctx->mgf1_md)) { |
247 | RSA_free(dstctx->rsa); |
248 | EVP_MD_free(dstctx->oaep_md); |
249 | OPENSSL_free(dstctx); |
250 | return NULL; |
251 | } |
252 | |
253 | return dstctx; |
254 | } |
255 | |
256 | static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) |
257 | { |
258 | PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; |
259 | OSSL_PARAM *p; |
260 | |
261 | if (prsactx == NULL || params == NULL) |
262 | return 0; |
263 | |
264 | p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE); |
265 | if (p != NULL && !OSSL_PARAM_set_int(p, prsactx->pad_mode)) |
266 | return 0; |
267 | |
268 | p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST); |
269 | if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->oaep_md == NULL |
270 | ? "" |
271 | : EVP_MD_name(prsactx->oaep_md))) |
272 | return 0; |
273 | |
274 | p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST); |
275 | if (p != NULL) { |
276 | EVP_MD *mgf1_md = prsactx->mgf1_md == NULL ? prsactx->oaep_md |
277 | : prsactx->mgf1_md; |
278 | |
279 | if (!OSSL_PARAM_set_utf8_string(p, mgf1_md == NULL |
280 | ? "" |
281 | : EVP_MD_name(mgf1_md))) |
282 | return 0; |
283 | } |
284 | |
285 | p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL); |
286 | if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, prsactx->oaep_label, 0)) |
287 | return 0; |
288 | |
289 | p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL_LEN); |
290 | if (p != NULL && !OSSL_PARAM_set_size_t(p, prsactx->oaep_labellen)) |
291 | return 0; |
292 | |
293 | p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION); |
294 | if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->client_version)) |
295 | return 0; |
296 | |
297 | p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION); |
298 | if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->alt_version)) |
299 | return 0; |
300 | |
301 | return 1; |
302 | } |
303 | |
304 | static const OSSL_PARAM known_gettable_ctx_params[] = { |
305 | OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0), |
306 | OSSL_PARAM_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL), |
307 | OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0), |
308 | OSSL_PARAM_DEFN(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_PTR, |
309 | NULL, 0), |
310 | OSSL_PARAM_size_t(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL_LEN, NULL), |
311 | OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL), |
312 | OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL), |
313 | OSSL_PARAM_END |
314 | }; |
315 | |
316 | static const OSSL_PARAM *rsa_gettable_ctx_params(void) |
317 | { |
318 | return known_gettable_ctx_params; |
319 | } |
320 | |
321 | static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) |
322 | { |
323 | PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; |
324 | const OSSL_PARAM *p; |
325 | /* Should be big enough */ |
326 | char mdname[80], mdprops[80] = { '\0' }; |
327 | char *str = mdname; |
328 | int pad_mode; |
329 | |
330 | if (prsactx == NULL || params == NULL) |
331 | return 0; |
332 | |
333 | p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST); |
334 | if (p != NULL) { |
335 | if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdname))) |
336 | return 0; |
337 | |
338 | str = mdprops; |
339 | p = OSSL_PARAM_locate_const(params, |
340 | OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS); |
341 | if (p != NULL) { |
342 | if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops))) |
343 | return 0; |
344 | } |
345 | |
346 | EVP_MD_free(prsactx->oaep_md); |
347 | prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, mdname, mdprops); |
348 | |
349 | if (prsactx->oaep_md == NULL) |
350 | return 0; |
351 | } |
352 | |
353 | p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE); |
354 | if (p != NULL) { |
355 | if (!OSSL_PARAM_get_int(p, &pad_mode)) |
356 | return 0; |
357 | /* |
358 | * PSS padding is for signatures only so is not compatible with |
359 | * asymmetric cipher use. |
360 | */ |
361 | if (pad_mode == RSA_PKCS1_PSS_PADDING) |
362 | return 0; |
363 | if (pad_mode == RSA_PKCS1_OAEP_PADDING && prsactx->oaep_md == NULL) { |
364 | prsactx->oaep_md = EVP_MD_fetch(prsactx->libctx, "SHA1" , mdprops); |
365 | if (prsactx->oaep_md == NULL) |
366 | return 0; |
367 | } |
368 | prsactx->pad_mode = pad_mode; |
369 | } |
370 | |
371 | p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST); |
372 | if (p != NULL) { |
373 | if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdname))) |
374 | return 0; |
375 | |
376 | str = mdprops; |
377 | p = OSSL_PARAM_locate_const(params, |
378 | OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS); |
379 | if (p != NULL) { |
380 | if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops))) |
381 | return 0; |
382 | } else { |
383 | str = NULL; |
384 | } |
385 | |
386 | EVP_MD_free(prsactx->mgf1_md); |
387 | prsactx->mgf1_md = EVP_MD_fetch(prsactx->libctx, mdname, str); |
388 | |
389 | if (prsactx->mgf1_md == NULL) |
390 | return 0; |
391 | } |
392 | |
393 | p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL); |
394 | if (p != NULL) { |
395 | void *tmp_label = NULL; |
396 | size_t tmp_labellen; |
397 | |
398 | if (!OSSL_PARAM_get_octet_string(p, &tmp_label, 0, &tmp_labellen)) |
399 | return 0; |
400 | OPENSSL_free(prsactx->oaep_label); |
401 | prsactx->oaep_label = (unsigned char *)tmp_label; |
402 | prsactx->oaep_labellen = tmp_labellen; |
403 | } |
404 | |
405 | p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION); |
406 | if (p != NULL) { |
407 | unsigned int client_version; |
408 | |
409 | if (!OSSL_PARAM_get_uint(p, &client_version)) |
410 | return 0; |
411 | prsactx->client_version = client_version; |
412 | } |
413 | |
414 | p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION); |
415 | if (p != NULL) { |
416 | unsigned int alt_version; |
417 | |
418 | if (!OSSL_PARAM_get_uint(p, &alt_version)) |
419 | return 0; |
420 | prsactx->alt_version = alt_version; |
421 | } |
422 | |
423 | return 1; |
424 | } |
425 | |
426 | static const OSSL_PARAM known_settable_ctx_params[] = { |
427 | OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0), |
428 | OSSL_PARAM_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL), |
429 | OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0), |
430 | OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS, NULL, 0), |
431 | OSSL_PARAM_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, NULL, 0), |
432 | OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL), |
433 | OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL), |
434 | OSSL_PARAM_END |
435 | }; |
436 | |
437 | static const OSSL_PARAM *rsa_settable_ctx_params(void) |
438 | { |
439 | return known_settable_ctx_params; |
440 | } |
441 | |
442 | const OSSL_DISPATCH rsa_asym_cipher_functions[] = { |
443 | { OSSL_FUNC_ASYM_CIPHER_NEWCTX, (void (*)(void))rsa_newctx }, |
444 | { OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT, (void (*)(void))rsa_init }, |
445 | { OSSL_FUNC_ASYM_CIPHER_ENCRYPT, (void (*)(void))rsa_encrypt }, |
446 | { OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT, (void (*)(void))rsa_init }, |
447 | { OSSL_FUNC_ASYM_CIPHER_DECRYPT, (void (*)(void))rsa_decrypt }, |
448 | { OSSL_FUNC_ASYM_CIPHER_FREECTX, (void (*)(void))rsa_freectx }, |
449 | { OSSL_FUNC_ASYM_CIPHER_DUPCTX, (void (*)(void))rsa_dupctx }, |
450 | { OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS, |
451 | (void (*)(void))rsa_get_ctx_params }, |
452 | { OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS, |
453 | (void (*)(void))rsa_gettable_ctx_params }, |
454 | { OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS, |
455 | (void (*)(void))rsa_set_ctx_params }, |
456 | { OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS, |
457 | (void (*)(void))rsa_settable_ctx_params }, |
458 | { 0, NULL } |
459 | }; |
460 | |