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;
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 ret = test_print_key_using_pem("RSA", pk)
314 && test_print_key_using_serializer("RSA", pk);
318 EVP_PKEY_CTX_free(key_ctx);
319 EVP_PKEY_CTX_free(ctx);
324 #ifndef OPENSSL_NO_DH
325 /* Array indexes used in test_fromdata_dh */
331 static int test_fromdata_dh(void)
334 EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
337 * 32-bit DH key, extracted from this command,
338 * executed with OpenSSL 1.0.2:
340 * openssl dhparam -out dhp.pem 32
341 * openssl genpkey -paramfile dhp.pem | openssl pkey -text
343 static unsigned long key_numbers[] = {
344 0x666c2b06, /* priv-key */
345 0x6fa6de50, /* pub-key */
349 OSSL_PARAM fromdata_params[] = {
350 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_PRIV_KEY, &key_numbers[PRIV_KEY]),
351 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_PUB_KEY, &key_numbers[PUB_KEY]),
352 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_FFC_P, &key_numbers[FFC_P]),
353 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_FFC_G, &key_numbers[FFC_G]),
357 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)))
360 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
361 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
362 || !TEST_int_eq(EVP_PKEY_bits(pk), 32)
363 || !TEST_int_eq(EVP_PKEY_security_bits(pk), 0) /* Missing Q */
364 || !TEST_int_eq(EVP_PKEY_size(pk), 4))
367 ret = test_print_key_using_pem("DH", pk)
368 && test_print_key_using_serializer("DH", pk);
370 if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
373 if (!TEST_false(EVP_PKEY_check(key_ctx))
374 || !TEST_true(EVP_PKEY_public_check(key_ctx))
375 || !TEST_false(EVP_PKEY_private_check(key_ctx)) /* Need a q */
376 || !TEST_true(EVP_PKEY_pairwise_check(key_ctx)))
381 EVP_PKEY_CTX_free(ctx);
382 EVP_PKEY_CTX_free(key_ctx);
388 #ifndef OPENSSL_NO_EC
389 /* Array indexes used in test_fromdata_ecx */
393 # define X25519_IDX 0
395 # define ED25519_IDX 2
398 static int test_fromdata_ecx(int tst)
401 EVP_PKEY_CTX *ctx = NULL;
403 const char *alg = NULL;
405 /* ED448_KEYLEN > X448_KEYLEN > X25519_KEYLEN == ED25519_KEYLEN */
406 static unsigned char key_numbers[4][2][ED448_KEYLEN] = {
407 /* X25519: Keys from RFC 7748 6.1 */
411 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
412 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
413 0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
418 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
419 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
420 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
424 /* X448: Keys from RFC 7748 6.2 */
428 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf,
429 0x46, 0xb0, 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba,
430 0xe8, 0xbc, 0x55, 0x65, 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9,
431 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 0x44, 0x89, 0x73, 0x91,
432 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 0x9a, 0xc2,
433 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b
437 0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22,
438 0xd5, 0xae, 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8,
439 0x3d, 0xe0, 0x9c, 0x63, 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5,
440 0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 0x41, 0xd9, 0x53, 0xd4,
441 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
442 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
445 /* ED25519: Keys from RFC 8032 */
449 0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84,
450 0x4a, 0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69,
451 0x7b, 0x32, 0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae,
456 0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b,
457 0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3,
458 0xda, 0xa6, 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07,
462 /* ED448: Keys from RFC 8032 */
466 0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, 0x10, 0xd6, 0x32,
467 0xbe, 0x89, 0xc8, 0x51, 0x3e, 0xbf, 0x6c, 0x92, 0x9f, 0x34,
468 0xdd, 0xfa, 0x8c, 0x9f, 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3,
469 0x48, 0xa3, 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, 0x4e,
470 0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, 0x8f, 0x03, 0x2e,
471 0x75, 0x49, 0xa2, 0x00, 0x98, 0xf9, 0x5b
475 0x5f, 0xd7, 0x44, 0x9b, 0x59, 0xb4, 0x61, 0xfd, 0x2c, 0xe7,
476 0x87, 0xec, 0x61, 0x6a, 0xd4, 0x6a, 0x1d, 0xa1, 0x34, 0x24,
477 0x85, 0xa7, 0x0e, 0x1f, 0x8a, 0x0e, 0xa7, 0x5d, 0x80, 0xe9,
478 0x67, 0x78, 0xed, 0xf1, 0x24, 0x76, 0x9b, 0x46, 0xc7, 0x06,
479 0x1b, 0xd6, 0x78, 0x3d, 0xf1, 0xe5, 0x0f, 0x6c, 0xd1, 0xfa,
480 0x1a, 0xbe, 0xaf, 0xe8, 0x25, 0x61, 0x80
484 OSSL_PARAM x25519_fromdata_params[] = {
485 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
486 key_numbers[X25519_IDX][PRIV_KEY],
488 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
489 key_numbers[X25519_IDX][PUB_KEY],
493 OSSL_PARAM x448_fromdata_params[] = {
494 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
495 key_numbers[X448_IDX][PRIV_KEY],
497 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
498 key_numbers[X448_IDX][PUB_KEY],
502 OSSL_PARAM ed25519_fromdata_params[] = {
503 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
504 key_numbers[ED25519_IDX][PRIV_KEY],
506 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
507 key_numbers[ED25519_IDX][PUB_KEY],
511 OSSL_PARAM ed448_fromdata_params[] = {
512 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
513 key_numbers[ED448_IDX][PRIV_KEY],
515 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
516 key_numbers[ED448_IDX][PUB_KEY],
520 OSSL_PARAM *fromdata_params = NULL;
521 int bits = 0, security_bits = 0, size = 0;
525 fromdata_params = x25519_fromdata_params;
527 security_bits = X25519_SECURITY_BITS;
528 size = X25519_KEYLEN;
533 fromdata_params = x448_fromdata_params;
535 security_bits = X448_SECURITY_BITS;
541 fromdata_params = ed25519_fromdata_params;
543 security_bits = ED25519_SECURITY_BITS;
544 size = ED25519_KEYLEN;
549 fromdata_params = ed448_fromdata_params;
551 security_bits = ED448_SECURITY_BITS;
557 ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
561 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
562 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
563 || !TEST_int_eq(EVP_PKEY_bits(pk), bits)
564 || !TEST_int_eq(EVP_PKEY_security_bits(pk), security_bits)
565 || !TEST_int_eq(EVP_PKEY_size(pk), size))
568 ret = test_print_key_using_pem(alg, pk)
569 && test_print_key_using_serializer(alg, pk);
573 EVP_PKEY_CTX_free(ctx);
578 static int test_fromdata_ec(void)
581 EVP_PKEY_CTX *ctx = NULL;
584 BIGNUM *ec_priv_bn = NULL;
585 OSSL_PARAM *fromdata_params = NULL;
586 const char *alg = "EC";
587 static const unsigned char ec_pub_keydata[] = {
589 0x1b, 0x93, 0x67, 0x55, 0x1c, 0x55, 0x9f, 0x63,
590 0xd1, 0x22, 0xa4, 0xd8, 0xd1, 0x0a, 0x60, 0x6d,
591 0x02, 0xa5, 0x77, 0x57, 0xc8, 0xa3, 0x47, 0x73,
592 0x3a, 0x6a, 0x08, 0x28, 0x39, 0xbd, 0xc9, 0xd2,
593 0x80, 0xec, 0xe9, 0xa7, 0x08, 0x29, 0x71, 0x2f,
594 0xc9, 0x56, 0x82, 0xee, 0x9a, 0x85, 0x0f, 0x6d,
595 0x7f, 0x59, 0x5f, 0x8c, 0xd1, 0x96, 0x0b, 0xdf,
596 0x29, 0x3e, 0x49, 0x07, 0x88, 0x3f, 0x9a, 0x29
598 static const unsigned char ec_priv_keydata[] = {
599 0x33, 0xd0, 0x43, 0x83, 0xa9, 0x89, 0x56, 0x03,
600 0xd2, 0xd7, 0xfe, 0x6b, 0x01, 0x6f, 0xe4, 0x59,
601 0xcc, 0x0d, 0x9a, 0x24, 0x6c, 0x86, 0x1b, 0x2e,
602 0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
605 ossl_param_bld_init(&bld);
607 if (!TEST_ptr(ec_priv_bn = BN_bin2bn(ec_priv_keydata,
608 sizeof(ec_priv_keydata), NULL)))
611 if (ossl_param_bld_push_utf8_string(&bld, OSSL_PKEY_PARAM_EC_NAME,
612 "prime256v1", 0) <= 0)
614 if (ossl_param_bld_push_octet_string(&bld, OSSL_PKEY_PARAM_PUB_KEY,
616 sizeof(ec_pub_keydata)) <= 0)
618 if (ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PRIV_KEY, ec_priv_bn) <= 0)
620 if (!TEST_ptr(fromdata_params = ossl_param_bld_to_param(&bld)))
622 ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
626 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
627 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
628 || !TEST_int_eq(EVP_PKEY_bits(pk), 256)
629 || !TEST_int_eq(EVP_PKEY_security_bits(pk), 128)
630 || !TEST_int_eq(EVP_PKEY_size(pk), 2 + 35 * 2))
633 ret = test_print_key_using_pem(alg, pk)
634 && test_print_key_using_serializer(alg, pk);
637 ossl_param_bld_free(fromdata_params);
639 EVP_PKEY_CTX_free(ctx);
643 #endif /* OPENSSL_NO_EC */
645 int setup_tests(void)
647 if (!test_skip_common_options()) {
648 TEST_error("Error parsing test options\n");
652 if (!TEST_ptr(datadir = test_get_argument(0)))
655 ADD_TEST(test_fromdata_rsa);
656 #ifndef OPENSSL_NO_DH
657 ADD_TEST(test_fromdata_dh);
659 #ifndef OPENSSL_NO_EC
660 ADD_ALL_TESTS(test_fromdata_ecx, 4);
661 ADD_TEST(test_fromdata_ec);