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