summaryrefslogtreecommitdiffstats
path: root/test/evp_pkey_provided_test.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-02-28 08:08:59 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-02-28 08:08:59 +1000
commit8efc4a9c656b8b3eabeac64c54efdeb07dd42f8e (patch)
treeb0bc5aac800d9bb912afb2dae10dd3f3bf503a08 /test/evp_pkey_provided_test.c
parent30a4cda5e0c67b4e77da4f21b7c5f27991d3367a (diff)
Implement the ECX Serializers
Provide serializers for X25519 and X448 for text, pem and der. There are no parameter serializers because there are no parameters for these algorithms. Add some documentation about the various import/export types available Add additional testing for the serializers Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11095)
Diffstat (limited to 'test/evp_pkey_provided_test.c')
-rw-r--r--test/evp_pkey_provided_test.c361
1 files changed, 327 insertions, 34 deletions
diff --git a/test/evp_pkey_provided_test.c b/test/evp_pkey_provided_test.c
index 3c1c090bde..c161698505 100644
--- a/test/evp_pkey_provided_test.c
+++ b/test/evp_pkey_provided_test.c
@@ -13,72 +13,242 @@
#include <openssl/provider.h>
#include <openssl/params.h>
#include <openssl/core_names.h>
+#include "crypto/ecx.h"
#include "internal/nelem.h"
#include "crypto/evp.h" /* For the internal API */
#include "testutil.h"
-static int test_print_key_using_pem(const EVP_PKEY *pk)
+static char *datadir = NULL;
+
+#define PRIV_TEXT 0
+#define PRIV_PEM 1
+#define PRIV_DER 2
+#define PUB_TEXT 3
+#define PUB_PEM 4
+#define PUB_DER 5
+
+static void stripcr(char *buf, size_t *len)
+{
+ size_t i;
+ char *curr, *writ;
+
+ for (i = *len, curr = buf, writ = buf; i > 0; i--, curr++) {
+ if (*curr == '\r') {
+ (*len)--;
+ continue;
+ }
+ if (curr != writ)
+ *writ = *curr;
+ writ++;
+ }
+}
+
+static int compare_with_file(const char *alg, int type, BIO *membio)
+{
+ char filename[80];
+ BIO *file = NULL;
+ char buf[1024];
+ char *memdata, *fullfile = NULL;
+ const char *suffix;
+ size_t readbytes;
+ int ret = 0;
+ int len;
+ size_t slen;
+
+ switch (type) {
+ case PRIV_TEXT:
+ suffix = "priv.txt";
+ break;
+
+ case PRIV_PEM:
+ suffix = "priv.pem";
+ break;
+
+ case PRIV_DER:
+ suffix = "priv.der";
+ break;
+
+ case PUB_TEXT:
+ suffix = "pub.txt";
+ break;
+
+ case PUB_PEM:
+ suffix = "pub.pem";
+ break;
+
+ case PUB_DER:
+ suffix = "pub.der";
+ break;
+
+ default:
+ TEST_error("Invalid file type");
+ goto err;
+ }
+
+ BIO_snprintf(filename, sizeof(filename), "%s.%s", alg, suffix);
+ fullfile = test_mk_file_path(datadir, filename);
+ if (!TEST_ptr(fullfile))
+ goto err;
+
+ file = BIO_new_file(fullfile, "rb");
+ if (!TEST_ptr(file))
+ goto err;
+
+ if (!TEST_true(BIO_read_ex(file, buf, sizeof(buf), &readbytes))
+ || !TEST_true(BIO_eof(file))
+ || !TEST_size_t_lt(readbytes, sizeof(buf)))
+ goto err;
+
+ len = BIO_get_mem_data(membio, &memdata);
+ if (!TEST_int_gt(len, 0))
+ goto err;
+
+ slen = len;
+ if (type != PRIV_DER && type != PUB_DER) {
+ stripcr(memdata, &slen);
+ stripcr(buf, &readbytes);
+ }
+
+ if (!TEST_mem_eq(memdata, slen, buf, readbytes))
+ goto err;
+
+ ret = 1;
+ err:
+ OPENSSL_free(fullfile);
+ (void)BIO_reset(membio);
+ BIO_free(file);
+ return ret;
+}
+
+static int test_print_key_using_pem(const char *alg, const EVP_PKEY *pk)
{
- if (!TEST_true(EVP_PKEY_print_private(bio_out, pk, 0, NULL))
+ BIO *membio = BIO_new(BIO_s_mem());
+ int ret = 0;
+
+ if (!TEST_ptr(membio))
+ goto err;
+
+ if (!TEST_true(EVP_PKEY_print_private(membio, pk, 0, NULL))
+ || !TEST_true(compare_with_file(alg, PRIV_TEXT, membio))
/* Public key in PEM form */
- || !TEST_true(PEM_write_bio_PUBKEY(bio_out, pk))
+ || !TEST_true(PEM_write_bio_PUBKEY(membio, pk))
+ || !TEST_true(compare_with_file(alg, PUB_PEM, membio))
/* Unencrypted private key in PEM form */
- || !TEST_true(PEM_write_bio_PrivateKey(bio_out, pk,
+ || !TEST_true(PEM_write_bio_PrivateKey(membio, pk,
NULL, NULL, 0, NULL, NULL))
+ || !TEST_true(compare_with_file(alg, PRIV_PEM, membio))
/* Encrypted private key in PEM form */
|| !TEST_true(PEM_write_bio_PrivateKey(bio_out, pk, EVP_aes_256_cbc(),
(unsigned char *)"pass", 4,
NULL, NULL)))
- return 0;
+ goto err;
- return 1;
+ ret = 1;
+ err:
+ BIO_free(membio);
+ return ret;
}
-static int test_print_key_using_serializer(const EVP_PKEY *pk)
+static int test_print_key_type_using_serializer(const char *alg, int type,
+ const EVP_PKEY *pk)
{
- const char *pq = OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ;
+ const char *pq;
OSSL_SERIALIZER_CTX *ctx = NULL;
+ BIO *membio = BIO_new(BIO_s_mem());
int ret = 1;
+ switch (type) {
+ case PRIV_TEXT:
+ pq = OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ;
+ break;
+
+ case PRIV_PEM:
+ pq = OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ;
+ break;
+
+ case PRIV_DER:
+ pq = OSSL_SERIALIZER_PrivateKey_TO_DER_PQ;
+ break;
+
+ case PUB_TEXT:
+ pq = OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ;
+ break;
+
+ case PUB_PEM:
+ pq = OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ;
+ break;
+
+ case PUB_DER:
+ pq = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ;
+ break;
+
+ default:
+ TEST_error("Invalid serialization type");
+ goto err;
+ }
+
+ if (!TEST_ptr(membio)) {
+ ret = 0;
+ goto err;
+ }
+
/* Make a context, it's valid for several prints */
TEST_note("Setting up a OSSL_SERIALIZER context with passphrase");
if (!TEST_ptr(ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pk, pq))
/* Check that this operation is supported */
- || !TEST_ptr(OSSL_SERIALIZER_CTX_get_serializer(ctx))
- /* Set a passphrase to be used later */
- || !TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(ctx,
- (unsigned char *)"pass",
- 4)))
+ || !TEST_ptr(OSSL_SERIALIZER_CTX_get_serializer(ctx)))
goto err;
/* Use no cipher. This should give us an unencrypted PEM */
- TEST_note("Displaying PEM with no encryption");
- if (!TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
+ TEST_note("Testing with no encryption");
+ if (!TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
+ || !TEST_true(compare_with_file(alg, type, membio)))
ret = 0;
- /* Use a valid cipher name */
- TEST_note("Displaying PEM encrypted with AES-256-CBC");
- if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, "AES-256-CBC", NULL))
- || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
- ret = 0;
+ if (type == PRIV_PEM) {
+ /* Set a passphrase to be used later */
+ if (!TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(ctx,
+ (unsigned char *)"pass",
+ 4)))
+ goto err;
- /* Use an invalid cipher name, which should generate no output */
- TEST_note("NOT Displaying PEM encrypted with (invalid) FOO");
- if (!TEST_false(OSSL_SERIALIZER_CTX_set_cipher(ctx, "FOO", NULL))
- || !TEST_false(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
- ret = 0;
+ /* Use a valid cipher name */
+ TEST_note("Displaying PEM encrypted with AES-256-CBC");
+ if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, "AES-256-CBC", NULL))
+ || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
+ ret = 0;
- /* Clear the cipher. This should give us an unencrypted PEM again */
- TEST_note("Displaying PEM with encryption cleared (no encryption)");
- if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, NULL, NULL))
- || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
- ret = 0;
+ /* Use an invalid cipher name, which should generate no output */
+ TEST_note("NOT Displaying PEM encrypted with (invalid) FOO");
+ if (!TEST_false(OSSL_SERIALIZER_CTX_set_cipher(ctx, "FOO", NULL))
+ || !TEST_false(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
+ ret = 0;
+
+ /* Clear the cipher. This should give us an unencrypted PEM again */
+ TEST_note("Testing with encryption cleared (no encryption)");
+ if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, NULL, NULL))
+ || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
+ || !TEST_true(compare_with_file(alg, type, membio)))
+ ret = 0;
+ }
err:
+ BIO_free(membio);
OSSL_SERIALIZER_CTX_free(ctx);
return ret;
}
+static int test_print_key_using_serializer(const char *alg, const EVP_PKEY *pk)
+{
+ int i;
+ int ret = 1;
+
+ for (i = 0; i < 6; i++)
+ ret = ret && test_print_key_type_using_serializer(alg, i, pk);
+
+ return ret;
+}
+
/* Array indexes used in test_fromdata_rsa */
#define N 0
#define E 1
@@ -141,8 +311,8 @@ static int test_fromdata_rsa(void)
|| !TEST_true(EVP_PKEY_pairwise_check(key_ctx)))
goto err;
- ret = test_print_key_using_pem(pk)
- | test_print_key_using_serializer(pk);
+ ret = test_print_key_using_pem("RSA", pk)
+ && test_print_key_using_serializer("RSA", pk);
err:
EVP_PKEY_free(pk);
@@ -195,8 +365,119 @@ static int test_fromdata_dh(void)
|| !TEST_int_eq(EVP_PKEY_size(pk), 4))
goto err;
- ret = test_print_key_using_pem(pk)
- | test_print_key_using_serializer(pk);
+ ret = test_print_key_using_pem("DH", pk)
+ && test_print_key_using_serializer("DH", pk);
+
+ err:
+ EVP_PKEY_free(pk);
+ EVP_PKEY_CTX_free(ctx);
+
+ return ret;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+/* Array indexes used in test_fromdata_ecx */
+# define PRIV_KEY 0
+# define PUB_KEY 1
+
+# define X25519_IDX 0
+# define X448_IDX 1
+
+static int test_fromdata_ecx(int tst)
+{
+ int ret = 0;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pk = NULL;
+ const char *alg = (tst == X25519_IDX) ? "X25519" : "X448";
+
+ /* X448_KEYLEN > X25519_KEYLEN */
+ static unsigned char key_numbers[2][2][X448_KEYLEN] = {
+ /* X25519: Keys from RFC 7748 6.1 */
+ {
+ /* Private Key */
+ {
+ 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
+ 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
+ 0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
+ 0x2c, 0x2a
+ },
+ /* Public Key */
+ {
+ 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
+ 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
+ 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
+ 0x4e, 0x6a
+ }
+ },
+ /* X448: Keys from RFC 7748 6.2 */
+ {
+ /* Private Key */
+ {
+ 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf,
+ 0x46, 0xb0, 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba,
+ 0xe8, 0xbc, 0x55, 0x65, 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9,
+ 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 0x44, 0x89, 0x73, 0x91,
+ 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 0x9a, 0xc2,
+ 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b
+ },
+ /* Public Key */
+ {
+ 0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22,
+ 0xd5, 0xae, 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8,
+ 0x3d, 0xe0, 0x9c, 0x63, 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5,
+ 0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 0x41, 0xd9, 0x53, 0xd4,
+ 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
+ 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
+ }
+ }
+ };
+ OSSL_PARAM x25519_fromdata_params[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
+ key_numbers[X25519_IDX][PRIV_KEY],
+ X25519_KEYLEN),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
+ key_numbers[X25519_IDX][PUB_KEY],
+ X25519_KEYLEN),
+ OSSL_PARAM_END
+ };
+ OSSL_PARAM x448_fromdata_params[] = {
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
+ key_numbers[X448_IDX][PRIV_KEY],
+ X448_KEYLEN),
+ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
+ key_numbers[X448_IDX][PUB_KEY],
+ X448_KEYLEN),
+ OSSL_PARAM_END
+ };
+ OSSL_PARAM *fromdata_params;
+ int bits, security_bits, size;
+
+ if (tst == X25519_IDX) {
+ fromdata_params = x25519_fromdata_params;
+ bits = X25519_BITS;
+ security_bits = X25519_SECURITY_BITS;
+ size = X25519_KEYLEN;
+ } else {
+ fromdata_params = x448_fromdata_params;
+ bits = X448_BITS;
+ security_bits = X448_SECURITY_BITS;
+ size = X448_KEYLEN;
+ }
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
+ if (!TEST_ptr(ctx))
+ goto err;
+
+ if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
+ || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
+ || !TEST_int_eq(EVP_PKEY_bits(pk), bits)
+ || !TEST_int_eq(EVP_PKEY_security_bits(pk), security_bits)
+ || !TEST_int_eq(EVP_PKEY_size(pk), size))
+ goto err;
+
+ ret = test_print_key_using_pem(alg, pk)
+ && test_print_key_using_serializer(alg, pk);
err:
EVP_PKEY_free(pk);
@@ -206,11 +487,23 @@ static int test_fromdata_dh(void)
}
#endif
+
int setup_tests(void)
{
+ if (!test_skip_common_options()) {
+ TEST_error("Error parsing test options\n");
+ return 0;
+ }
+
+ if (!TEST_ptr(datadir = test_get_argument(0)))
+ return 0;
+
ADD_TEST(test_fromdata_rsa);
#ifndef OPENSSL_NO_DH
ADD_TEST(test_fromdata_dh);
#endif
+#ifndef OPENSSL_NO_EC
+ ADD_ALL_TESTS(test_fromdata_ecx, 2);
+#endif
return 1;
}