2 * Copyright 2019 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 "crypto/evp.h" /* For the internal API */
21 static char *datadir = NULL;
30 static void stripcr(char *buf, size_t *len)
35 for (i = *len, curr = buf, writ = buf; i > 0; i--, curr++) {
46 static int compare_with_file(const char *alg, int type, BIO *membio)
51 char *memdata, *fullfile = NULL;
84 TEST_error("Invalid file type");
88 BIO_snprintf(filename, sizeof(filename), "%s.%s", alg, suffix);
89 fullfile = test_mk_file_path(datadir, filename);
90 if (!TEST_ptr(fullfile))
93 file = BIO_new_file(fullfile, "rb");
97 if (!TEST_true(BIO_read_ex(file, buf, sizeof(buf), &readbytes))
98 || !TEST_true(BIO_eof(file))
99 || !TEST_size_t_lt(readbytes, sizeof(buf)))
102 len = BIO_get_mem_data(membio, &memdata);
103 if (!TEST_int_gt(len, 0))
107 if (type != PRIV_DER && type != PUB_DER) {
108 stripcr(memdata, &slen);
109 stripcr(buf, &readbytes);
112 if (!TEST_mem_eq(memdata, slen, buf, readbytes))
117 OPENSSL_free(fullfile);
118 (void)BIO_reset(membio);
123 static int test_print_key_using_pem(const char *alg, const EVP_PKEY *pk)
125 BIO *membio = BIO_new(BIO_s_mem());
128 if (!TEST_ptr(membio))
131 if (!TEST_true(EVP_PKEY_print_private(membio, pk, 0, NULL))
132 || !TEST_true(compare_with_file(alg, PRIV_TEXT, membio))
133 /* Public key in PEM form */
134 || !TEST_true(PEM_write_bio_PUBKEY(membio, pk))
135 || !TEST_true(compare_with_file(alg, PUB_PEM, membio))
136 /* Unencrypted private key in PEM form */
137 || !TEST_true(PEM_write_bio_PrivateKey(membio, pk,
138 NULL, NULL, 0, NULL, NULL))
139 || !TEST_true(compare_with_file(alg, PRIV_PEM, membio))
140 /* Encrypted private key in PEM form */
141 || !TEST_true(PEM_write_bio_PrivateKey(bio_out, pk, EVP_aes_256_cbc(),
142 (unsigned char *)"pass", 4,
152 static int test_print_key_type_using_serializer(const char *alg, int type,
156 OSSL_SERIALIZER_CTX *ctx = NULL;
157 BIO *membio = BIO_new(BIO_s_mem());
162 pq = OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ;
166 pq = OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ;
170 pq = OSSL_SERIALIZER_PrivateKey_TO_DER_PQ;
174 pq = OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ;
178 pq = OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ;
182 pq = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ;
186 TEST_error("Invalid serialization type");
190 if (!TEST_ptr(membio)) {
195 /* Make a context, it's valid for several prints */
196 TEST_note("Setting up a OSSL_SERIALIZER context with passphrase");
197 if (!TEST_ptr(ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pk, pq))
198 /* Check that this operation is supported */
199 || !TEST_ptr(OSSL_SERIALIZER_CTX_get_serializer(ctx)))
202 /* Use no cipher. This should give us an unencrypted PEM */
203 TEST_note("Testing with no encryption");
204 if (!TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
205 || !TEST_true(compare_with_file(alg, type, membio)))
208 if (type == PRIV_PEM) {
209 /* Set a passphrase to be used later */
210 if (!TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(ctx,
211 (unsigned char *)"pass",
215 /* Use a valid cipher name */
216 TEST_note("Displaying PEM encrypted with AES-256-CBC");
217 if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, "AES-256-CBC", NULL))
218 || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
221 /* Use an invalid cipher name, which should generate no output */
222 TEST_note("NOT Displaying PEM encrypted with (invalid) FOO");
223 if (!TEST_false(OSSL_SERIALIZER_CTX_set_cipher(ctx, "FOO", NULL))
224 || !TEST_false(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
227 /* Clear the cipher. This should give us an unencrypted PEM again */
228 TEST_note("Testing with encryption cleared (no encryption)");
229 if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, NULL, NULL))
230 || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
231 || !TEST_true(compare_with_file(alg, type, membio)))
237 OSSL_SERIALIZER_CTX_free(ctx);
241 static int test_print_key_using_serializer(const char *alg, const EVP_PKEY *pk)
246 for (i = 0; i < 6; i++)
247 ret = ret && test_print_key_type_using_serializer(alg, i, pk);
252 /* Array indexes used in test_fromdata_rsa */
262 static int test_fromdata_rsa(void)
265 EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL;
268 * 32-bit RSA key, extracted from this command,
269 * executed with OpenSSL 1.0.2:
271 * openssl genrsa 32 | openssl rsa -text
273 static unsigned long key_numbers[] = {
283 OSSL_PARAM fromdata_params[] = {
284 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_N, &key_numbers[N]),
285 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_E, &key_numbers[E]),
286 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_D, &key_numbers[D]),
287 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[P]),
288 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_FACTOR, &key_numbers[Q]),
289 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DP]),
290 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_EXPONENT, &key_numbers[DQ]),
291 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_RSA_COEFFICIENT, &key_numbers[QINV]),
295 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)))
298 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
299 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
300 || !TEST_int_eq(EVP_PKEY_bits(pk), 32)
301 || !TEST_int_eq(EVP_PKEY_security_bits(pk), 8)
302 || !TEST_int_eq(EVP_PKEY_size(pk), 4))
305 if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pk, "")))
308 if (!TEST_true(EVP_PKEY_check(key_ctx))
309 || !TEST_true(EVP_PKEY_public_check(key_ctx))
310 || !TEST_true(EVP_PKEY_private_check(key_ctx))
311 || !TEST_true(EVP_PKEY_pairwise_check(key_ctx)))
314 ret = test_print_key_using_pem("RSA", pk)
315 && test_print_key_using_serializer("RSA", pk);
319 EVP_PKEY_CTX_free(key_ctx);
320 EVP_PKEY_CTX_free(ctx);
325 #ifndef OPENSSL_NO_DH
326 /* Array indexes used in test_fromdata_dh */
332 static int test_fromdata_dh(void)
335 EVP_PKEY_CTX *ctx = NULL;
338 * 32-bit DH key, extracted from this command,
339 * executed with OpenSSL 1.0.2:
341 * openssl dhparam -out dhp.pem 32
342 * openssl genpkey -paramfile dhp.pem | openssl pkey -text
344 static unsigned long key_numbers[] = {
345 0x666c2b06, /* priv-key */
346 0x6fa6de50, /* pub-key */
350 OSSL_PARAM fromdata_params[] = {
351 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_PRIV_KEY, &key_numbers[PRIV_KEY]),
352 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_PUB_KEY, &key_numbers[PUB_KEY]),
353 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_FFC_P, &key_numbers[FFC_P]),
354 OSSL_PARAM_ulong(OSSL_PKEY_PARAM_FFC_G, &key_numbers[FFC_G]),
358 if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)))
361 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
362 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
363 || !TEST_int_eq(EVP_PKEY_bits(pk), 32)
364 || !TEST_int_eq(EVP_PKEY_security_bits(pk), 0) /* Missing Q */
365 || !TEST_int_eq(EVP_PKEY_size(pk), 4))
368 ret = test_print_key_using_pem("DH", pk)
369 && test_print_key_using_serializer("DH", pk);
373 EVP_PKEY_CTX_free(ctx);
379 #ifndef OPENSSL_NO_EC
380 /* Array indexes used in test_fromdata_ecx */
384 # define X25519_IDX 0
387 static int test_fromdata_ecx(int tst)
390 EVP_PKEY_CTX *ctx = NULL;
392 const char *alg = (tst == X25519_IDX) ? "X25519" : "X448";
394 /* X448_KEYLEN > X25519_KEYLEN */
395 static unsigned char key_numbers[2][2][X448_KEYLEN] = {
396 /* X25519: Keys from RFC 7748 6.1 */
400 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
401 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
402 0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
407 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
408 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
409 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
413 /* X448: Keys from RFC 7748 6.2 */
417 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf,
418 0x46, 0xb0, 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba,
419 0xe8, 0xbc, 0x55, 0x65, 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9,
420 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 0x44, 0x89, 0x73, 0x91,
421 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 0x9a, 0xc2,
422 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b
426 0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22,
427 0xd5, 0xae, 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8,
428 0x3d, 0xe0, 0x9c, 0x63, 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5,
429 0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 0x41, 0xd9, 0x53, 0xd4,
430 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
431 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
435 OSSL_PARAM x25519_fromdata_params[] = {
436 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
437 key_numbers[X25519_IDX][PRIV_KEY],
439 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
440 key_numbers[X25519_IDX][PUB_KEY],
444 OSSL_PARAM x448_fromdata_params[] = {
445 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
446 key_numbers[X448_IDX][PRIV_KEY],
448 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
449 key_numbers[X448_IDX][PUB_KEY],
453 OSSL_PARAM *fromdata_params;
454 int bits, security_bits, size;
456 if (tst == X25519_IDX) {
457 fromdata_params = x25519_fromdata_params;
459 security_bits = X25519_SECURITY_BITS;
460 size = X25519_KEYLEN;
462 fromdata_params = x448_fromdata_params;
464 security_bits = X448_SECURITY_BITS;
468 ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
472 if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
473 || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
474 || !TEST_int_eq(EVP_PKEY_bits(pk), bits)
475 || !TEST_int_eq(EVP_PKEY_security_bits(pk), security_bits)
476 || !TEST_int_eq(EVP_PKEY_size(pk), size))
479 ret = test_print_key_using_pem(alg, pk)
480 && test_print_key_using_serializer(alg, pk);
484 EVP_PKEY_CTX_free(ctx);
491 int setup_tests(void)
493 if (!test_skip_common_options()) {
494 TEST_error("Error parsing test options\n");
498 if (!TEST_ptr(datadir = test_get_argument(0)))
501 ADD_TEST(test_fromdata_rsa);
502 #ifndef OPENSSL_NO_DH
503 ADD_TEST(test_fromdata_dh);
505 #ifndef OPENSSL_NO_EC
506 ADD_ALL_TESTS(test_fromdata_ecx, 2);