Migrate to openssl3
[platform/core/security/yaca.git] / src / rsa.c
1 /*
2  *  Copyright (c) 2016-2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19 /**
20  * @file   rsa.c
21  * @brief  Advanced API for low-level RSA operations
22  */
23
24 #include <assert.h>
25
26 #include <openssl/evp.h>
27 #include <openssl/rsa.h>
28
29 #include <yaca_rsa.h>
30 #include <yaca_error.h>
31 #include <yaca_types.h>
32 #include <yaca_crypto.h>
33 #include <yaca_key.h>
34
35 #include "internal.h"
36
37 #ifdef OPENSSL_MOCKUP_TESTS
38 #include "../tests/openssl_mock_redefine.h"
39 #endif
40
41
42 int rsa_padding2openssl(yaca_padding_e padding)
43 {
44         switch (padding) {
45         case YACA_PADDING_NONE:
46                 return RSA_NO_PADDING;
47         case YACA_PADDING_X931:
48                 return RSA_X931_PADDING;
49         case YACA_PADDING_PKCS1:
50         case YACA_PADDING_PKCS1_SSLV23:
51                 return RSA_PKCS1_PADDING;
52         case YACA_PADDING_PKCS1_PSS:
53                 return RSA_PKCS1_PSS_PADDING;
54         case YACA_PADDING_PKCS1_OAEP:
55                 return RSA_PKCS1_OAEP_PADDING;
56         default:
57                 assert(false);
58                 return -1;
59         }
60 }
61
62 typedef int (*encrypt_decrypt_fn)(int, const unsigned char*, unsigned char*, RSA*, int);
63
64 static int encrypt_decrypt(yaca_padding_e padding,
65                                                    const yaca_key_h key,
66                                                    const char *input,
67                                                    size_t input_len,
68                                                    char **output,
69                                                    size_t *output_len,
70                                                    encrypt_decrypt_fn fn)
71 {
72         int ret;
73         size_t max_len;
74         char *loutput = NULL;
75         struct yaca_key_evp_s *lasym_key;
76         int lpadding;
77
78         if ((input == NULL && input_len > 0) || (input != NULL && input_len == 0) ||
79                 output == NULL || output_len == NULL)
80                 return YACA_ERROR_INVALID_PARAMETER;
81
82         lpadding = rsa_padding2openssl(padding);
83
84         lasym_key = key_get_evp(key);
85         assert(lasym_key != NULL);
86
87         ret = EVP_PKEY_get_size(lasym_key->evp);
88         if (ret <= 0) {
89                 ret = YACA_ERROR_INTERNAL;
90                 ERROR_DUMP(ret);
91                 return ret;
92         }
93
94         max_len = ret;
95
96         if (input_len > max_len)
97                 return YACA_ERROR_INVALID_PARAMETER;
98
99         ret = yaca_zalloc(max_len, (void**)&loutput);
100         if (ret != YACA_ERROR_NONE)
101                 return ret;
102
103         ret = fn(input_len,
104                          (const unsigned char*)input,
105                          (unsigned char*)loutput,
106                          (RSA *)EVP_PKEY_get0_RSA(lasym_key->evp),
107                          lpadding);
108
109         if (ret < 0) {
110                 ret = ERROR_HANDLE();
111                 goto exit;
112         }
113
114         if (ret == 0) {
115                 yaca_free(loutput);
116                 loutput = NULL;
117         }
118
119         *output_len = ret;
120         *output = loutput;
121         loutput = NULL;
122         ret = YACA_ERROR_NONE;
123
124 exit:
125         yaca_free(loutput);
126         return ret;
127 }
128
129
130 API int yaca_rsa_public_encrypt(yaca_padding_e padding,
131                                                                 const yaca_key_h pub_key,
132                                                                 const char *plaintext,
133                                                                 size_t plaintext_len,
134                                                                 char **ciphertext,
135                                                                 size_t *ciphertext_len)
136 {
137         if (pub_key == YACA_KEY_NULL || pub_key->type != YACA_KEY_TYPE_RSA_PUB)
138                 return YACA_ERROR_INVALID_PARAMETER;
139
140         switch (padding) {
141         case YACA_PADDING_NONE:
142         case YACA_PADDING_PKCS1:
143         case YACA_PADDING_PKCS1_OAEP:
144         case YACA_PADDING_PKCS1_SSLV23:
145                 break;
146         default:
147                 return YACA_ERROR_INVALID_PARAMETER;
148         }
149
150         return encrypt_decrypt(padding,
151                                                    pub_key,
152                                                    plaintext,
153                                                    plaintext_len,
154                                                    ciphertext,
155                                                    ciphertext_len,
156                                                    RSA_public_encrypt);
157 }
158
159 API int yaca_rsa_private_decrypt(yaca_padding_e padding,
160                                                                  const yaca_key_h prv_key,
161                                                                  const char *ciphertext,
162                                                                  size_t ciphertext_len,
163                                                                  char **plaintext,
164                                                                  size_t *plaintext_len)
165 {
166         if (prv_key == YACA_KEY_NULL || prv_key->type != YACA_KEY_TYPE_RSA_PRIV)
167                 return YACA_ERROR_INVALID_PARAMETER;
168
169         switch (padding) {
170         case YACA_PADDING_NONE:
171         case YACA_PADDING_PKCS1:
172         case YACA_PADDING_PKCS1_OAEP:
173         case YACA_PADDING_PKCS1_SSLV23:
174                 break;
175         default:
176                 return YACA_ERROR_INVALID_PARAMETER;
177         }
178
179         return encrypt_decrypt(padding,
180                                                    prv_key,
181                                                    ciphertext,
182                                                    ciphertext_len,
183                                                    plaintext,
184                                                    plaintext_len,
185                                                    RSA_private_decrypt);
186 }
187
188 API int yaca_rsa_private_encrypt(yaca_padding_e padding,
189                                                                  const yaca_key_h prv_key,
190                                                                  const char *plaintext,
191                                                                  size_t plaintext_len,
192                                                                  char **ciphertext,
193                                                                  size_t *ciphertext_len)
194 {
195         if (prv_key == YACA_KEY_NULL || prv_key->type != YACA_KEY_TYPE_RSA_PRIV)
196                 return YACA_ERROR_INVALID_PARAMETER;
197
198         switch (padding) {
199         case YACA_PADDING_NONE:
200         case YACA_PADDING_PKCS1:
201         case YACA_PADDING_PKCS1_SSLV23:
202                 break;
203         default:
204                 return YACA_ERROR_INVALID_PARAMETER;
205         }
206
207         return encrypt_decrypt(padding,
208                                                    prv_key,
209                                                    plaintext,
210                                                    plaintext_len,
211                                                    ciphertext,
212                                                    ciphertext_len,
213                                                    RSA_private_encrypt);
214 }
215
216 API int yaca_rsa_public_decrypt(yaca_padding_e padding,
217                                                                 const yaca_key_h pub_key,
218                                                                 const char *ciphertext,
219                                                                 size_t ciphertext_len,
220                                                                 char **plaintext,
221                                                                 size_t *plaintext_len)
222 {
223         if (pub_key == YACA_KEY_NULL || pub_key->type != YACA_KEY_TYPE_RSA_PUB)
224                 return YACA_ERROR_INVALID_PARAMETER;
225
226         switch (padding) {
227         case YACA_PADDING_NONE:
228         case YACA_PADDING_PKCS1:
229         case YACA_PADDING_PKCS1_SSLV23:
230                 break;
231         default:
232                 return YACA_ERROR_INVALID_PARAMETER;
233         }
234
235         return encrypt_decrypt(padding,
236                                                    pub_key,
237                                                    ciphertext,
238                                                    ciphertext_len,
239                                                    plaintext,
240                                                    plaintext_len,
241                                                    RSA_public_decrypt);
242 }