Adjust to openssl 1.1.1j padding changes
[platform/core/test/security-tests.git] / src / yaca / yaca-test-rsa.cpp
1 /*
2  *  Copyright (c) 2016 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Dariusz Michaluk (d.michaluk@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
21  * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
22  */
23
24 #include <vector>
25
26 #include "dpl/test/test_runner.h"
27
28 #include <yaca_rsa.h>
29 #include <yaca_types.h>
30 #include <yaca_key.h>
31
32 #include "yaca-test-common.h"
33 #include "yaca-test-vector.h"
34 #include "lorem.h"
35
36
37 namespace {
38
39 const size_t SHORT_ENOUGH = 16;
40
41 typedef int (*CryptoOp)(yaca_padding_e, const yaca_key_h, const char *, size_t, char **, size_t *);
42
43 void rsa_invalid_param(CryptoOp op,
44                        yaca_padding_e padding,
45                        const yaca_key_h key,
46                        const char *input,
47                        size_t input_len,
48                        char **output,
49                        size_t *output_len)
50 {
51     if (output != nullptr)
52         *output = nullptr;
53     if (output_len != nullptr)
54         *output_len = 0;
55
56     YACA_INVALID_PARAM(op(padding, key, input, input_len, output, output_len));
57 }
58
59 void test_rsa_common_invalid_param(CryptoOp op, const KeyPtr& valid_key,
60                                    const char *input, size_t input_len)
61 {
62     char *output = nullptr;
63     size_t output_len;
64
65     auto sym_key = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_192BIT);
66     auto iv = generate_key(YACA_KEY_TYPE_IV, YACA_KEY_LENGTH_IV_128BIT);
67     auto dsa_param = generate_key(YACA_KEY_TYPE_DSA_PARAMS, YACA_KEY_LENGTH_1024BIT);
68     auto dsa_priv = generate_key_from_parameters(dsa_param);
69     auto dsa_pub = extract_public_key(dsa_priv);
70
71     YACA_INVALID_PARAM(op(static_cast<yaca_padding_e>(-1), valid_key.get(),
72                           input, input_len,
73                           &output, &output_len));
74
75     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, YACA_KEY_NULL,
76                           input, input_len,
77                           &output, &output_len));
78     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, dsa_pub.get(),
79                           input, input_len,
80                           &output, &output_len));
81     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, sym_key.get(),
82                           input, input_len,
83                           &output, &output_len));
84     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, iv.get(),
85                           input, input_len,
86                           &output, &output_len));
87     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, dsa_param.get(),
88                           input, input_len,
89                           &output, &output_len));
90
91     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, valid_key.get(),
92                           nullptr, SHORT_ENOUGH,
93                           &output, &output_len));
94     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, valid_key.get(),
95                           input, 0,
96                           &output, &output_len));
97
98     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, valid_key.get(),
99                           input, input_len,
100                           nullptr, &output_len));
101     YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, valid_key.get(),
102                           input, input_len,
103                           &output, nullptr));
104 }
105
106 enum EncryptionType
107 {
108     ET_NONE = 0,
109     ET_PUB = 1 << 0,
110     ET_PRV = 1 << 1
111 };
112
113 struct PaddingInfo {
114     yaca_padding_e padding;
115     int supported_encryption;
116     size_t padding_size;
117     bool exact;
118 };
119
120 const std::vector<PaddingInfo> PADDINGS = {
121     { YACA_PADDING_NONE,         ET_PUB | ET_PRV, 0,  true  },
122     { YACA_PADDING_X931,         ET_NONE,         0,  false },
123     { YACA_PADDING_PKCS1,        ET_PUB | ET_PRV, 11, false },
124     { YACA_PADDING_PKCS1_PSS,    ET_NONE,         0,  false },
125     { YACA_PADDING_PKCS1_OAEP,   ET_PUB,          42, false },
126     { YACA_PADDING_PKCS1_SSLV23, ET_PUB,          11, false },
127     { YACA_PADDING_PKCS7,        ET_NONE,         0,  false }
128 };
129
130 void test_rsa_padding(const KeyPair& kp, const PaddingInfo& pi, EncryptionType et)
131 {
132     char *tmp;
133     size_t ciphertext_len;
134     size_t plaintext_len;
135     int expected;
136
137     yaca_padding_e padding = pi.padding;
138     size_t max_len = kp.bit_len / 8 - pi.padding_size;
139     const KeyPtr& enc_key = (et == ET_PUB) ? kp.pub : kp.prv;
140     const KeyPtr& dec_key = (et == ET_PUB) ? kp.prv : kp.pub;
141     CryptoOp encrypt = (et == ET_PUB) ? yaca_rsa_public_encrypt : yaca_rsa_private_encrypt;
142     CryptoOp decrypt = (et == ET_PUB) ? yaca_rsa_private_decrypt : yaca_rsa_public_decrypt;
143
144     /* padding not suitable for this operation */
145     if ((pi.supported_encryption & et) == 0) {
146         YACA_INVALID_PARAM(encrypt(pi.padding, enc_key.get(),
147                                    lorem1024, SHORT_ENOUGH,
148                                    &tmp, &ciphertext_len));
149         return;
150     }
151
152     /* input too long */
153     YACA_INVALID_PARAM(encrypt(padding, enc_key.get(),
154                                lorem1024, max_len + 1,
155                                &tmp, &ciphertext_len));
156
157     /* input shorter than max len */
158     expected = pi.exact ? YACA_ERROR_INVALID_PARAMETER : YACA_ERROR_NONE;
159     tmp = NULL;
160     YACA_RESULT(expected, encrypt(padding, enc_key.get(),
161                                   lorem1024, max_len - 1,
162                                   &tmp, &ciphertext_len));
163     yaca_free(tmp);
164     tmp = NULL;
165     YACA_RESULT(expected, encrypt(padding, enc_key.get(),
166                                   nullptr, 0,
167                                   &tmp, &ciphertext_len));
168     yaca_free(tmp);
169
170     /* valid length */
171     tmp = NULL;
172     YACA_SUCCESS(encrypt(padding, enc_key.get(),
173                          lorem1024, max_len,
174                          &tmp, &ciphertext_len));
175
176     auto ciphertext = wrap_ptr(tmp);
177
178     YACA_ASSERT_MSG(ciphertext != nullptr, "Empty ciphertext");
179     YACA_ASSERT_MSG(ciphertext_len == kp.bit_len / 8,
180                     "Expected ciphertext length: " << kp.bit_len / 8 <<
181                     " got: " << ciphertext_len);
182
183     /* decrypt with incorrect paddings */
184     for (auto& p : PADDINGS) {
185         /* don't decrypt with the same padding except for SSLV23 */
186         if (p.padding == padding && p.padding != YACA_PADDING_PKCS1_SSLV23)
187             continue;
188
189         /*
190          * - YACA_PADDING_PKCS1 & YACA_PADDING_PKCS1_SSLV23 are compatible
191          * - YACA_PADDING_NONE checks only the input length
192          */
193         expected = YACA_ERROR_INVALID_PARAMETER;
194         if (p.padding == YACA_PADDING_NONE ||
195             (p.padding == YACA_PADDING_PKCS1 && padding == YACA_PADDING_PKCS1_SSLV23) ||
196             (p.padding == YACA_PADDING_PKCS1_SSLV23 && padding == YACA_PADDING_PKCS1))
197             expected = YACA_ERROR_NONE;
198
199         int ret = decrypt(p.padding, dec_key.get(),
200                           ciphertext.get(), ciphertext_len,
201                           &tmp, &plaintext_len);
202         if (ret != expected && expected == YACA_ERROR_INVALID_PARAMETER) {
203             YACA_ASSERT_MSG(ret == YACA_ERROR_NONE, "Got unexpected error " << ret);
204             YACA_ASSERT_MSG(plaintext_len != max_len,
205                             "Message unpadded with invalid padding has correct length");
206         }
207     }
208
209     /* decryption with SSLV23 will fail if it was used during encryption */
210     if (padding == YACA_PADDING_PKCS1_SSLV23)
211         padding = YACA_PADDING_PKCS1;
212
213     /*
214      * Shortened ciphertext. During encryption without padding OpenSSL allows
215      * input of length equal to the key length but during decryption it allows
216      * also shorter input. Yaca API does the same.
217      */
218     if (padding != YACA_PADDING_NONE)
219         YACA_INVALID_PARAM(decrypt(padding, dec_key.get(),
220                                    ciphertext.get(), ciphertext_len - 1,
221                                    &tmp, &plaintext_len));
222
223     /* extended ciphertext */
224     std::vector<char> extended(ciphertext.get(), ciphertext.get() + ciphertext_len);
225     extended.push_back(' ');
226     YACA_INVALID_PARAM(decrypt(padding, dec_key.get(),
227                                extended.data(), extended.size(),
228                                &tmp, &plaintext_len));
229
230     /* valid ciphertext */
231     YACA_SUCCESS(decrypt(padding, dec_key.get(),
232                          ciphertext.get(), ciphertext_len,
233                          &tmp, &plaintext_len));
234     ChrPtr plaintext = wrap_ptr(tmp);
235
236     RUNNER_ASSERT_MSG(plaintext_len == max_len,
237                       "Decrypted message has different length (" << plaintext_len <<
238                       "B) than the original (" << max_len << "B)");
239
240     YACA_SUCCESS(yaca_memcmp(plaintext.get(), lorem1024, plaintext_len));
241 }
242
243 } // anonymous namespace
244
245 RUNNER_TEST_GROUP_INIT(T9000_YACA_RSA);
246
247 RUNNER_TEST(T9010_yaca_rsa_public_encrypt_invalid_param, YacaTest)
248 {
249     char *ciphertext = nullptr;
250     size_t ciphertext_len;
251
252     KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
253
254     test_rsa_common_invalid_param(yaca_rsa_public_encrypt, rsa.pub, lorem1024, SHORT_ENOUGH);
255
256     rsa_invalid_param(yaca_rsa_public_encrypt, YACA_PADDING_PKCS1, rsa.prv.get(),
257                       lorem1024, SHORT_ENOUGH,
258                       &ciphertext, &ciphertext_len);
259 }
260
261 RUNNER_TEST(T9020_yaca_rsa_private_decrypt_invalid_param, YacaTest)
262 {
263     char *tmp;
264     size_t ciphertext_len;
265     char *plaintext = nullptr;
266     size_t plaintext_len;
267
268     KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
269
270     YACA_SUCCESS(yaca_rsa_public_encrypt(YACA_PADDING_PKCS1, rsa.pub.get(),
271                                          lorem1024, SHORT_ENOUGH,
272                                          &tmp, &ciphertext_len));
273
274     ChrPtr ciphertext = wrap_ptr(tmp);
275
276     test_rsa_common_invalid_param(yaca_rsa_private_decrypt, rsa.prv,
277                                   ciphertext.get(), ciphertext_len);
278
279     rsa_invalid_param(yaca_rsa_private_decrypt, YACA_PADDING_PKCS1, rsa.pub.get(),
280                       ciphertext.get(), ciphertext_len,
281                       &plaintext, &plaintext_len);
282 }
283
284 RUNNER_TEST(T9030_yaca_rsa_private_encrypt_invalid_param, YacaTest)
285 {
286     char *ciphertext = nullptr;
287     size_t ciphertext_len;
288
289     KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
290
291     test_rsa_common_invalid_param(yaca_rsa_private_encrypt, rsa.prv, lorem1024, SHORT_ENOUGH);
292
293     rsa_invalid_param(yaca_rsa_private_encrypt, YACA_PADDING_PKCS1, rsa.pub.get(),
294                       lorem1024, SHORT_ENOUGH,
295                       &ciphertext, &ciphertext_len);
296 }
297
298 RUNNER_TEST(T9040_yaca_rsa_public_decrypt_invalid_param, YacaTest)
299 {
300     char *tmp;
301     size_t ciphertext_len;
302     char *plaintext = nullptr;
303     size_t plaintext_len;
304
305     KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
306
307     YACA_SUCCESS(yaca_rsa_private_encrypt(YACA_PADDING_PKCS1, rsa.prv.get(),
308                                           lorem1024, SHORT_ENOUGH,
309                                           &tmp, &ciphertext_len));
310
311     ChrPtr ciphertext = wrap_ptr(tmp);
312
313     test_rsa_common_invalid_param(yaca_rsa_public_decrypt, rsa.pub,
314                                   ciphertext.get(), ciphertext_len);
315
316     rsa_invalid_param(yaca_rsa_public_decrypt, YACA_PADDING_PKCS1, rsa.prv.get(),
317                       ciphertext.get(), ciphertext_len,
318                       &plaintext, &plaintext_len);
319 }
320
321 RUNNER_TEST(T9050_yaca_rsa_encryption_paddings, YacaTest)
322 {
323     std::vector<KeyPair> key_pairs;
324     key_pairs.emplace_back(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_512BIT);
325     key_pairs.emplace_back(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
326     key_pairs.emplace_back(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_2048BIT);
327     key_pairs.emplace_back(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_3072BIT);
328     key_pairs.emplace_back(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_4096BIT);
329
330     for (auto& kp : key_pairs) {
331         for (auto& pi : PADDINGS) {
332             test_rsa_padding(kp, pi, ET_PUB);
333             test_rsa_padding(kp, pi, ET_PRV);
334         }
335     }
336 }