2 * Copyright 2019-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
10 #include <openssl/evp.h>
11 #include <openssl/pem.h>
12 #include <openssl/serializer.h>
13 #include <openssl/provider.h>
14 #include <openssl/params.h>
15 #include <openssl/core_names.h>
16 #include "crypto/ecx.h"
17 #include "internal/nelem.h"
18 #include "internal/param_build.h"
19 #include "crypto/evp.h" /* For the internal API */
22 static char *datadir = NULL;
31 static void stripcr(char *buf, size_t *len)
36 for (i = *len, curr = buf, writ = buf; i > 0; i--, curr++) {
47 static int compare_with_file(const char *alg, int type, BIO *membio)
52 char *memdata, *fullfile = NULL;
85 TEST_error("Invalid file type");
89 BIO_snprintf(filename, sizeof(filename), "%s.%s", alg, suffix);
90 fullfile = test_mk_file_path(datadir, filename);
91 if (!TEST_ptr(fullfile))
94 file = BIO_new_file(fullfile, "rb");
98 if (!TEST_true(BIO_read_ex(file, buf, sizeof(buf), &readbytes))
99 || !TEST_true(BIO_eof(file))
100 || !TEST_size_t_lt(readbytes, sizeof(buf)))
103 len = BIO_get_mem_data(membio, &memdata);
104 if (!TEST_int_gt(len, 0))
108 if (type != PRIV_DER && type != PUB_DER) {
109 stripcr(memdata, &slen);
110 stripcr(buf, &readbytes);
113 if (!TEST_mem_eq(memdata, slen, buf, readbytes))
118 OPENSSL_free(fullfile);
119 (void)BIO_reset(membio);
124 static int test_print_key_using_pem(const char *alg, const EVP_PKEY *pk)
126 BIO *membio = BIO_new(BIO_s_mem());
129 if (!TEST_ptr(membio))
132 if (!TEST_true(EVP_PKEY_print_private(membio, pk, 0, NULL))
133 || !TEST_true(compare_with_file(alg, PRIV_TEXT, membio))
134 /* Public key in PEM form */
135 || !TEST_true(PEM_write_bio_PUBKEY(membio, pk))
136 || !TEST_true(compare_with_file(alg, PUB_PEM, membio))
137 /* Unencrypted private key in PEM form */
138 || !TEST_true(PEM_write_bio_PrivateKey(membio, pk,
139 NULL, NULL, 0, NULL, NULL))
140 || !TEST_true(compare_with_file(alg, PRIV_PEM, membio))
141 /* Encrypted private key in PEM form */
142 || !TEST_true(PEM_write_bio_PrivateKey(bio_out, pk, EVP_aes_256_cbc(),
143 (unsigned char *)"pass", 4,
153 static int test_print_key_type_using_serializer(const char *alg, int type,
157 OSSL_SERIALIZER_CTX *ctx = NULL;
158 BIO *membio = BIO_new(BIO_s_mem());
163 pq = OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ;
167 pq = OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ;
171 pq = OSSL_SERIALIZER_PrivateKey_TO_DER_PQ;
175 pq = OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ;
179 pq = OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ;
183 pq = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ;
187 TEST_error("Invalid serialization type");
191 if (!TEST_ptr(membio))
194 /* Make a context, it's valid for several prints */
195 TEST_note("Setting up a OSSL_SERIALIZER context with passphrase");
196 if (!TEST_ptr(ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pk, pq))
197 /* Check that this operation is supported */
198 || !TEST_ptr(OSSL_SERIALIZER_CTX_get_serializer(ctx)))
201 /* Use no cipher. This should give us an unencrypted PEM */
202 TEST_note("Testing with no encryption");
203 if (!TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
204 || !TEST_true(compare_with_file(alg, type, membio)))
207 if (type == PRIV_PEM) {
208 /* Set a passphrase to be used later */
209 if (!TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(ctx,
210 (unsigned char *)"pass",
214 /* Use a valid cipher name */
215 TEST_note("Displaying PEM encrypted with AES-256-CBC");
216 if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, "AES-256-CBC", NULL))
217 || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
220 /* Use an invalid cipher name, which should generate no output */
221 TEST_note("NOT Displaying PEM encrypted with (invalid) FOO");
222 if (!TEST_false(OSSL_SERIALIZER_CTX_set_cipher(ctx, "FOO", NULL))
223 || !TEST_false(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
226 /* Clear the cipher. This should give us an unencrypted PEM again */
227 TEST_note("Testing with encryption cleared (no encryption)");
228 if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, NULL, NULL))
229 || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
230 || !TEST_true(compare_with_file(alg, type, membio)))
236 OSSL_SERIALIZER_CTX_free(ctx);
240 static int test_print_key_using_serializer(const char *alg, const EVP_PKEY *pk)
245 for (i = 0; i < 6; i++)
246 ret = ret && test_print_key_type_using_serializer(alg, i, pk);
251 /* Array indexes used in test_fromdata_rsa */
261 static int test_fromdata_rsa(void)
264 EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
265 EVP_PKEY *pk = NULL, *copy_pk = NULL;
267 * 32-bit RSA key, extracted from this command,
268 * executed with OpenSSL 1.0.2:
270 * openssl genrsa 32 | openssl rsa -text
272 static unsigned long key_numbers[] = {
282 OSSL_PARAM fromdata_params[] = {
283 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_N, &key_numbers[N]),
284 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_E, &key_numbers[E]),
285 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_D, &key_numbers[D]),
286 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[P]),
287 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[Q]),
288 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DP]),
289 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DQ]),
290 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT, &key_numbers[QINV]),
294 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)))
297 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
298 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
299 || !TEST_int_eq(EVP_PKEY_bits(pk), 32)
300 || !TEST_int_eq(EVP_PKEY_security_bits(pk), 8)
301 || !TEST_int_eq(EVP_PKEY_size(pk), 4))
304 if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
307 if (!TEST_true(EVP_PKEY_check(key_ctx))
308 || !TEST_true(EVP_PKEY_public_check(key_ctx))
309 || !TEST_true(EVP_PKEY_private_check(key_ctx))
310 || !TEST_true(EVP_PKEY_pairwise_check(key_ctx)))
313 /* EVP_PKEY_copy_parameters() should fail for RSA */
314 if (!TEST_ptr(copy_pk = EVP_PKEY_new())
315 || !TEST_false(EVP_PKEY_copy_parameters(copy_pk, pk)))
318 ret = test_print_key_using_pem("RSA", pk)
319 && test_print_key_using_serializer("RSA", pk);
323 EVP_PKEY_free(copy_pk);
324 EVP_PKEY_CTX_free(key_ctx);
325 EVP_PKEY_CTX_free(ctx);
330 #ifndef OPENSSL_NO_DH
331 /* Array indexes used in test_fromdata_dh */
337 static int test_fromdata_dh(void)
340 EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
341 EVP_PKEY *pk = NULL, *copy_pk = NULL;
343 * 32-bit DH key, extracted from this command,
344 * executed with OpenSSL 1.0.2:
346 * openssl dhparam -out dhp.pem 32
347 * openssl genpkey -paramfile dhp.pem | openssl pkey -text
349 static unsigned long key_numbers[] = {
350 0x666c2b06, /* priv-key */
351 0x6fa6de50, /* pub-key */
355 OSSL_PARAM fromdata_params[] = {
356 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_PRIV_KEY, &key_numbers[PRIV_KEY]),
357 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_PUB_KEY, &key_numbers[PUB_KEY]),
358 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_FFC_P, &key_numbers[FFC_P]),
359 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_FFC_G, &key_numbers[FFC_G]),
363 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)))
366 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
367 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
368 || !TEST_int_eq(EVP_PKEY_bits(pk), 32)
369 || !TEST_int_eq(EVP_PKEY_security_bits(pk), 0) /* Missing Q */
370 || !TEST_int_eq(EVP_PKEY_size(pk), 4))
373 if (!TEST_ptr(copy_pk = EVP_PKEY_new())
374 || !TEST_true(EVP_PKEY_copy_parameters(copy_pk, pk)))
377 ret = test_print_key_using_pem("DH", pk)
378 && test_print_key_using_serializer("DH", pk);
380 if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
383 if (!TEST_false(EVP_PKEY_check(key_ctx))
384 || !TEST_true(EVP_PKEY_public_check(key_ctx))
385 || !TEST_false(EVP_PKEY_private_check(key_ctx)) /* Need a q */
386 || !TEST_true(EVP_PKEY_pairwise_check(key_ctx)))
391 EVP_PKEY_free(copy_pk);
392 EVP_PKEY_CTX_free(ctx);
393 EVP_PKEY_CTX_free(key_ctx);
399 #ifndef OPENSSL_NO_EC
400 /* Array indexes used in test_fromdata_ecx */
404 # define X25519_IDX 0
406 # define ED25519_IDX 2
409 static int test_fromdata_ecx(int tst)
412 EVP_PKEY_CTX *ctx = NULL;
413 EVP_PKEY *pk = NULL, *copy_pk = NULL;
414 const char *alg = NULL;
416 /* ED448_KEYLEN > X448_KEYLEN > X25519_KEYLEN == ED25519_KEYLEN */
417 static unsigned char key_numbers[4][2][ED448_KEYLEN] = {
418 /* X25519: Keys from RFC 7748 6.1 */
422 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
423 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
424 0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
429 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
430 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
431 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
435 /* X448: Keys from RFC 7748 6.2 */
439 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf,
440 0x46, 0xb0, 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba,
441 0xe8, 0xbc, 0x55, 0x65, 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9,
442 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 0x44, 0x89, 0x73, 0x91,
443 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 0x9a, 0xc2,
444 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b
448 0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22,
449 0xd5, 0xae, 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8,
450 0x3d, 0xe0, 0x9c, 0x63, 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5,
451 0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 0x41, 0xd9, 0x53, 0xd4,
452 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
453 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
456 /* ED25519: Keys from RFC 8032 */
460 0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84,
461 0x4a, 0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69,
462 0x7b, 0x32, 0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae,
467 0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b,
468 0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3,
469 0xda, 0xa6, 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07,
473 /* ED448: Keys from RFC 8032 */
477 0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, 0x10, 0xd6, 0x32,
478 0xbe, 0x89, 0xc8, 0x51, 0x3e, 0xbf, 0x6c, 0x92, 0x9f, 0x34,
479 0xdd, 0xfa, 0x8c, 0x9f, 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3,
480 0x48, 0xa3, 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, 0x4e,
481 0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, 0x8f, 0x03, 0x2e,
482 0x75, 0x49, 0xa2, 0x00, 0x98, 0xf9, 0x5b
486 0x5f, 0xd7, 0x44, 0x9b, 0x59, 0xb4, 0x61, 0xfd, 0x2c, 0xe7,
487 0x87, 0xec, 0x61, 0x6a, 0xd4, 0x6a, 0x1d, 0xa1, 0x34, 0x24,
488 0x85, 0xa7, 0x0e, 0x1f, 0x8a, 0x0e, 0xa7, 0x5d, 0x80, 0xe9,
489 0x67, 0x78, 0xed, 0xf1, 0x24, 0x76, 0x9b, 0x46, 0xc7, 0x06,
490 0x1b, 0xd6, 0x78, 0x3d, 0xf1, 0xe5, 0x0f, 0x6c, 0xd1, 0xfa,
491 0x1a, 0xbe, 0xaf, 0xe8, 0x25, 0x61, 0x80
495 OSSL_PARAM x25519_fromdata_params[] = {
496 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
497 key_numbers[X25519_IDX][PRIV_KEY],
499 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
500 key_numbers[X25519_IDX][PUB_KEY],
504 OSSL_PARAM x448_fromdata_params[] = {
505 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
506 key_numbers[X448_IDX][PRIV_KEY],
508 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
509 key_numbers[X448_IDX][PUB_KEY],
513 OSSL_PARAM ed25519_fromdata_params[] = {
514 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
515 key_numbers[ED25519_IDX][PRIV_KEY],
517 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
518 key_numbers[ED25519_IDX][PUB_KEY],
522 OSSL_PARAM ed448_fromdata_params[] = {
523 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
524 key_numbers[ED448_IDX][PRIV_KEY],
526 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
527 key_numbers[ED448_IDX][PUB_KEY],
531 OSSL_PARAM *fromdata_params = NULL;
532 int bits = 0, security_bits = 0, size = 0;
536 fromdata_params = x25519_fromdata_params;
538 security_bits = X25519_SECURITY_BITS;
539 size = X25519_KEYLEN;
544 fromdata_params = x448_fromdata_params;
546 security_bits = X448_SECURITY_BITS;
552 fromdata_params = ed25519_fromdata_params;
554 security_bits = ED25519_SECURITY_BITS;
555 size = ED25519_KEYLEN;
560 fromdata_params = ed448_fromdata_params;
562 security_bits = ED448_SECURITY_BITS;
568 ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
572 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
573 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
574 || !TEST_int_eq(EVP_PKEY_bits(pk), bits)
575 || !TEST_int_eq(EVP_PKEY_security_bits(pk), security_bits)
576 || !TEST_int_eq(EVP_PKEY_size(pk), size))
579 if (!TEST_ptr(copy_pk = EVP_PKEY_new())
580 || !TEST_false(EVP_PKEY_copy_parameters(copy_pk, pk)))
583 ret = test_print_key_using_pem(alg, pk)
584 && test_print_key_using_serializer(alg, pk);
588 EVP_PKEY_free(copy_pk);
589 EVP_PKEY_CTX_free(ctx);
594 static int test_fromdata_ec(void)
597 EVP_PKEY_CTX *ctx = NULL;
598 EVP_PKEY *pk = NULL, *copy_pk = NULL;
600 BIGNUM *ec_priv_bn = NULL;
601 OSSL_PARAM *fromdata_params = NULL;
602 const char *alg = "EC";
603 static const unsigned char ec_pub_keydata[] = {
605 0x1b, 0x93, 0x67, 0x55, 0x1c, 0x55, 0x9f, 0x63,
606 0xd1, 0x22, 0xa4, 0xd8, 0xd1, 0x0a, 0x60, 0x6d,
607 0x02, 0xa5, 0x77, 0x57, 0xc8, 0xa3, 0x47, 0x73,
608 0x3a, 0x6a, 0x08, 0x28, 0x39, 0xbd, 0xc9, 0xd2,
609 0x80, 0xec, 0xe9, 0xa7, 0x08, 0x29, 0x71, 0x2f,
610 0xc9, 0x56, 0x82, 0xee, 0x9a, 0x85, 0x0f, 0x6d,
611 0x7f, 0x59, 0x5f, 0x8c, 0xd1, 0x96, 0x0b, 0xdf,
612 0x29, 0x3e, 0x49, 0x07, 0x88, 0x3f, 0x9a, 0x29
614 static const unsigned char ec_priv_keydata[] = {
615 0x33, 0xd0, 0x43, 0x83, 0xa9, 0x89, 0x56, 0x03,
616 0xd2, 0xd7, 0xfe, 0x6b, 0x01, 0x6f, 0xe4, 0x59,
617 0xcc, 0x0d, 0x9a, 0x24, 0x6c, 0x86, 0x1b, 0x2e,
618 0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
621 ossl_param_bld_init(&bld);
623 if (!TEST_ptr(ec_priv_bn = BN_bin2bn(ec_priv_keydata,
624 sizeof(ec_priv_keydata), NULL)))
627 if (ossl_param_bld_push_utf8_string(&bld, OSSL_PKEY_PARAM_EC_NAME,
628 "prime256v1", 0) <= 0)
630 if (ossl_param_bld_push_octet_string(&bld, OSSL_PKEY_PARAM_PUB_KEY,
632 sizeof(ec_pub_keydata)) <= 0)
634 if (ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PRIV_KEY, ec_priv_bn) <= 0)
636 if (!TEST_ptr(fromdata_params = ossl_param_bld_to_param(&bld)))
638 ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
642 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
643 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
644 || !TEST_int_eq(EVP_PKEY_bits(pk), 256)
645 || !TEST_int_eq(EVP_PKEY_security_bits(pk), 128)
646 || !TEST_int_eq(EVP_PKEY_size(pk), 2 + 35 * 2))
649 if (!TEST_ptr(copy_pk = EVP_PKEY_new())
650 || !TEST_true(EVP_PKEY_copy_parameters(copy_pk, pk)))
653 ret = test_print_key_using_pem(alg, pk)
654 && test_print_key_using_serializer(alg, pk);
657 ossl_param_bld_free(fromdata_params);
659 EVP_PKEY_free(copy_pk);
660 EVP_PKEY_CTX_free(ctx);
664 #endif /* OPENSSL_NO_EC */
666 int setup_tests(void)
668 if (!test_skip_common_options()) {
669 TEST_error("Error parsing test options\n");
673 if (!TEST_ptr(datadir = test_get_argument(0)))
676 ADD_TEST(test_fromdata_rsa);
677 #ifndef OPENSSL_NO_DH
678 ADD_TEST(test_fromdata_dh);
680 #ifndef OPENSSL_NO_EC
681 ADD_ALL_TESTS(test_fromdata_ecx, 4);
682 ADD_TEST(test_fromdata_ec);