2 * Copyright (c) 2016 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Dariusz Michaluk (d.michaluk@samsung.com)
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
21 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
26 #include "dpl/test/test_runner.h"
29 #include <yaca_types.h>
32 #include "yaca-test-common.h"
33 #include "yaca-test-vector.h"
39 const size_t SHORT_ENOUGH = 16;
41 typedef int (*CryptoOp)(yaca_padding_e, const yaca_key_h, const char *, size_t, char **, size_t *);
43 void rsa_invalid_param(CryptoOp op,
44 yaca_padding_e padding,
51 if (output != nullptr)
53 if (output_len != nullptr)
56 YACA_INVALID_PARAM(op(padding, key, input, input_len, output, output_len));
59 void test_rsa_common_invalid_param(CryptoOp op, const KeyPtr& valid_key,
60 const char *input, size_t input_len)
62 char *output = nullptr;
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);
71 YACA_INVALID_PARAM(op(static_cast<yaca_padding_e>(-1), valid_key.get(),
73 &output, &output_len));
75 YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, YACA_KEY_NULL,
77 &output, &output_len));
78 YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, dsa_pub.get(),
80 &output, &output_len));
81 YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, sym_key.get(),
83 &output, &output_len));
84 YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, iv.get(),
86 &output, &output_len));
87 YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, dsa_param.get(),
89 &output, &output_len));
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(),
96 &output, &output_len));
98 YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, valid_key.get(),
100 nullptr, &output_len));
101 YACA_INVALID_PARAM(op(YACA_PADDING_PKCS1, valid_key.get(),
114 yaca_padding_e padding;
115 int supported_encryption;
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 }
130 void test_rsa_padding(const KeyPair& kp, const PaddingInfo& pi, EncryptionType et)
133 size_t ciphertext_len;
134 size_t plaintext_len;
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;
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));
153 YACA_INVALID_PARAM(encrypt(padding, enc_key.get(),
154 lorem1024, max_len + 1,
155 &tmp, &ciphertext_len));
157 /* input shorter than max len */
158 expected = pi.exact ? YACA_ERROR_INVALID_PARAMETER : YACA_ERROR_NONE;
160 YACA_RESULT(expected, encrypt(padding, enc_key.get(),
161 lorem1024, max_len - 1,
162 &tmp, &ciphertext_len));
165 YACA_RESULT(expected, encrypt(padding, enc_key.get(),
167 &tmp, &ciphertext_len));
172 YACA_SUCCESS(encrypt(padding, enc_key.get(),
174 &tmp, &ciphertext_len));
176 auto ciphertext = wrap_ptr(tmp);
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);
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)
190 * - YACA_PADDING_PKCS1 & YACA_PADDING_PKCS1_SSLV23 are compatible
191 * - YACA_PADDING_NONE checks only the input length
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;
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");
209 /* decryption with SSLV23 will fail if it was used during encryption */
210 if (padding == YACA_PADDING_PKCS1_SSLV23)
211 padding = YACA_PADDING_PKCS1;
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.
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));
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));
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);
236 RUNNER_ASSERT_MSG(plaintext_len == max_len,
237 "Decrypted message has different length (" << plaintext_len <<
238 "B) than the original (" << max_len << "B)");
240 YACA_SUCCESS(yaca_memcmp(plaintext.get(), lorem1024, plaintext_len));
243 } // anonymous namespace
245 RUNNER_TEST_GROUP_INIT(T9000_YACA_RSA);
247 RUNNER_TEST(T9010_yaca_rsa_public_encrypt_invalid_param, YacaTest)
249 char *ciphertext = nullptr;
250 size_t ciphertext_len;
252 KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
254 test_rsa_common_invalid_param(yaca_rsa_public_encrypt, rsa.pub, lorem1024, SHORT_ENOUGH);
256 rsa_invalid_param(yaca_rsa_public_encrypt, YACA_PADDING_PKCS1, rsa.prv.get(),
257 lorem1024, SHORT_ENOUGH,
258 &ciphertext, &ciphertext_len);
261 RUNNER_TEST(T9020_yaca_rsa_private_decrypt_invalid_param, YacaTest)
264 size_t ciphertext_len;
265 char *plaintext = nullptr;
266 size_t plaintext_len;
268 KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
270 YACA_SUCCESS(yaca_rsa_public_encrypt(YACA_PADDING_PKCS1, rsa.pub.get(),
271 lorem1024, SHORT_ENOUGH,
272 &tmp, &ciphertext_len));
274 ChrPtr ciphertext = wrap_ptr(tmp);
276 test_rsa_common_invalid_param(yaca_rsa_private_decrypt, rsa.prv,
277 ciphertext.get(), ciphertext_len);
279 rsa_invalid_param(yaca_rsa_private_decrypt, YACA_PADDING_PKCS1, rsa.pub.get(),
280 ciphertext.get(), ciphertext_len,
281 &plaintext, &plaintext_len);
284 RUNNER_TEST(T9030_yaca_rsa_private_encrypt_invalid_param, YacaTest)
286 char *ciphertext = nullptr;
287 size_t ciphertext_len;
289 KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
291 test_rsa_common_invalid_param(yaca_rsa_private_encrypt, rsa.prv, lorem1024, SHORT_ENOUGH);
293 rsa_invalid_param(yaca_rsa_private_encrypt, YACA_PADDING_PKCS1, rsa.pub.get(),
294 lorem1024, SHORT_ENOUGH,
295 &ciphertext, &ciphertext_len);
298 RUNNER_TEST(T9040_yaca_rsa_public_decrypt_invalid_param, YacaTest)
301 size_t ciphertext_len;
302 char *plaintext = nullptr;
303 size_t plaintext_len;
305 KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
307 YACA_SUCCESS(yaca_rsa_private_encrypt(YACA_PADDING_PKCS1, rsa.prv.get(),
308 lorem1024, SHORT_ENOUGH,
309 &tmp, &ciphertext_len));
311 ChrPtr ciphertext = wrap_ptr(tmp);
313 test_rsa_common_invalid_param(yaca_rsa_public_decrypt, rsa.pub,
314 ciphertext.get(), ciphertext_len);
316 rsa_invalid_param(yaca_rsa_public_decrypt, YACA_PADDING_PKCS1, rsa.prv.get(),
317 ciphertext.get(), ciphertext_len,
318 &plaintext, &plaintext_len);
321 RUNNER_TEST(T9050_yaca_rsa_encryption_paddings, YacaTest)
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);
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);