OpenSSL and libc mockup infrastructure implementation
[platform/core/security/yaca.git] / src / rsa.c
1 /*
2  *  Copyright (c) 2016-2020 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                 return RSA_PKCS1_PADDING;
51         case YACA_PADDING_PKCS1_PSS:
52                 return RSA_PKCS1_PSS_PADDING;
53         case YACA_PADDING_PKCS1_OAEP:
54                 return RSA_PKCS1_OAEP_PADDING;
55         case YACA_PADDING_PKCS1_SSLV23:
56                 return RSA_SSLV23_PADDING;
57         default:
58                 assert(false);
59                 return -1;
60         }
61 }
62
63 typedef int (*encrypt_decrypt_fn)(int, const unsigned char*, unsigned char*, RSA*, int);
64
65 static int encrypt_decrypt(yaca_padding_e padding,
66                                                    const yaca_key_h key,
67                                                    const char *input,
68                                                    size_t input_len,
69                                                    char **output,
70                                                    size_t *output_len,
71                                                    encrypt_decrypt_fn fn)
72 {
73         int ret;
74         size_t max_len;
75         char *loutput = NULL;
76         struct yaca_key_evp_s *lasym_key;
77         int lpadding;
78
79         if ((input == NULL && input_len > 0) || (input != NULL && input_len == 0) ||
80                 output == NULL || output_len == NULL)
81                 return YACA_ERROR_INVALID_PARAMETER;
82
83         lpadding = rsa_padding2openssl(padding);
84
85         lasym_key = key_get_evp(key);
86         assert(lasym_key != NULL);
87
88         ret = EVP_PKEY_size(lasym_key->evp);
89         if (ret <= 0) {
90                 ret = YACA_ERROR_INTERNAL;
91                 ERROR_DUMP(ret);
92                 return ret;
93         }
94
95         max_len = ret;
96
97         ret = yaca_zalloc(max_len, (void**)&loutput);
98         if (ret != YACA_ERROR_NONE)
99                 return ret;
100
101         ret = fn(input_len,
102                          (const unsigned char*)input,
103                          (unsigned char*)loutput,
104                          EVP_PKEY_get0_RSA(lasym_key->evp),
105                          lpadding);
106
107         if (ret < 0) {
108                 ret = ERROR_HANDLE();
109                 goto exit;
110         }
111
112         if (ret == 0) {
113                 yaca_free(loutput);
114                 loutput = NULL;
115         }
116
117         *output_len = ret;
118         *output = loutput;
119         loutput = NULL;
120         ret = YACA_ERROR_NONE;
121
122 exit:
123         yaca_free(loutput);
124         return ret;
125 }
126
127
128 API int yaca_rsa_public_encrypt(yaca_padding_e padding,
129                                                                 const yaca_key_h pub_key,
130                                                                 const char *plaintext,
131                                                                 size_t plaintext_len,
132                                                                 char **ciphertext,
133                                                                 size_t *ciphertext_len)
134 {
135         if (pub_key == YACA_KEY_NULL || pub_key->type != YACA_KEY_TYPE_RSA_PUB)
136                 return YACA_ERROR_INVALID_PARAMETER;
137
138         switch (padding) {
139         case YACA_PADDING_NONE:
140         case YACA_PADDING_PKCS1:
141         case YACA_PADDING_PKCS1_OAEP:
142         case YACA_PADDING_PKCS1_SSLV23:
143                 break;
144         default:
145                 return YACA_ERROR_INVALID_PARAMETER;
146         }
147
148         return encrypt_decrypt(padding,
149                                                    pub_key,
150                                                    plaintext,
151                                                    plaintext_len,
152                                                    ciphertext,
153                                                    ciphertext_len,
154                                                    RSA_public_encrypt);
155 }
156
157 API int yaca_rsa_private_decrypt(yaca_padding_e padding,
158                                                                  const yaca_key_h prv_key,
159                                                                  const char *ciphertext,
160                                                                  size_t ciphertext_len,
161                                                                  char **plaintext,
162                                                                  size_t *plaintext_len)
163 {
164         if (prv_key == YACA_KEY_NULL || prv_key->type != YACA_KEY_TYPE_RSA_PRIV)
165                 return YACA_ERROR_INVALID_PARAMETER;
166
167         switch (padding) {
168         case YACA_PADDING_NONE:
169         case YACA_PADDING_PKCS1:
170         case YACA_PADDING_PKCS1_OAEP:
171         case YACA_PADDING_PKCS1_SSLV23:
172                 break;
173         default:
174                 return YACA_ERROR_INVALID_PARAMETER;
175         }
176
177         return encrypt_decrypt(padding,
178                                                    prv_key,
179                                                    ciphertext,
180                                                    ciphertext_len,
181                                                    plaintext,
182                                                    plaintext_len,
183                                                    RSA_private_decrypt);
184 }
185
186 API int yaca_rsa_private_encrypt(yaca_padding_e padding,
187                                                                  const yaca_key_h prv_key,
188                                                                  const char *plaintext,
189                                                                  size_t plaintext_len,
190                                                                  char **ciphertext,
191                                                                  size_t *ciphertext_len)
192 {
193         if (prv_key == YACA_KEY_NULL || prv_key->type != YACA_KEY_TYPE_RSA_PRIV)
194                 return YACA_ERROR_INVALID_PARAMETER;
195
196         switch (padding) {
197         case YACA_PADDING_NONE:
198         case YACA_PADDING_PKCS1:
199                 break;
200         default:
201                 return YACA_ERROR_INVALID_PARAMETER;
202         }
203
204         return encrypt_decrypt(padding,
205                                                    prv_key,
206                                                    plaintext,
207                                                    plaintext_len,
208                                                    ciphertext,
209                                                    ciphertext_len,
210                                                    RSA_private_encrypt);
211 }
212
213 API int yaca_rsa_public_decrypt(yaca_padding_e padding,
214                                                                 const yaca_key_h pub_key,
215                                                                 const char *ciphertext,
216                                                                 size_t ciphertext_len,
217                                                                 char **plaintext,
218                                                                 size_t *plaintext_len)
219 {
220         if (pub_key == YACA_KEY_NULL || pub_key->type != YACA_KEY_TYPE_RSA_PUB)
221                 return YACA_ERROR_INVALID_PARAMETER;
222
223         switch (padding) {
224         case YACA_PADDING_NONE:
225         case YACA_PADDING_PKCS1:
226                 break;
227         default:
228                 return YACA_ERROR_INVALID_PARAMETER;
229         }
230
231         return encrypt_decrypt(padding,
232                                                    pub_key,
233                                                    ciphertext,
234                                                    ciphertext_len,
235                                                    plaintext,
236                                                    plaintext_len,
237                                                    RSA_public_decrypt);
238 }