TEST: Add RSA-PSS cases in test/serdes_test.c
[openssl.git] / test / serdes_test.c
1 /*
2  * Copyright 2020 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 <string.h>
11 #include <openssl/evp.h>
12 #include <openssl/pem.h>
13 #include <openssl/rsa.h>
14 #include <openssl/x509.h>
15 #include <openssl/serializer.h>
16 #include <openssl/deserializer.h>
17
18 #include "internal/cryptlib.h"   /* ossl_assert */
19
20 #include "testutil.h"
21
22 /*
23  * TODO(3.0) Modify PEM_write_bio_PrivateKey_traditional() to handle
24  * provider side EVP_PKEYs (which don't necessarily have an ameth)
25  *
26  * In the mean time, we use separate "downgraded" EVP_PKEYs to test
27  * serializing/deserializing with "traditional" keys.
28  */
29
30 static EVP_PKEY *key_RSA = NULL;
31 static EVP_PKEY *legacy_key_RSA = NULL;
32 static EVP_PKEY *key_RSA_PSS = NULL;
33 static EVP_PKEY *legacy_key_RSA_PSS = NULL;
34
35 static EVP_PKEY *make_RSA(const char *rsa_type, int make_legacy)
36 {
37     EVP_PKEY *pkey = NULL;
38     EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, rsa_type, NULL);
39
40     /*
41      * No real need to check the errors other than for the cascade
42      * effect.  |pkey| will imply remain NULL if something goes wrong.
43      */
44     (void)(ctx != NULL
45            && EVP_PKEY_keygen_init(ctx) > 0
46            && EVP_PKEY_keygen(ctx, &pkey) > 0);
47     EVP_PKEY_CTX_free(ctx);
48     if (make_legacy && EVP_PKEY_get0(pkey) == NULL) {
49         EVP_PKEY_free(pkey);
50         pkey = NULL;
51     }
52
53     return pkey;
54 }
55
56 /* Main test driver */
57
58 typedef int (serializer)(void **serialized, long *serialized_len,
59                          void *object,
60                          const char *pass, const char *pcipher,
61                          const char *ser_propq);
62 typedef int (deserializer)(void **object,
63                            void *serialized, long serialized_len,
64                            const char *pass, const char *pcipher);
65 typedef int (checker)(const char *type, const void *data, size_t data_len);
66 typedef void (dumper)(const char *label, const void *data, size_t data_len);
67
68 static int test_serialize_deserialize(const char *type, EVP_PKEY *pkey,
69                                       const char *pass, const char *pcipher,
70                                       serializer *serialize_cb,
71                                       deserializer *deserialize_cb,
72                                       checker *check_cb, dumper *dump_cb,
73                                       const char *ser_propq, int make_legacy)
74 {
75     void *serialized = NULL;
76     long serialized_len = 0;
77     EVP_PKEY *pkey2 = NULL;
78     void *serialized2 = NULL;
79     long serialized2_len = 0;
80     int ok = 0;
81
82     if (!serialize_cb(&serialized, &serialized_len, pkey,
83                       pass, pcipher, ser_propq)
84         || !check_cb(type, serialized, serialized_len)
85         || !deserialize_cb((void **)&pkey2, serialized, serialized_len,
86                            pass, pcipher)
87         || !TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 1))
88         goto end;
89
90     /*
91      * TODO(3.0) Remove this when PEM_write_bio_PrivateKey_traditional()
92      * handles provider side keys.
93      */
94     if (make_legacy
95         && !TEST_ptr(EVP_PKEY_get0(pkey2)))
96         goto end;
97
98     /*
99      * Double check the serialization, but only for unprotected keys,
100      * as protected keys have a random component, which makes the output
101      * differ.
102      */
103     if ((pass == NULL && pcipher == NULL)
104         && (!serialize_cb(&serialized2, &serialized2_len, pkey2,
105                           pass, pcipher, ser_propq)
106             || !TEST_mem_eq(serialized, serialized_len,
107                             serialized2, serialized2_len)))
108         goto end;
109
110     ok = 1;
111  end:
112     if (!ok)
113         dump_cb("serialized result", serialized, serialized_len);
114
115     OPENSSL_free(serialized);
116     OPENSSL_free(serialized2);
117     EVP_PKEY_free(pkey2);
118     return ok;
119 }
120
121 /* Serializing and desserializing methods */
122
123 static int serialize_EVP_PKEY_prov(void **serialized, long *serialized_len,
124                                    void *object,
125                                    const char *pass, const char *pcipher,
126                                    const char *ser_propq)
127 {
128     EVP_PKEY *pkey = object;
129     OSSL_SERIALIZER_CTX *sctx = NULL;
130     BIO *mem_ser = NULL;
131     BUF_MEM *mem_buf = NULL;
132     const unsigned char *upass = (const unsigned char *)pass;
133     int ok = 0;
134
135     if (!TEST_ptr(sctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, ser_propq))
136         || (pass != NULL
137             && !TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(sctx, upass,
138                                                              strlen(pass))))
139         || (pcipher != NULL
140             && !TEST_true(OSSL_SERIALIZER_CTX_set_cipher(sctx, pcipher, NULL)))
141         || !TEST_ptr(mem_ser = BIO_new(BIO_s_mem()))
142         || !TEST_true(OSSL_SERIALIZER_to_bio(sctx, mem_ser))
143         || !TEST_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
144         || !TEST_ptr(*serialized = mem_buf->data)
145         || !TEST_long_gt(*serialized_len = mem_buf->length, 0))
146         goto end;
147
148     /* Detach the serialized output */
149     mem_buf->data = NULL;
150     mem_buf->length = 0;
151     ok = 1;
152  end:
153     BIO_free(mem_ser);
154     OSSL_SERIALIZER_CTX_free(sctx);
155     return ok;
156 }
157
158 static int deserialize_EVP_PKEY_prov(void **object,
159                                      void *serialized, long serialized_len,
160                                      const char *pass, const char *pcipher)
161 {
162     EVP_PKEY *pkey = NULL;
163     OSSL_DESERIALIZER_CTX *dctx = NULL;
164     BIO *mem_deser = NULL;
165     const unsigned char *upass = (const unsigned char *)pass;
166     int ok = 0;
167
168     if (!TEST_ptr(dctx = OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(&pkey, NULL,
169                                                                NULL, NULL))
170         || (pass != NULL
171             && !OSSL_DESERIALIZER_CTX_set_passphrase(dctx, upass,
172                                                      strlen(pass)))
173         || (pcipher != NULL
174             && !OSSL_DESERIALIZER_CTX_set_cipher(dctx, pcipher, NULL))
175         || !TEST_ptr(mem_deser = BIO_new_mem_buf(serialized, serialized_len))
176         || !TEST_true(OSSL_DESERIALIZER_from_bio(dctx, mem_deser)))
177         goto end;
178     ok = 1;
179     *object = pkey;
180  end:
181     BIO_free(mem_deser);
182     OSSL_DESERIALIZER_CTX_free(dctx);
183     return ok;
184 }
185
186 static int serialize_EVP_PKEY_legacy_PEM(void **serialized,
187                                          long *serialized_len,
188                                          void *object,
189                                          const char *pass, const char *pcipher,
190                                          ossl_unused const char *ser_propq)
191 {
192     EVP_PKEY *pkey = object;
193     EVP_CIPHER *cipher = NULL;
194     BIO *mem_ser = NULL;
195     BUF_MEM *mem_buf = NULL;
196     const unsigned char *upass = (const unsigned char *)pass;
197     size_t passlen = 0;
198     int ok = 0;
199
200     if (pcipher != NULL && pass != NULL) {
201         passlen = strlen(pass);
202         if (!TEST_ptr(cipher = EVP_CIPHER_fetch(NULL, pcipher, NULL)))
203             goto end;
204     }
205     if (!TEST_ptr(mem_ser = BIO_new(BIO_s_mem()))
206         || !TEST_true(PEM_write_bio_PrivateKey_traditional(mem_ser, pkey,
207                                                            cipher,
208                                                            upass, passlen,
209                                                            NULL, NULL))
210         || !TEST_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
211         || !TEST_ptr(*serialized = mem_buf->data)
212         || !TEST_long_gt(*serialized_len = mem_buf->length, 0))
213         goto end;
214
215     /* Detach the serialized output */
216     mem_buf->data = NULL;
217     mem_buf->length = 0;
218     ok = 1;
219  end:
220     BIO_free(mem_ser);
221     EVP_CIPHER_free(cipher);
222     return ok;
223 }
224
225 /* Test cases and their dumpers / checkers */
226
227 static void dump_der(const char *label, const void *data, size_t data_len)
228 {
229     test_output_memory(label, data, data_len);
230 }
231
232 static void dump_pem(const char *label, const void *data, size_t data_len)
233 {
234     test_output_string(label, data, data_len - 1);
235 }
236
237 static int check_unprotected_PKCS8_DER(const char *type,
238                                        const void *data, size_t data_len)
239 {
240     const unsigned char *datap = data;
241     PKCS8_PRIV_KEY_INFO *p8inf =
242         d2i_PKCS8_PRIV_KEY_INFO(NULL, &datap, data_len);
243     int ok = 0;
244
245     if (TEST_ptr(p8inf)) {
246         EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
247
248         ok = (TEST_ptr(pkey) && TEST_true(EVP_PKEY_is_a(pkey, type)));
249         EVP_PKEY_free(pkey);
250     }
251     PKCS8_PRIV_KEY_INFO_free(p8inf);
252     return ok;
253 }
254
255 static int test_unprotected_RSA_via_DER(void)
256 {
257     return test_serialize_deserialize("RSA", key_RSA, NULL, NULL,
258                                       serialize_EVP_PKEY_prov,
259                                       deserialize_EVP_PKEY_prov,
260                                       check_unprotected_PKCS8_DER, dump_der,
261                                       OSSL_SERIALIZER_PrivateKey_TO_DER_PQ,
262                                       0);
263 }
264
265 static int test_unprotected_RSA_PSS_via_DER(void)
266 {
267     return test_serialize_deserialize("RSA-PSS", key_RSA_PSS, NULL, NULL,
268                                       serialize_EVP_PKEY_prov,
269                                       deserialize_EVP_PKEY_prov,
270                                       check_unprotected_PKCS8_DER, dump_der,
271                                       OSSL_SERIALIZER_PrivateKey_TO_DER_PQ,
272                                       0);
273 }
274
275 static int check_unprotected_PKCS8_PEM(const char *type,
276                                        const void *data, size_t data_len)
277 {
278     static const char pem_header[] = "-----BEGIN " PEM_STRING_PKCS8INF "-----";
279
280     return TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
281 }
282
283 static int test_unprotected_RSA_via_PEM(void)
284 {
285     return test_serialize_deserialize("RSA", key_RSA, NULL, NULL,
286                                       serialize_EVP_PKEY_prov,
287                                       deserialize_EVP_PKEY_prov,
288                                       check_unprotected_PKCS8_PEM, dump_pem,
289                                       OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ,
290                                       0);
291 }
292
293 static int test_unprotected_RSA_PSS_via_PEM(void)
294 {
295     return test_serialize_deserialize("RSA-PSS", key_RSA_PSS, NULL, NULL,
296                                       serialize_EVP_PKEY_prov,
297                                       deserialize_EVP_PKEY_prov,
298                                       check_unprotected_PKCS8_PEM, dump_pem,
299                                       OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ,
300                                       0);
301 }
302
303 static int check_unprotected_legacy_PEM(const char *type,
304                                         const void *data, size_t data_len)
305 {
306     static char pem_header[80];
307
308     return
309         TEST_int_gt(BIO_snprintf(pem_header, sizeof(pem_header),
310                                  "-----BEGIN %s PRIVATE KEY-----", type), 0)
311         && TEST_strn_eq(data, pem_header, strlen(pem_header));
312 }
313
314 static int test_unprotected_RSA_via_legacy_PEM(void)
315 {
316     return test_serialize_deserialize("RSA", legacy_key_RSA, NULL, NULL,
317                                       serialize_EVP_PKEY_legacy_PEM,
318                                       deserialize_EVP_PKEY_prov,
319                                       check_unprotected_legacy_PEM, dump_pem,
320                                       NULL, 1);
321 }
322
323 static int test_unprotected_RSA_PSS_via_legacy_PEM(void)
324 {
325     return test_serialize_deserialize("RSA-PSS", legacy_key_RSA_PSS, NULL, NULL,
326                                       serialize_EVP_PKEY_legacy_PEM,
327                                       deserialize_EVP_PKEY_prov,
328                                       check_unprotected_legacy_PEM, dump_pem,
329                                       NULL, 1);
330 }
331
332 static const char *pass_cipher = "AES-256-CBC";
333 static const char *pass = "the holy handgrenade of antioch";
334
335 static int check_protected_PKCS8_DER(const char *type,
336                                      const void *data, size_t data_len)
337 {
338     const unsigned char *datap = data;
339     X509_SIG *p8 = d2i_X509_SIG(NULL, &datap, data_len);
340     int ok = TEST_ptr(p8);
341
342     X509_SIG_free(p8);
343     return ok;
344 }
345
346 static int test_protected_RSA_via_DER(void)
347 {
348     return test_serialize_deserialize("RSA", key_RSA, pass, pass_cipher,
349                                       serialize_EVP_PKEY_prov,
350                                       deserialize_EVP_PKEY_prov,
351                                       check_protected_PKCS8_DER, dump_der,
352                                       OSSL_SERIALIZER_PrivateKey_TO_DER_PQ,
353                                       0);
354 }
355
356 static int test_protected_RSA_PSS_via_DER(void)
357 {
358     return test_serialize_deserialize("RSA", key_RSA, pass, pass_cipher,
359                                       serialize_EVP_PKEY_prov,
360                                       deserialize_EVP_PKEY_prov,
361                                       check_protected_PKCS8_DER, dump_der,
362                                       OSSL_SERIALIZER_PrivateKey_TO_DER_PQ,
363                                       0);
364 }
365
366 static int check_protected_PKCS8_PEM(const char *type,
367                                      const void *data, size_t data_len)
368 {
369     static const char pem_header[] = "-----BEGIN " PEM_STRING_PKCS8 "-----";
370
371     return TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
372 }
373
374 static int test_protected_RSA_via_PEM(void)
375 {
376     return test_serialize_deserialize("RSA", key_RSA, pass, pass_cipher,
377                                       serialize_EVP_PKEY_prov,
378                                       deserialize_EVP_PKEY_prov,
379                                       check_protected_PKCS8_PEM, dump_pem,
380                                       OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ,
381                                       0);
382 }
383
384 static int test_protected_RSA_PSS_via_PEM(void)
385 {
386     return test_serialize_deserialize("RSA-PSS", key_RSA_PSS, pass, pass_cipher,
387                                       serialize_EVP_PKEY_prov,
388                                       deserialize_EVP_PKEY_prov,
389                                       check_protected_PKCS8_PEM, dump_pem,
390                                       OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ,
391                                       0);
392 }
393
394 static int check_protected_legacy_PEM(const char *type,
395                                       const void *data, size_t data_len)
396 {
397     static char pem_header[80];
398
399     return
400         TEST_int_gt(BIO_snprintf(pem_header, sizeof(pem_header),
401                                  "-----BEGIN %s PRIVATE KEY-----", type), 0)
402         && TEST_strn_eq(data, pem_header, strlen(pem_header))
403         && TEST_ptr(strstr(data, "\nDEK-Info: "));
404 }
405
406 static int test_protected_RSA_via_legacy_PEM(void)
407 {
408     return test_serialize_deserialize("RSA", legacy_key_RSA, pass, pass_cipher,
409                                       serialize_EVP_PKEY_legacy_PEM,
410                                       deserialize_EVP_PKEY_prov,
411                                       check_protected_legacy_PEM, dump_pem,
412                                       NULL, 1);
413 }
414
415 static int test_protected_RSA_PSS_via_legacy_PEM(void)
416 {
417     return test_serialize_deserialize("RSA-PSS", legacy_key_RSA_PSS,
418                                       pass, pass_cipher,
419                                       serialize_EVP_PKEY_legacy_PEM,
420                                       deserialize_EVP_PKEY_prov,
421                                       check_protected_legacy_PEM, dump_pem,
422                                       NULL, 1);
423 }
424
425 int setup_tests(void)
426 {
427     TEST_info("Generating keys...");
428     if (!TEST_ptr(key_RSA = make_RSA("RSA", 0))
429         || !TEST_ptr(legacy_key_RSA = make_RSA("RSA", 1))
430         || !TEST_ptr(key_RSA_PSS = make_RSA("RSA-PSS", 0))
431         || !TEST_ptr(legacy_key_RSA_PSS = make_RSA("RSA-PSS", 1))) {
432         EVP_PKEY_free(key_RSA);
433         EVP_PKEY_free(legacy_key_RSA);
434         EVP_PKEY_free(key_RSA_PSS);
435         EVP_PKEY_free(legacy_key_RSA_PSS);
436         return 0;
437     }
438     TEST_info("Generating key... done");
439
440     ADD_TEST(test_unprotected_RSA_via_DER);
441     ADD_TEST(test_unprotected_RSA_via_PEM);
442     ADD_TEST(test_unprotected_RSA_via_legacy_PEM);
443     ADD_TEST(test_protected_RSA_via_DER);
444     ADD_TEST(test_protected_RSA_via_PEM);
445     ADD_TEST(test_protected_RSA_via_legacy_PEM);
446     ADD_TEST(test_unprotected_RSA_PSS_via_DER);
447     ADD_TEST(test_unprotected_RSA_PSS_via_PEM);
448     ADD_TEST(test_unprotected_RSA_PSS_via_legacy_PEM);
449     ADD_TEST(test_protected_RSA_PSS_via_DER);
450     ADD_TEST(test_protected_RSA_PSS_via_PEM);
451     ADD_TEST(test_protected_RSA_PSS_via_legacy_PEM);
452
453     return 1;
454 }