summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-10-17 08:59:48 +0200
committerRichard Levitte <levitte@openssl.org>2020-11-15 19:37:26 +0100
commite76a696273e472803b156af90fa869bb9aeb798c (patch)
tree73b23a5133b6fc14516ba6a69afed5f6a5617e44 /test
parentefb4667f72356046a492d8875bd3b02b6fe352e8 (diff)
test/endecoder_legacy_test.c: new test for legacy comparison
It checks that all of these functions have a corresponding OSSL_ENCODER implementation, and that the output is the same: - i2d_{TYPE}PrivateKey - i2d_{TYPE}PublicKey - i2d_{TYPE}params - i2d_{TYPE}_PUBKEY - PEM_write_bio_{TYPE}PrivateKey - PEM_write_bio_{TYPE}PublicKey - PEM_write_bio_{TYPE}Parameters - PEM_write_bio_{TYPE}_PUBKEY It also checks that all of these functions have a corresponding OSSL_DECODER implementation, and that the decoding result matches: - d2i_{TYPE}PrivateKey() - d2i_{TYPE}PublicKey(), - d2i_{TYPE}params(), - d2i_{TYPE}_PUBKEY(), - PEM_read_bio_{TYPE}PrivateKey() - PEM_read_bio_{TYPE}PublicKey() - PEM_read_bio_{TYPE}params() - PEM_read_bio_{TYPE}_PUBKEY() Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/13262)
Diffstat (limited to 'test')
-rw-r--r--test/build.info5
-rw-r--r--test/endecoder_legacy_test.c696
-rw-r--r--test/recipes/04-test_encoder_decoder_legacy.t23
3 files changed, 724 insertions, 0 deletions
diff --git a/test/build.info b/test/build.info
index 51100d1418..b7fafb7eba 100644
--- a/test/build.info
+++ b/test/build.info
@@ -793,6 +793,11 @@ IF[{- !$disabled{tests} -}]
INCLUDE[endecode_test]=.. ../include ../apps/include
DEPEND[endecode_test]=../libcrypto.a libtestutil.a
+ PROGRAMS{noinst}=endecoder_legacy_test
+ SOURCE[endecoder_legacy_test]=endecoder_legacy_test.c
+ INCLUDE[endecoder_legacy_test]=.. ../include ../apps/include
+ DEPEND[endecoder_legacy_test]=../libcrypto.a libtestutil.a
+
PROGRAMS{noinst}=namemap_internal_test
SOURCE[namemap_internal_test]=namemap_internal_test.c
INCLUDE[namemap_internal_test]=.. ../include ../apps/include
diff --git a/test/endecoder_legacy_test.c b/test/endecoder_legacy_test.c
new file mode 100644
index 0000000000..1bdbda79fa
--- /dev/null
+++ b/test/endecoder_legacy_test.c
@@ -0,0 +1,696 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This program tests the following known key type specific function against
+ * the corresponding OSSL_ENCODER implementation:
+ *
+ * - i2d_{TYPE}PrivateKey()
+ * - i2d_{TYPE}PublicKey(),
+ * - i2d_{TYPE}params(),
+ * - i2d_{TYPE}_PUBKEY(),
+ * - PEM_write_bio_{TYPE}PrivateKey()
+ * - PEM_write_bio_{TYPE}PublicKey()
+ * - PEM_write_bio_{TYPE}params()
+ * - PEM_write_bio_{TYPE}_PUBKEY()
+ *
+ * as well as the following functions against the corresponding OSSL_DECODER
+ * implementation.
+ *
+ * - d2i_{TYPE}PrivateKey()
+ * - d2i_{TYPE}PublicKey(),
+ * - d2i_{TYPE}params(),
+ * - d2i_{TYPE}_PUBKEY(),
+ * - PEM_read_bio_{TYPE}PrivateKey()
+ * - PEM_read_bio_{TYPE}PublicKey()
+ * - PEM_read_bio_{TYPE}params()
+ * - PEM_read_bio_{TYPE}_PUBKEY()
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/asn1.h>
+#include <openssl/pem.h>
+#include <openssl/params.h>
+#include <openssl/encoder.h>
+#include <openssl/decoder.h>
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+# include <openssl/rsa.h>
+#endif
+#include "internal/nelem.h"
+#include "crypto/evp.h"
+
+#include "testutil.h"
+
+typedef int PEM_write_bio_of_void_protected(BIO *out, void *obj,
+ const EVP_CIPHER *enc,
+ unsigned char *kstr, int klen,
+ pem_password_cb *cb, void *u);
+typedef int PEM_write_bio_of_void_unprotected(BIO *out, void *obj);
+typedef void *PEM_read_bio_of_void(BIO *out, void **obj,
+ pem_password_cb *cb, void *u);
+typedef int EVP_PKEY_print_fn(BIO *out, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx);
+typedef int EVP_PKEY_eq_fn(const EVP_PKEY *a, const EVP_PKEY *b);
+
+static struct test_stanza_st {
+ const char *keytype;
+ const char *structure[2];
+ int evp_type;
+
+ i2d_of_void *i2d_PrivateKey;
+ i2d_of_void *i2d_PublicKey;
+ i2d_of_void *i2d_params;
+ i2d_of_void *i2d_PUBKEY;
+ PEM_write_bio_of_void_protected *pem_write_bio_PrivateKey;
+ PEM_write_bio_of_void_unprotected *pem_write_bio_PublicKey;
+ PEM_write_bio_of_void_unprotected *pem_write_bio_params;
+ PEM_write_bio_of_void_unprotected *pem_write_bio_PUBKEY;
+
+ d2i_of_void *d2i_PrivateKey;
+ d2i_of_void *d2i_PublicKey;
+ d2i_of_void *d2i_params;
+ d2i_of_void *d2i_PUBKEY;
+ PEM_read_bio_of_void *pem_read_bio_PrivateKey;
+ PEM_read_bio_of_void *pem_read_bio_PublicKey;
+ PEM_read_bio_of_void *pem_read_bio_params;
+ PEM_read_bio_of_void *pem_read_bio_PUBKEY;
+} test_stanzas[] = {
+#ifndef OPENSSL_NO_DH
+ { "DH", { "DH", "type-specific" }, EVP_PKEY_DH,
+ NULL, /* No i2d_DHPrivateKey */
+ NULL, /* No i2d_DHPublicKey */
+ (i2d_of_void *)i2d_DHparams,
+ NULL, /* No i2d_DH_PUBKEY */
+ NULL, /* No PEM_write_bio_DHPrivateKey */
+ NULL, /* No PEM_write_bio_DHPublicKey */
+ (PEM_write_bio_of_void_unprotected *)PEM_write_bio_DHparams,
+ NULL, /* No PEM_write_bio_DH_PUBKEY */
+ NULL, /* No d2i_DHPrivateKey */
+ NULL, /* No d2i_DHPublicKey */
+ (d2i_of_void *)d2i_DHparams,
+ NULL, /* No d2i_DH_PUBKEY */
+ NULL, /* No PEM_read_bio_DHPrivateKey */
+ NULL, /* No PEM_read_bio_DHPublicKey */
+ (PEM_read_bio_of_void *)PEM_read_bio_DHparams,
+ NULL }, /* No PEM_read_bio_DH_PUBKEY */
+ { "DHX", { "DHX", "type-specific" }, EVP_PKEY_DHX,
+ NULL, /* No i2d_DHxPrivateKey */
+ NULL, /* No i2d_DHxPublicKey */
+ (i2d_of_void *)i2d_DHxparams,
+ NULL, /* No i2d_DHx_PUBKEY */
+ NULL, /* No PEM_write_bio_DHxPrivateKey */
+ NULL, /* No PEM_write_bio_DHxPublicKey */
+ (PEM_write_bio_of_void_unprotected *)PEM_write_bio_DHxparams,
+ NULL, /* No PEM_write_bio_DHx_PUBKEY */
+ NULL, /* No d2i_DHxPrivateKey */
+ NULL, /* No d2i_DHxPublicKey */
+ (d2i_of_void *)d2i_DHxparams,
+ NULL, /* No d2i_DHx_PUBKEY */
+ NULL, /* No PEM_read_bio_DHxPrivateKey */
+ NULL, /* No PEM_read_bio_DHxPublicKey */
+ NULL, /* No PEM_read_bio_DHxparams */
+ NULL }, /* No PEM_read_bio_DHx_PUBKEY */
+#endif
+#ifndef OPENSSL_NO_DSA
+ { "DSA", { "DSA", "type-specific" }, EVP_PKEY_DSA,
+ (i2d_of_void *)i2d_DSAPrivateKey,
+ (i2d_of_void *)i2d_DSAPublicKey,
+ (i2d_of_void *)i2d_DSAparams,
+ (i2d_of_void *)i2d_DSA_PUBKEY,
+ (PEM_write_bio_of_void_protected *)PEM_write_bio_DSAPrivateKey,
+ NULL, /* No PEM_write_bio_DSAPublicKey */
+ (PEM_write_bio_of_void_unprotected *)PEM_write_bio_DSAparams,
+ (PEM_write_bio_of_void_unprotected *)PEM_write_bio_DSA_PUBKEY,
+ (d2i_of_void *)d2i_DSAPrivateKey,
+ (d2i_of_void *)d2i_DSAPublicKey,
+ (d2i_of_void *)d2i_DSAparams,
+ (d2i_of_void *)d2i_DSA_PUBKEY,
+ (PEM_read_bio_of_void *)PEM_read_bio_DSAPrivateKey,
+ NULL, /* No PEM_write_bio_DSAPublicKey */
+ (PEM_read_bio_of_void *)PEM_read_bio_DSAparams,
+ (PEM_read_bio_of_void *)PEM_read_bio_DSA_PUBKEY },
+#endif
+#ifndef OPENSSL_NO_EC
+ { "EC", { "EC", "type-specific" }, EVP_PKEY_EC,
+ (i2d_of_void *)i2d_ECPrivateKey,
+ NULL, /* No i2d_ECPublicKey */
+ (i2d_of_void *)i2d_ECParameters,
+ (i2d_of_void *)i2d_EC_PUBKEY,
+ (PEM_write_bio_of_void_protected *)PEM_write_bio_ECPrivateKey,
+ NULL, /* No PEM_write_bio_ECPublicKey */
+ NULL, /* No PEM_write_bio_ECParameters */
+ (PEM_write_bio_of_void_unprotected *)PEM_write_bio_EC_PUBKEY,
+ (d2i_of_void *)d2i_ECPrivateKey,
+ NULL, /* No d2i_ECPublicKey */
+ (d2i_of_void *)d2i_ECParameters,
+ (d2i_of_void *)d2i_EC_PUBKEY,
+ (PEM_read_bio_of_void *)PEM_read_bio_ECPrivateKey,
+ NULL, /* No PEM_read_bio_ECPublicKey */
+ NULL, /* No PEM_read_bio_ECParameters */
+ (PEM_read_bio_of_void *)PEM_read_bio_EC_PUBKEY, },
+#endif
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ { "RSA", { "RSA", "type-specific" }, EVP_PKEY_RSA,
+ (i2d_of_void *)i2d_RSAPrivateKey,
+ (i2d_of_void *)i2d_RSAPublicKey,
+ NULL, /* No i2d_RSAparams */
+ (i2d_of_void *)i2d_RSA_PUBKEY,
+ (PEM_write_bio_of_void_protected *)PEM_write_bio_RSAPrivateKey,
+ (PEM_write_bio_of_void_unprotected *)PEM_write_bio_RSAPublicKey,
+ NULL, /* No PEM_write_bio_RSAparams */
+ (PEM_write_bio_of_void_unprotected *)PEM_write_bio_RSA_PUBKEY,
+ (d2i_of_void *)d2i_RSAPrivateKey,
+ (d2i_of_void *)d2i_RSAPublicKey,
+ NULL, /* No d2i_RSAparams */
+ (d2i_of_void *)d2i_RSA_PUBKEY,
+ (PEM_read_bio_of_void *)PEM_read_bio_RSAPrivateKey,
+ (PEM_read_bio_of_void *)PEM_read_bio_RSAPublicKey,
+ NULL, /* No PEM_read_bio_RSAparams */
+ (PEM_read_bio_of_void *)PEM_read_bio_RSA_PUBKEY }
+#endif
+};
+
+/*
+ * Keys that we're going to test with. We initialize this with the intended
+ * key types, and generate the keys themselves on program setup.
+ * They must all be downgradable with EVP_PKEY_get0()
+ */
+
+#ifndef OPENSSL_NO_DH
+static const OSSL_PARAM DH_params[] = { OSSL_PARAM_END };
+static const OSSL_PARAM DHX_params[] = { OSSL_PARAM_END };
+#endif
+#ifndef OPENSSL_NO_DSA
+static size_t qbits = 160; /* PVK only tolerates 160 Q bits */
+static size_t pbits = 1024; /* With 160 Q bits, we MUST use 1024 P bits */
+static const OSSL_PARAM DSA_params[] = {
+ OSSL_PARAM_size_t("pbits", &pbits),
+ OSSL_PARAM_size_t("qbits", &qbits),
+ OSSL_PARAM_END
+};
+#endif
+#ifndef OPENSSL_NO_EC
+static char groupname[] = "prime256v1";
+static const OSSL_PARAM EC_params[] = {
+ OSSL_PARAM_utf8_string("group", groupname, sizeof(groupname) - 1),
+ OSSL_PARAM_END
+};
+#endif
+
+static struct key_st {
+ const char *keytype;
+ int evp_type;
+ /* non-NULL if a template EVP_PKEY must be generated first */
+ const OSSL_PARAM *template_params;
+
+ EVP_PKEY *key;
+} keys[] = {
+#ifndef OPENSSL_NO_DH
+ { "DH", EVP_PKEY_DH, DH_params, NULL },
+ { "DHX", EVP_PKEY_DHX, DHX_params, NULL },
+#endif
+#ifndef OPENSSL_NO_DSA
+ { "DSA", EVP_PKEY_DSA, DSA_params, NULL },
+#endif
+#ifndef OPENSSL_NO_EC
+ { "EC", EVP_PKEY_EC, EC_params, NULL },
+#endif
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ { "RSA", EVP_PKEY_RSA, NULL, NULL },
+#endif
+};
+
+static EVP_PKEY *make_key(const char *type,
+ const OSSL_PARAM *gen_template_params)
+{
+ EVP_PKEY *template = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ OSSL_PARAM *gen_template_params_noconst =
+ (OSSL_PARAM *)gen_template_params;
+
+ if (gen_template_params != NULL
+ && ((ctx = EVP_PKEY_CTX_new_from_name(NULL, type, NULL)) == NULL
+ || EVP_PKEY_paramgen_init(ctx) <= 0
+ || (gen_template_params[0].key != NULL
+ && EVP_PKEY_CTX_set_params(ctx, gen_template_params_noconst) <= 0)
+ || EVP_PKEY_gen(ctx, &template) <= 0))
+ goto end;
+ EVP_PKEY_CTX_free(ctx);
+
+ /*
+ * No real need to check the errors other than for the cascade
+ * effect. |pkey| will simply remain NULL if something goes wrong.
+ */
+ ctx =
+ template != NULL
+ ? EVP_PKEY_CTX_new(template, NULL)
+ : EVP_PKEY_CTX_new_from_name(NULL, type, NULL);
+
+ (void)(ctx != NULL
+ && EVP_PKEY_keygen_init(ctx) > 0
+ && EVP_PKEY_keygen(ctx, &pkey) > 0);
+
+ end:
+ EVP_PKEY_free(template);
+ EVP_PKEY_CTX_free(ctx);
+ return pkey;
+}
+
+static struct key_st *lookup_key(const char *type)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(keys); i++) {
+ if (strcmp(keys[i].keytype, type) == 0)
+ return &keys[i];
+ }
+ return NULL;
+}
+
+static int test_membio_str_eq(BIO *bio_provided, BIO *bio_legacy)
+{
+ char *str_provided = NULL, *str_legacy = NULL;
+ long len_provided = BIO_get_mem_data(bio_provided, &str_provided);
+ long len_legacy = BIO_get_mem_data(bio_legacy, &str_legacy);
+
+ return TEST_strn2_eq(str_provided, len_provided,
+ str_legacy, len_legacy);
+}
+
+static int test_protected_PEM(const char *keytype, int evp_type,
+ void *legacy_key,
+ PEM_write_bio_of_void_protected *pem_write_bio,
+ PEM_read_bio_of_void *pem_read_bio,
+ EVP_PKEY_eq_fn *evp_pkey_eq,
+ EVP_PKEY_print_fn *evp_pkey_print,
+ EVP_PKEY *provided_pkey, int selection,
+ const char *structure)
+{
+ int ok = 0;
+ BIO *membio_legacy = NULL;
+ BIO *membio_provided = NULL;
+ OSSL_ENCODER_CTX *ectx = NULL;
+ OSSL_DECODER_CTX *dctx = NULL;
+ void *decoded_legacy_key = NULL;
+ EVP_PKEY *decoded_legacy_pkey = NULL;
+ EVP_PKEY *decoded_provided_pkey = NULL;
+
+ /* Set up the BIOs, so we have them */
+ if (!TEST_ptr(membio_legacy = BIO_new(BIO_s_mem()))
+ || !TEST_ptr(membio_provided = BIO_new(BIO_s_mem())))
+ goto end;
+
+ if (!TEST_ptr(ectx =
+ OSSL_ENCODER_CTX_new_by_EVP_PKEY(provided_pkey, selection,
+ "PEM", structure,
+ NULL, NULL))
+ || !TEST_true(OSSL_ENCODER_to_bio(ectx, membio_provided))
+ || !TEST_true(pem_write_bio(membio_legacy, legacy_key,
+ NULL, NULL, 0, NULL, NULL))
+ || !test_membio_str_eq(membio_provided, membio_legacy))
+ goto end;
+
+ if (pem_read_bio != NULL) {
+ /* Now try decoding the results and compare the resulting keys */
+
+ if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new())
+ || !TEST_ptr(dctx =
+ OSSL_DECODER_CTX_new_by_EVP_PKEY(&decoded_provided_pkey,
+ "PEM", structure,
+ keytype, selection,
+ NULL, NULL))
+ || !TEST_true(OSSL_DECODER_from_bio(dctx, membio_provided))
+ || !TEST_ptr(decoded_legacy_key =
+ pem_read_bio(membio_legacy, NULL, NULL, NULL))
+ || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type,
+ decoded_legacy_key)))
+ goto end;
+
+ if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey,
+ decoded_legacy_pkey), 0)) {
+ TEST_info("decoded_provided_pkey:");
+ evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL);
+ TEST_info("decoded_legacy_pkey:");
+ evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL);
+ }
+ }
+ ok = 1;
+ end:
+ EVP_PKEY_free(decoded_legacy_pkey);
+ EVP_PKEY_free(decoded_provided_pkey);
+ OSSL_ENCODER_CTX_free(ectx);
+ OSSL_DECODER_CTX_free(dctx);
+ BIO_free(membio_provided);
+ BIO_free(membio_legacy);
+ return ok;
+}
+
+static int test_unprotected_PEM(const char *keytype, int evp_type,
+ void *legacy_key,
+ PEM_write_bio_of_void_unprotected *pem_write_bio,
+ PEM_read_bio_of_void *pem_read_bio,
+ EVP_PKEY_eq_fn *evp_pkey_eq,
+ EVP_PKEY_print_fn *evp_pkey_print,
+ EVP_PKEY *provided_pkey, int selection,
+ const char *structure)
+{
+ int ok = 0;
+ BIO *membio_legacy = NULL;
+ BIO *membio_provided = NULL;
+ OSSL_ENCODER_CTX *ectx = NULL;
+ OSSL_DECODER_CTX *dctx = NULL;
+ void *decoded_legacy_key = NULL;
+ EVP_PKEY *decoded_legacy_pkey = NULL;
+ EVP_PKEY *decoded_provided_pkey = NULL;
+
+ /* Set up the BIOs, so we have them */
+ if (!TEST_ptr(membio_legacy = BIO_new(BIO_s_mem()))
+ || !TEST_ptr(membio_provided = BIO_new(BIO_s_mem())))
+ goto end;
+
+ if (!TEST_ptr(ectx =
+ OSSL_ENCODER_CTX_new_by_EVP_PKEY(provided_pkey, selection,
+ "PEM", structure,
+ NULL, NULL))
+ || !TEST_true(OSSL_ENCODER_to_bio(ectx, membio_provided))
+ || !TEST_true(pem_write_bio(membio_legacy, legacy_key))
+ || !test_membio_str_eq(membio_provided, membio_legacy))
+ goto end;
+
+ if (pem_read_bio != NULL) {
+ /* Now try decoding the results and compare the resulting keys */
+
+ if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new())
+ || !TEST_ptr(dctx =
+ OSSL_DECODER_CTX_new_by_EVP_PKEY(&decoded_provided_pkey,
+ "PEM", structure,
+ keytype, selection,
+ NULL, NULL))
+ || !TEST_true(OSSL_DECODER_from_bio(dctx, membio_provided))
+ || !TEST_ptr(decoded_legacy_key =
+ pem_read_bio(membio_legacy, NULL, NULL, NULL))
+ || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type,
+ decoded_legacy_key)))
+ goto end;
+
+ if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey,
+ decoded_legacy_pkey), 0)) {
+ TEST_info("decoded_provided_pkey:");
+ evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL);
+ TEST_info("decoded_legacy_pkey:");
+ evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL);
+ }
+ }
+ ok = 1;
+ end:
+ EVP_PKEY_free(decoded_legacy_pkey);
+ EVP_PKEY_free(decoded_provided_pkey);
+ OSSL_ENCODER_CTX_free(ectx);
+ OSSL_DECODER_CTX_free(dctx);
+ BIO_free(membio_provided);
+ BIO_free(membio_legacy);
+ return ok;
+}
+
+static int test_DER(const char *keytype, int evp_type,
+ void *legacy_key, i2d_of_void *i2d, d2i_of_void *d2i,
+ EVP_PKEY_eq_fn *evp_pkey_eq,
+ EVP_PKEY_print_fn *evp_pkey_print,
+ EVP_PKEY *provided_pkey, int selection,
+ const char *structure)
+{
+ int ok = 0;
+ unsigned char *der_legacy = NULL;
+ const unsigned char *pder_legacy = NULL;
+ size_t der_legacy_len = 0;
+ unsigned char *der_provided = NULL;
+ const unsigned char *pder_provided = NULL;
+ size_t der_provided_len = 0;
+ size_t tmp_size;
+ OSSL_ENCODER_CTX *ectx = NULL;
+ OSSL_DECODER_CTX *dctx = NULL;
+ void *decoded_legacy_key = NULL;
+ EVP_PKEY *decoded_legacy_pkey = NULL;
+ EVP_PKEY *decoded_provided_pkey = NULL;
+
+ if (!TEST_ptr(ectx =
+ OSSL_ENCODER_CTX_new_by_EVP_PKEY(provided_pkey, selection,
+ "DER", structure,
+ NULL, NULL))
+ || !TEST_true(OSSL_ENCODER_to_data(ectx,
+ &der_provided, &der_provided_len))
+ || !TEST_size_t_gt(der_legacy_len = i2d(legacy_key, &der_legacy), 0)
+ || !TEST_mem_eq(der_provided, der_provided_len,
+ der_legacy, der_legacy_len))
+ goto end;
+
+ if (d2i != NULL) {
+ /* Now try decoding the results and compare the resulting keys */
+
+ if (!TEST_ptr(decoded_legacy_pkey = EVP_PKEY_new())
+ || !TEST_ptr(dctx =
+ OSSL_DECODER_CTX_new_by_EVP_PKEY(&decoded_provided_pkey,
+ "DER", structure,
+ keytype, selection,
+ NULL, NULL))
+ || !TEST_true((pder_provided = der_provided,
+ tmp_size = der_provided_len,
+ OSSL_DECODER_from_data(dctx, &pder_provided,
+ &tmp_size)))
+ || !TEST_ptr((pder_legacy = der_legacy,
+ decoded_legacy_key = d2i(NULL, &pder_legacy,
+ (long)der_legacy_len)))
+ || !TEST_true(EVP_PKEY_assign(decoded_legacy_pkey, evp_type,
+ decoded_legacy_key)))
+ goto end;
+
+ if (!TEST_int_gt(evp_pkey_eq(decoded_provided_pkey,
+ decoded_legacy_pkey), 0)) {
+ TEST_info("decoded_provided_pkey:");
+ evp_pkey_print(bio_out, decoded_provided_pkey, 0, NULL);
+ TEST_info("decoded_legacy_pkey:");
+ evp_pkey_print(bio_out, decoded_legacy_pkey, 0, NULL);
+ }
+ }
+ ok = 1;
+ end:
+ EVP_PKEY_free(decoded_legacy_pkey);
+ EVP_PKEY_free(decoded_provided_pkey);
+ OSSL_ENCODER_CTX_free(ectx);
+ OSSL_DECODER_CTX_free(dctx);
+ OPENSSL_free(der_provided);
+ OPENSSL_free(der_legacy);
+ return ok;
+}
+
+static int test_key(int idx)
+{
+ struct test_stanza_st *test_stanza = NULL;
+ struct key_st *key = NULL;
+ int ok = 0;
+ size_t i;
+ EVP_PKEY *pkey = NULL, *downgraded_pkey = NULL;
+ void *legacy_obj = NULL;
+
+ /* Get the test data */
+ if (!TEST_ptr(test_stanza = &test_stanzas[idx])
+ || !TEST_ptr(key = lookup_key(test_stanza->keytype)))
+ goto end;
+
+ /* Set up the keys */
+ if (!TEST_ptr(pkey = key->key)
+ || !TEST_true(evp_pkey_copy_downgraded(&downgraded_pkey, pkey))
+ || !TEST_ptr(downgraded_pkey)
+ || !TEST_int_eq(EVP_PKEY_id(downgraded_pkey), key->evp_type)
+ || !TEST_ptr(legacy_obj = EVP_PKEY_get0(downgraded_pkey)))
+ goto end;
+
+ ok = 1;
+
+ /* Test PrivateKey to PEM */
+ if (test_stanza->pem_write_bio_PrivateKey != NULL) {
+ int selection = OSSL_KEYMGMT_SELECT_ALL;
+
+ for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) {
+ const char *structure = test_stanza->structure[i];
+
+ TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}PrivateKey for %s, %s",
+ test_stanza->keytype, structure);
+ if (!test_protected_PEM(key->keytype, key->evp_type, legacy_obj,
+ test_stanza->pem_write_bio_PrivateKey,
+ test_stanza->pem_read_bio_PrivateKey,
+ EVP_PKEY_eq, EVP_PKEY_print_private,
+ pkey, selection, structure))
+ ok = 0;
+ }
+ }
+
+ /* Test PublicKey to PEM */
+ if (test_stanza->pem_write_bio_PublicKey != NULL) {
+ int selection =
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+
+ for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) {
+ const char *structure = test_stanza->structure[i];
+
+ TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}PublicKey for %s, %s",
+ test_stanza->keytype, structure);
+ if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj,
+ test_stanza->pem_write_bio_PublicKey,
+ test_stanza->pem_read_bio_PublicKey,
+ EVP_PKEY_eq, EVP_PKEY_print_public,
+ pkey, selection, structure))
+ ok = 0;
+ }
+ }
+
+ /* Test params to PEM */
+ if (test_stanza->pem_write_bio_params != NULL) {
+ int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+
+ for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) {
+ const char *structure = test_stanza->structure[i];
+
+ TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}params for %s, %s",
+ test_stanza->keytype, structure);
+ if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj,
+ test_stanza->pem_write_bio_params,
+ test_stanza->pem_read_bio_params,
+ EVP_PKEY_parameters_eq,
+ EVP_PKEY_print_params,
+ pkey, selection, structure))
+ ok = 0;
+ }
+ }
+
+ /* Test PUBKEY to PEM */
+ if (test_stanza->pem_write_bio_PUBKEY != NULL) {
+ int selection =
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+ const char *structure = "SubjectPublicKeyInfo";
+
+ TEST_info("Test OSSL_ENCODER against PEM_write_bio_{TYPE}_PUBKEY for %s, %s",
+ test_stanza->keytype, structure);
+ if (!test_unprotected_PEM(key->keytype, key->evp_type, legacy_obj,
+ test_stanza->pem_write_bio_PUBKEY,
+ test_stanza->pem_read_bio_PUBKEY,
+ EVP_PKEY_eq, EVP_PKEY_print_public,
+ pkey, selection, structure))
+ ok = 0;
+ }
+
+
+ /* Test PrivateKey to DER */
+ if (test_stanza->i2d_PrivateKey != NULL) {
+ int selection = OSSL_KEYMGMT_SELECT_ALL;
+
+ for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) {
+ const char *structure = test_stanza->structure[i];
+
+ TEST_info("Test OSSL_ENCODER against i2d_{TYPE}PrivateKey for %s, %s",
+ test_stanza->keytype, structure);
+ if (!test_DER(key->keytype, key->evp_type, legacy_obj,
+ test_stanza->i2d_PrivateKey,
+ test_stanza->d2i_PrivateKey,
+ EVP_PKEY_eq, EVP_PKEY_print_private,
+ pkey, selection, structure))
+ ok = 0;
+ }
+ }
+
+ /* Test PublicKey to DER */
+ if (test_stanza->i2d_PublicKey != NULL) {
+ int selection =
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+
+ for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) {
+ const char *structure = test_stanza->structure[i];
+
+ TEST_info("Test OSSL_ENCODER against i2d_{TYPE}PublicKey for %s, %s",
+ test_stanza->keytype, structure);
+ if (!test_DER(key->keytype, key->evp_type, legacy_obj,
+ test_stanza->i2d_PublicKey,
+ test_stanza->d2i_PublicKey,
+ EVP_PKEY_eq, EVP_PKEY_print_public,
+ pkey, selection, structure))
+ ok = 0;
+ }
+ }
+
+ /* Test params to DER */
+ if (test_stanza->i2d_params != NULL) {
+ int selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+
+ for (i = 0; i < OSSL_NELEM(test_stanza->structure); i++) {
+ const char *structure = test_stanza->structure[i];
+
+ TEST_info("Test OSSL_ENCODER against i2d_{TYPE}params for %s, %s",
+ test_stanza->keytype, structure);
+ if (!test_DER(key->keytype, key->evp_type, legacy_obj,
+ test_stanza->i2d_params, test_stanza->d2i_params,
+ EVP_PKEY_parameters_eq, EVP_PKEY_print_params,
+ pkey, selection, structure))
+ ok = 0;
+ }
+ }
+
+ /* Test PUBKEY to DER */
+ if (test_stanza->i2d_PUBKEY != NULL) {
+ int selection =
+ OSSL_KEYMGMT_SELECT_PUBLIC_KEY
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
+ const char *structure = "SubjectPublicKeyInfo";
+
+ TEST_info("Test OSSL_ENCODER against i2d_{TYPE}_PUBKEY for %s, %s",
+ test_stanza->keytype, structure);
+ if (!test_DER(key->keytype, key->evp_type, legacy_obj,
+ test_stanza->i2d_PUBKEY, test_stanza->d2i_PUBKEY,
+ EVP_PKEY_eq, EVP_PKEY_print_public,
+ pkey, selection, structure))
+ ok = 0;
+ }
+ end:
+ EVP_PKEY_free(downgraded_pkey);
+ return ok;
+}
+
+int setup_tests(void)
+{
+ size_t i;
+
+ TEST_info("Generating keys...");
+
+ for (i = 0; i < OSSL_NELEM(keys); i++) {
+ if (!TEST_ptr(keys[i].key =
+ make_key(keys[i].keytype, keys[i].template_params)))
+ return 0;
+ }
+
+ TEST_info("Generating key... done");
+
+ ADD_ALL_TESTS(test_key, OSSL_NELEM(test_stanzas));
+ return 1;
+}
+
+void cleanup_tests(void)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(keys); i++)
+ EVP_PKEY_free(keys[i].key);
+}
diff --git a/test/recipes/04-test_encoder_decoder_legacy.t b/test/recipes/04-test_encoder_decoder_legacy.t
new file mode 100644
index 0000000000..9881322628
--- /dev/null
+++ b/test/recipes/04-test_encoder_decoder_legacy.t
@@ -0,0 +1,23 @@
+#! /usr/bin/env perl
+# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use warnings;
+
+use OpenSSL::Test::Simple;
+use OpenSSL::Test qw/:DEFAULT srctop_file bldtop_dir/;
+use Cwd qw(abs_path);
+
+setup("test_encode_legacy");
+
+plan tests => 1;
+
+$ENV{OPENSSL_MODULES} = abs_path(bldtop_dir("providers"));
+$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default-and-legacy.cnf"));
+
+ok(run(test(["endecoder_legacy_test"])));