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
396 static int test_fromdata_ecx(int tst)
399 EVP_PKEY_CTX *ctx = NULL;
401 const char *alg = (tst == X25519_IDX) ? "X25519" : "X448";
403 /* X448_KEYLEN > X25519_KEYLEN */
404 static unsigned char key_numbers[2][2][X448_KEYLEN] = {
405 /* X25519: Keys from RFC 7748 6.1 */
409 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
410 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
411 0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
416 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
417 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
418 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
422 /* X448: Keys from RFC 7748 6.2 */
426 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf,
427 0x46, 0xb0, 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba,
428 0xe8, 0xbc, 0x55, 0x65, 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9,
429 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 0x44, 0x89, 0x73, 0x91,
430 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 0x9a, 0xc2,
431 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b
435 0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22,
436 0xd5, 0xae, 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8,
437 0x3d, 0xe0, 0x9c, 0x63, 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5,
438 0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 0x41, 0xd9, 0x53, 0xd4,
439 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
440 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
444 OSSL_PARAM x25519_fromdata_params[] = {
445 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
446 key_numbers[X25519_IDX][PRIV_KEY],
448 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
449 key_numbers[X25519_IDX][PUB_KEY],
453 OSSL_PARAM x448_fromdata_params[] = {
454 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
455 key_numbers[X448_IDX][PRIV_KEY],
457 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
458 key_numbers[X448_IDX][PUB_KEY],
462 OSSL_PARAM *fromdata_params;
463 int bits, security_bits, size;
465 if (tst == X25519_IDX) {
466 fromdata_params = x25519_fromdata_params;
468 security_bits = X25519_SECURITY_BITS;
469 size = X25519_KEYLEN;
471 fromdata_params = x448_fromdata_params;
473 security_bits = X448_SECURITY_BITS;
477 ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
481 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
482 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
483 || !TEST_int_eq(EVP_PKEY_bits(pk), bits)
484 || !TEST_int_eq(EVP_PKEY_security_bits(pk), security_bits)
485 || !TEST_int_eq(EVP_PKEY_size(pk), size))
488 ret = test_print_key_using_pem(alg, pk)
489 && test_print_key_using_serializer(alg, pk);
493 EVP_PKEY_CTX_free(ctx);
498 static int test_fromdata_ec(void)
501 EVP_PKEY_CTX *ctx = NULL;
504 BIGNUM *ec_priv_bn = NULL;
505 OSSL_PARAM *fromdata_params = NULL;
506 const char *alg = "EC";
507 static const unsigned char ec_pub_keydata[] = {
509 0x1b, 0x93, 0x67, 0x55, 0x1c, 0x55, 0x9f, 0x63,
510 0xd1, 0x22, 0xa4, 0xd8, 0xd1, 0x0a, 0x60, 0x6d,
511 0x02, 0xa5, 0x77, 0x57, 0xc8, 0xa3, 0x47, 0x73,
512 0x3a, 0x6a, 0x08, 0x28, 0x39, 0xbd, 0xc9, 0xd2,
513 0x80, 0xec, 0xe9, 0xa7, 0x08, 0x29, 0x71, 0x2f,
514 0xc9, 0x56, 0x82, 0xee, 0x9a, 0x85, 0x0f, 0x6d,
515 0x7f, 0x59, 0x5f, 0x8c, 0xd1, 0x96, 0x0b, 0xdf,
516 0x29, 0x3e, 0x49, 0x07, 0x88, 0x3f, 0x9a, 0x29
518 static const unsigned char ec_priv_keydata[] = {
519 0x33, 0xd0, 0x43, 0x83, 0xa9, 0x89, 0x56, 0x03,
520 0xd2, 0xd7, 0xfe, 0x6b, 0x01, 0x6f, 0xe4, 0x59,
521 0xcc, 0x0d, 0x9a, 0x24, 0x6c, 0x86, 0x1b, 0x2e,
522 0xdc, 0x4b, 0x4d, 0x35, 0x43, 0xe1, 0x1b, 0xad
525 ossl_param_bld_init(&bld);
527 if (!TEST_ptr(ec_priv_bn = BN_bin2bn(ec_priv_keydata,
528 sizeof(ec_priv_keydata), NULL)))
531 if (ossl_param_bld_push_utf8_string(&bld, OSSL_PKEY_PARAM_EC_NAME,
532 "prime256v1", 0) <= 0)
534 if (ossl_param_bld_push_octet_string(&bld, OSSL_PKEY_PARAM_PUB_KEY,
536 sizeof(ec_pub_keydata)) <= 0)
538 if (ossl_param_bld_push_BN(&bld, OSSL_PKEY_PARAM_PRIV_KEY, ec_priv_bn) <= 0)
540 if (!TEST_ptr(fromdata_params = ossl_param_bld_to_param(&bld)))
542 ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
546 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
547 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
548 || !TEST_int_eq(EVP_PKEY_bits(pk), 256)
549 || !TEST_int_eq(EVP_PKEY_security_bits(pk), 128)
550 || !TEST_int_eq(EVP_PKEY_size(pk), 2 + 35 * 2))
553 ret = test_print_key_using_pem(alg, pk)
554 && test_print_key_using_serializer(alg, pk);
557 ossl_param_bld_free(fromdata_params);
559 EVP_PKEY_CTX_free(ctx);
563 #endif /* OPENSSL_NO_EC */
565 int setup_tests(void)
567 if (!test_skip_common_options()) {
568 TEST_error("Error parsing test options\n");
572 if (!TEST_ptr(datadir = test_get_argument(0)))
575 ADD_TEST(test_fromdata_rsa);
576 #ifndef OPENSSL_NO_DH
577 ADD_TEST(test_fromdata_dh);
579 #ifndef OPENSSL_NO_EC
580 ADD_ALL_TESTS(test_fromdata_ecx, 2);
581 ADD_TEST(test_fromdata_ec);