2 * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
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
11 #include <openssl/evp.h>
12 #include <openssl/pem.h>
13 #include <openssl/rsa.h>
14 #include <openssl/x509.h>
15 #include <openssl/params.h>
16 #include <openssl/serializer.h>
17 #include <openssl/deserializer.h>
19 #include "internal/cryptlib.h" /* ossl_assert */
24 * TODO(3.0) Modify PEM_write_bio_PrivateKey_traditional() to handle
25 * provider side EVP_PKEYs (which don't necessarily have an ameth)
27 * In the mean time, we use separate "downgraded" EVP_PKEYs to test
28 * serializing/deserializing with "traditional" keys.
31 static EVP_PKEY *make_template(const char *type, OSSL_PARAM *genparams)
33 EVP_PKEY *pkey = NULL;
34 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, type, NULL);
37 * No real need to check the errors other than for the cascade
38 * effect. |pkey| will simply remain NULL if something goes wrong.
41 && EVP_PKEY_paramgen_init(ctx) > 0
43 || EVP_PKEY_CTX_set_params(ctx, genparams) > 0)
44 && EVP_PKEY_gen(ctx, &pkey) > 0);
45 EVP_PKEY_CTX_free(ctx);
50 static EVP_PKEY *make_key(const char *type, EVP_PKEY *template,
51 OSSL_PARAM *genparams, int make_legacy)
53 EVP_PKEY *pkey = NULL;
56 ? EVP_PKEY_CTX_new(template, NULL)
57 : EVP_PKEY_CTX_new_from_name(NULL, type, NULL);
60 * No real need to check the errors other than for the cascade
61 * effect. |pkey| will simply remain NULL if something goes wrong.
64 && EVP_PKEY_keygen_init(ctx) > 0
66 || EVP_PKEY_CTX_set_params(ctx, genparams) > 0)
67 && EVP_PKEY_keygen(ctx, &pkey) > 0);
68 EVP_PKEY_CTX_free(ctx);
69 if (make_legacy && EVP_PKEY_get0(pkey) == NULL) {
78 /* Main test driver */
81 * TODO(3.0) For better error output, changed the callbacks to take __FILE__
82 * and __LINE__ as first two arguments, and have them use the lower case
83 * functions, such as test_strn_eq(), rather than the uppercase macros
84 * (TEST_strn2_eq(), for example).
87 typedef int (serializer)(void **serialized, long *serialized_len,
88 void *object, const char *pass, const char *pcipher,
89 const char *ser_propq);
90 typedef int (deserializer)(void **object,
91 void *serialized, long serialized_len,
93 typedef int (checker)(const char *type, const void *data, size_t data_len);
94 typedef void (dumper)(const char *label, const void *data, size_t data_len);
96 static int test_serialize_deserialize(const char *type, EVP_PKEY *pkey,
97 const char *pass, const char *pcipher,
98 serializer *serialize_cb,
99 deserializer *deserialize_cb,
100 checker *check_cb, dumper *dump_cb,
101 const char *ser_propq, int make_legacy)
103 void *serialized = NULL;
104 long serialized_len = 0;
105 EVP_PKEY *pkey2 = NULL;
106 void *serialized2 = NULL;
107 long serialized2_len = 0;
110 if (!serialize_cb(&serialized, &serialized_len, pkey,
111 pass, pcipher, ser_propq)
112 || !check_cb(type, serialized, serialized_len)
113 || !deserialize_cb((void **)&pkey2, serialized, serialized_len,
115 || !TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 1))
119 * TODO(3.0) Remove this when PEM_write_bio_PrivateKey_traditional()
120 * handles provider side keys.
123 && !TEST_ptr(EVP_PKEY_get0(pkey2)))
127 * Double check the serialization, but only for unprotected keys,
128 * as protected keys have a random component, which makes the output
131 if ((pass == NULL && pcipher == NULL)
132 && (!serialize_cb(&serialized2, &serialized2_len, pkey2,
133 pass, pcipher, ser_propq)
134 || !TEST_mem_eq(serialized, serialized_len,
135 serialized2, serialized2_len)))
141 dump_cb("serialized result", serialized, serialized_len);
143 OPENSSL_free(serialized);
144 OPENSSL_free(serialized2);
145 EVP_PKEY_free(pkey2);
149 /* Serializing and desserializing methods */
151 static int serialize_EVP_PKEY_prov(void **serialized, long *serialized_len,
153 const char *pass, const char *pcipher,
154 const char *ser_propq)
156 EVP_PKEY *pkey = object;
157 OSSL_SERIALIZER_CTX *sctx = NULL;
159 BUF_MEM *mem_buf = NULL;
160 const unsigned char *upass = (const unsigned char *)pass;
163 if (!TEST_ptr(sctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, ser_propq))
165 && !TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(sctx, upass,
168 && !TEST_true(OSSL_SERIALIZER_CTX_set_cipher(sctx, pcipher, NULL)))
169 || !TEST_ptr(mem_ser = BIO_new(BIO_s_mem()))
170 || !TEST_true(OSSL_SERIALIZER_to_bio(sctx, mem_ser))
171 || !TEST_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
172 || !TEST_ptr(*serialized = mem_buf->data)
173 || !TEST_long_gt(*serialized_len = mem_buf->length, 0))
176 /* Detach the serialized output */
177 mem_buf->data = NULL;
182 OSSL_SERIALIZER_CTX_free(sctx);
186 static int deserialize_EVP_PKEY_prov(void **object,
187 void *serialized, long serialized_len,
190 EVP_PKEY *pkey = NULL;
191 OSSL_DESERIALIZER_CTX *dctx = NULL;
192 BIO *mem_deser = NULL;
193 const unsigned char *upass = (const unsigned char *)pass;
196 if (!TEST_ptr(dctx = OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(&pkey, NULL,
199 && !OSSL_DESERIALIZER_CTX_set_passphrase(dctx, upass,
201 || !TEST_ptr(mem_deser = BIO_new_mem_buf(serialized, serialized_len))
202 || !TEST_true(OSSL_DESERIALIZER_from_bio(dctx, mem_deser)))
208 OSSL_DESERIALIZER_CTX_free(dctx);
212 static int serialize_EVP_PKEY_legacy_PEM(void **serialized,
213 long *serialized_len,
215 const char *pass, const char *pcipher,
216 ossl_unused const char *ser_propq)
218 EVP_PKEY *pkey = object;
219 EVP_CIPHER *cipher = NULL;
221 BUF_MEM *mem_buf = NULL;
222 const unsigned char *upass = (const unsigned char *)pass;
226 if (pcipher != NULL && pass != NULL) {
227 passlen = strlen(pass);
228 if (!TEST_ptr(cipher = EVP_CIPHER_fetch(NULL, pcipher, NULL)))
231 if (!TEST_ptr(mem_ser = BIO_new(BIO_s_mem()))
232 || !TEST_true(PEM_write_bio_PrivateKey_traditional(mem_ser, pkey,
236 || !TEST_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
237 || !TEST_ptr(*serialized = mem_buf->data)
238 || !TEST_long_gt(*serialized_len = mem_buf->length, 0))
241 /* Detach the serialized output */
242 mem_buf->data = NULL;
247 EVP_CIPHER_free(cipher);
251 /* Test cases and their dumpers / checkers */
253 static void dump_der(const char *label, const void *data, size_t data_len)
255 test_output_memory(label, data, data_len);
258 static void dump_pem(const char *label, const void *data, size_t data_len)
260 test_output_string(label, data, data_len - 1);
263 static int check_unprotected_PKCS8_DER(const char *type,
264 const void *data, size_t data_len)
266 const unsigned char *datap = data;
267 PKCS8_PRIV_KEY_INFO *p8inf =
268 d2i_PKCS8_PRIV_KEY_INFO(NULL, &datap, data_len);
271 if (TEST_ptr(p8inf)) {
272 EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
274 ok = (TEST_ptr(pkey) && TEST_true(EVP_PKEY_is_a(pkey, type)));
277 PKCS8_PRIV_KEY_INFO_free(p8inf);
281 static int test_unprotected_via_DER(const char *type, EVP_PKEY *key)
283 return test_serialize_deserialize(type, key, NULL, NULL,
284 serialize_EVP_PKEY_prov,
285 deserialize_EVP_PKEY_prov,
286 check_unprotected_PKCS8_DER, dump_der,
287 OSSL_SERIALIZER_PrivateKey_TO_DER_PQ,
291 static int check_unprotected_PKCS8_PEM(const char *type,
292 const void *data, size_t data_len)
294 static const char pem_header[] = "-----BEGIN " PEM_STRING_PKCS8INF "-----";
296 return TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
299 static int test_unprotected_via_PEM(const char *type, EVP_PKEY *key)
301 return test_serialize_deserialize(type, key, NULL, NULL,
302 serialize_EVP_PKEY_prov,
303 deserialize_EVP_PKEY_prov,
304 check_unprotected_PKCS8_PEM, dump_pem,
305 OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ,
309 static int check_unprotected_legacy_PEM(const char *type,
310 const void *data, size_t data_len)
312 static char pem_header[80];
315 TEST_int_gt(BIO_snprintf(pem_header, sizeof(pem_header),
316 "-----BEGIN %s PRIVATE KEY-----", type), 0)
317 && TEST_strn_eq(data, pem_header, strlen(pem_header));
320 static int test_unprotected_via_legacy_PEM(const char *type, EVP_PKEY *key)
322 return test_serialize_deserialize(type, key, NULL, NULL,
323 serialize_EVP_PKEY_legacy_PEM,
324 deserialize_EVP_PKEY_prov,
325 check_unprotected_legacy_PEM, dump_pem,
329 static const char *pass_cipher = "AES-256-CBC";
330 static const char *pass = "the holy handgrenade of antioch";
332 static int check_protected_PKCS8_DER(const char *type,
333 const void *data, size_t data_len)
335 const unsigned char *datap = data;
336 X509_SIG *p8 = d2i_X509_SIG(NULL, &datap, data_len);
337 int ok = TEST_ptr(p8);
343 static int test_protected_via_DER(const char *type, EVP_PKEY *key)
345 return test_serialize_deserialize(type, key, pass, pass_cipher,
346 serialize_EVP_PKEY_prov,
347 deserialize_EVP_PKEY_prov,
348 check_protected_PKCS8_DER, dump_der,
349 OSSL_SERIALIZER_PrivateKey_TO_DER_PQ,
353 static int check_protected_PKCS8_PEM(const char *type,
354 const void *data, size_t data_len)
356 static const char pem_header[] = "-----BEGIN " PEM_STRING_PKCS8 "-----";
358 return TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
361 static int test_protected_via_PEM(const char *type, EVP_PKEY *key)
363 return test_serialize_deserialize(type, key, pass, pass_cipher,
364 serialize_EVP_PKEY_prov,
365 deserialize_EVP_PKEY_prov,
366 check_protected_PKCS8_PEM, dump_pem,
367 OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ,
371 static int check_protected_legacy_PEM(const char *type,
372 const void *data, size_t data_len)
374 static char pem_header[80];
377 TEST_int_gt(BIO_snprintf(pem_header, sizeof(pem_header),
378 "-----BEGIN %s PRIVATE KEY-----", type), 0)
379 && TEST_strn_eq(data, pem_header, strlen(pem_header))
380 && TEST_ptr(strstr(data, "\nDEK-Info: "));
383 static int test_protected_via_legacy_PEM(const char *type, EVP_PKEY *key)
385 return test_serialize_deserialize(type, key, pass, pass_cipher,
386 serialize_EVP_PKEY_legacy_PEM,
387 deserialize_EVP_PKEY_prov,
388 check_protected_legacy_PEM, dump_pem,
392 static int check_public_DER(const char *type, const void *data, size_t data_len)
394 const unsigned char *datap = data;
395 EVP_PKEY *pkey = d2i_PUBKEY(NULL, &datap, data_len);
396 int ok = (TEST_ptr(pkey) && TEST_true(EVP_PKEY_is_a(pkey, type)));
402 static int test_public_via_DER(const char *type, EVP_PKEY *key)
404 return test_serialize_deserialize(type, key, NULL, NULL,
405 serialize_EVP_PKEY_prov,
406 deserialize_EVP_PKEY_prov,
407 check_public_DER, dump_der,
408 OSSL_SERIALIZER_PUBKEY_TO_DER_PQ,
412 static int check_public_PEM(const char *type, const void *data, size_t data_len)
414 static const char pem_header[] = "-----BEGIN " PEM_STRING_PUBLIC "-----";
417 TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
420 static int test_public_via_PEM(const char *type, EVP_PKEY *key)
422 return test_serialize_deserialize(type, key, NULL, NULL,
423 serialize_EVP_PKEY_prov,
424 deserialize_EVP_PKEY_prov,
425 check_public_PEM, dump_pem,
426 OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ,
430 #define KEYS(KEYTYPE) \
431 static EVP_PKEY *key_##KEYTYPE = NULL; \
432 static EVP_PKEY *legacy_key_##KEYTYPE = NULL
433 #define MAKE_KEYS(KEYTYPE, KEYTYPEstr, params) \
435 && TEST_ptr(key_##KEYTYPE = \
436 make_key(KEYTYPEstr, NULL, params, 0)) \
437 && TEST_ptr(legacy_key_##KEYTYPE = \
438 make_key(KEYTYPEstr, NULL, params, 1))
439 #define FREE_KEYS(KEYTYPE) \
440 EVP_PKEY_free(key_##KEYTYPE); \
441 EVP_PKEY_free(legacy_key_##KEYTYPE)
443 #define DOMAIN_KEYS(KEYTYPE) \
444 static EVP_PKEY *template_##KEYTYPE = NULL; \
445 static EVP_PKEY *key_##KEYTYPE = NULL; \
446 static EVP_PKEY *legacy_key_##KEYTYPE = NULL
447 #define MAKE_DOMAIN_KEYS(KEYTYPE, KEYTYPEstr, params) \
449 && TEST_ptr(template_##KEYTYPE = \
450 make_template(KEYTYPEstr, params)) \
451 && TEST_ptr(key_##KEYTYPE = \
452 make_key(KEYTYPEstr, template_##KEYTYPE, NULL, 0)) \
453 && TEST_ptr(legacy_key_##KEYTYPE = \
454 make_key(KEYTYPEstr, template_##KEYTYPE, NULL, 1))
455 #define FREE_DOMAIN_KEYS(KEYTYPE) \
456 EVP_PKEY_free(template_##KEYTYPE); \
457 EVP_PKEY_free(key_##KEYTYPE); \
458 EVP_PKEY_free(legacy_key_##KEYTYPE)
460 #define IMPLEMENT_TEST_SUITE(KEYTYPE, KEYTYPEstr) \
461 static int test_unprotected_##KEYTYPE##_via_DER(void) \
463 return test_unprotected_via_DER(KEYTYPEstr, key_##KEYTYPE); \
465 static int test_unprotected_##KEYTYPE##_via_PEM(void) \
467 return test_unprotected_via_PEM(KEYTYPEstr, key_##KEYTYPE); \
469 static int test_unprotected_##KEYTYPE##_via_legacy_PEM(void) \
471 return test_unprotected_via_legacy_PEM(KEYTYPEstr, \
472 legacy_key_##KEYTYPE); \
474 static int test_protected_##KEYTYPE##_via_DER(void) \
476 return test_protected_via_DER(KEYTYPEstr, key_##KEYTYPE); \
478 static int test_protected_##KEYTYPE##_via_PEM(void) \
480 return test_protected_via_PEM(KEYTYPEstr, key_##KEYTYPE); \
482 static int test_protected_##KEYTYPE##_via_legacy_PEM(void) \
484 return test_protected_via_legacy_PEM(KEYTYPEstr, \
485 legacy_key_##KEYTYPE); \
487 static int test_public_##KEYTYPE##_via_DER(void) \
489 return test_public_via_DER(KEYTYPEstr, key_##KEYTYPE); \
491 static int test_public_##KEYTYPE##_via_PEM(void) \
493 return test_public_via_PEM(KEYTYPEstr, key_##KEYTYPE); \
496 #define ADD_TEST_SUITE(KEYTYPE) \
497 ADD_TEST(test_unprotected_##KEYTYPE##_via_DER); \
498 ADD_TEST(test_unprotected_##KEYTYPE##_via_PEM); \
499 ADD_TEST(test_unprotected_##KEYTYPE##_via_legacy_PEM); \
500 ADD_TEST(test_protected_##KEYTYPE##_via_DER); \
501 ADD_TEST(test_protected_##KEYTYPE##_via_PEM); \
502 ADD_TEST(test_protected_##KEYTYPE##_via_legacy_PEM); \
503 ADD_TEST(test_public_##KEYTYPE##_via_DER); \
504 ADD_TEST(test_public_##KEYTYPE##_via_PEM)
506 #ifndef OPENSSL_NO_DH
508 IMPLEMENT_TEST_SUITE(DH, "DH")
510 #ifndef OPENSSL_NO_DSA
512 IMPLEMENT_TEST_SUITE(DSA, "DSA")
514 #ifndef OPENSSL_NO_EC
516 IMPLEMENT_TEST_SUITE(EC, "EC")
518 IMPLEMENT_TEST_SUITE(ED25519, "ED25519")
520 IMPLEMENT_TEST_SUITE(ED448, "ED448")
522 IMPLEMENT_TEST_SUITE(X25519, "X25519")
524 IMPLEMENT_TEST_SUITE(X448, "X448")
527 IMPLEMENT_TEST_SUITE(RSA, "RSA")
529 IMPLEMENT_TEST_SUITE(RSA_PSS, "RSA-PSS")
531 int setup_tests(void)
535 #ifndef OPENSSL_NO_EC
536 static char groupname[] = "prime256v1";
537 OSSL_PARAM EC_params[] = {
538 OSSL_PARAM_utf8_string("group", groupname, sizeof(groupname) - 1),
543 /* 7 is the default magic number */
544 static unsigned int rsapss_min_saltlen = 7;
545 OSSL_PARAM RSA_PSS_params[] = {
546 OSSL_PARAM_uint("saltlen", &rsapss_min_saltlen),
550 TEST_info("Generating keys...");
551 #ifndef OPENSSL_NO_DH
552 MAKE_DOMAIN_KEYS(DH, "DH", NULL);
554 #ifndef OPENSSL_NO_DSA
555 MAKE_DOMAIN_KEYS(DSA, "DSA", NULL);
557 #ifndef OPENSSL_NO_EC
558 MAKE_DOMAIN_KEYS(EC, "EC", EC_params);
559 MAKE_KEYS(ED25519, "ED25519", NULL);
560 MAKE_KEYS(ED448, "ED448", NULL);
561 MAKE_KEYS(X25519, "X25519", NULL);
562 MAKE_KEYS(X448, "X448", NULL);
564 MAKE_KEYS(RSA, "RSA", NULL);
565 MAKE_KEYS(RSA_PSS, "RSA-PSS", RSA_PSS_params);
566 TEST_info("Generating key... done");
569 #ifndef OPENSSL_NO_DH
572 #ifndef OPENSSL_NO_DSA
575 #ifndef OPENSSL_NO_EC
577 ADD_TEST_SUITE(ED25519);
578 ADD_TEST_SUITE(ED448);
579 ADD_TEST_SUITE(X25519);
580 ADD_TEST_SUITE(X448);
583 ADD_TEST_SUITE(RSA_PSS);
589 void cleanup_tests(void)
591 #ifndef OPENSSL_NO_DH
592 FREE_DOMAIN_KEYS(DH);
594 #ifndef OPENSSL_NO_DSA
595 FREE_DOMAIN_KEYS(DSA);
597 #ifndef OPENSSL_NO_EC
598 FREE_DOMAIN_KEYS(EC);