2 * Copyright 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
11 #include <openssl/evp.h>
12 #include <openssl/pem.h>
13 #include <openssl/rsa.h>
14 #include <openssl/x509.h>
15 #include <openssl/serializer.h>
16 #include <openssl/deserializer.h>
20 static EVP_PKEY *key_RSA = NULL;
22 static EVP_PKEY *make_RSA(const char *rsa_type)
24 EVP_PKEY *pkey = NULL;
25 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, rsa_type, NULL);
28 * No real need to check the errors other than for the cascade
29 * effect. |pkey| will imply remain NULL if something goes wrong.
32 && EVP_PKEY_keygen_init(ctx) > 0
33 && EVP_PKEY_keygen(ctx, &pkey) > 0);
34 EVP_PKEY_CTX_free(ctx);
39 /* Main test driver */
41 typedef int (serializer)(void **serialized, long *serialized_len,
43 const char *pass, const char *pcipher,
44 const char *ser_propq);
45 typedef int (deserializer)(void **object,
46 void *serialized, long serialized_len,
47 const char *pass, const char *pcipher);
48 typedef int (checker)(int type, const void *data, size_t data_len);
49 typedef void (dumper)(const char *label, const void *data, size_t data_len);
51 static int test_serialize_deserialize(EVP_PKEY *pkey,
52 const char *pass, const char *pcipher,
53 serializer *serialize_cb,
54 deserializer *deserialize_cb,
55 checker *check_cb, dumper *dump_cb,
56 const char *ser_propq)
58 void *serialized = NULL;
59 long serialized_len = 0;
60 EVP_PKEY *pkey2 = NULL;
61 void *serialized2 = NULL;
62 long serialized2_len = 0;
65 if (!serialize_cb(&serialized, &serialized_len, pkey,
66 pass, pcipher, ser_propq)
67 || !check_cb(EVP_PKEY_base_id(pkey), serialized, serialized_len)
68 || !deserialize_cb((void **)&pkey2, serialized, serialized_len,
70 || !TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 1))
74 * Double check the serialization, but only for unprotected keys,
75 * as protected keys have a random component, which makes the output
78 if ((pass == NULL && pcipher == NULL)
79 && (!serialize_cb(&serialized2, &serialized2_len, pkey2,
80 pass, pcipher, ser_propq)
81 || !TEST_mem_eq(serialized, serialized_len,
82 serialized2, serialized2_len)))
88 dump_cb("serialized result", serialized, serialized_len);
90 OPENSSL_free(serialized);
91 OPENSSL_free(serialized2);
96 /* Serializing and desserializing methods */
98 static int serialize_EVP_PKEY(void **serialized, long *serialized_len,
100 const char *pass, const char *pcipher,
101 const char *ser_propq)
103 EVP_PKEY *pkey = object;
104 OSSL_SERIALIZER_CTX *sctx = NULL;
106 BUF_MEM *mem_buf = NULL;
107 const unsigned char *upass = (const unsigned char *)pass;
110 if (!TEST_ptr(sctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, ser_propq))
112 && !OSSL_SERIALIZER_CTX_set_passphrase(sctx, upass, strlen(pass)))
114 && !OSSL_SERIALIZER_CTX_set_cipher(sctx, pcipher, NULL))
115 || !TEST_ptr(mem_ser = BIO_new(BIO_s_mem()))
116 || !TEST_true(OSSL_SERIALIZER_to_bio(sctx, mem_ser))
117 || !TEST_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
118 || !TEST_ptr(*serialized = mem_buf->data)
119 || !TEST_long_gt(*serialized_len = mem_buf->length, 0))
122 /* Detach the serialized output */
123 mem_buf->data = NULL;
128 OSSL_SERIALIZER_CTX_free(sctx);
132 static int deserialize_EVP_PKEY(void **object,
133 void *serialized, long serialized_len,
134 const char *pass, const char *pcipher)
136 EVP_PKEY *pkey = NULL;
137 OSSL_DESERIALIZER_CTX *dctx = NULL;
138 BIO *mem_deser = NULL;
139 const unsigned char *upass = (const unsigned char *)pass;
142 if (!TEST_ptr(dctx = OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(&pkey, NULL,
145 && !OSSL_DESERIALIZER_CTX_set_passphrase(dctx, upass,
148 && !OSSL_DESERIALIZER_CTX_set_cipher(dctx, pcipher, NULL))
149 || !TEST_ptr(mem_deser = BIO_new_mem_buf(serialized, serialized_len))
150 || !TEST_true(OSSL_DESERIALIZER_from_bio(dctx, mem_deser)))
156 OSSL_DESERIALIZER_CTX_free(dctx);
160 /* Test cases and their dumpers / checkers */
162 static void dump_der(const char *label, const void *data, size_t data_len)
164 test_output_memory(label, data, data_len);
167 static void dump_pem(const char *label, const void *data, size_t data_len)
169 test_output_string(label, data, data_len - 1);
172 static int check_unprotected_PKCS8_DER(int type,
173 const void *data, size_t data_len)
175 const unsigned char *datap = data;
176 PKCS8_PRIV_KEY_INFO *p8inf =
177 d2i_PKCS8_PRIV_KEY_INFO(NULL, &datap, data_len);
180 if (TEST_ptr(p8inf)) {
181 EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
183 ok = (TEST_ptr(pkey) && TEST_true(EVP_PKEY_is_a(pkey, "RSA")));
186 PKCS8_PRIV_KEY_INFO_free(p8inf);
190 static int test_unprotected_RSA_via_DER(void)
192 return test_serialize_deserialize(key_RSA, NULL, NULL,
194 deserialize_EVP_PKEY,
195 check_unprotected_PKCS8_DER, dump_der,
196 OSSL_SERIALIZER_PrivateKey_TO_DER_PQ);
199 static int check_unprotected_PKCS8_PEM(int type,
200 const void *data, size_t data_len)
202 static const char pem_header[] = "-----BEGIN " PEM_STRING_PKCS8INF "-----";
204 return TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
207 static int test_unprotected_RSA_via_PEM(void)
209 return test_serialize_deserialize(key_RSA, NULL, NULL,
211 deserialize_EVP_PKEY,
212 check_unprotected_PKCS8_PEM, dump_pem,
213 OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ);
216 static const char *pass_cipher = "AES-256-CBC";
217 static const char *pass = "the holy handgrenade of antioch";
219 static int check_protected_PKCS8_DER(int type,
220 const void *data, size_t data_len)
222 const unsigned char *datap = data;
223 X509_SIG *p8 = d2i_X509_SIG(NULL, &datap, data_len);
224 int ok = TEST_ptr(p8);
230 static int test_protected_RSA_via_DER(void)
232 return test_serialize_deserialize(key_RSA, pass, pass_cipher,
234 deserialize_EVP_PKEY,
235 check_protected_PKCS8_DER, dump_der,
236 OSSL_SERIALIZER_PrivateKey_TO_DER_PQ);
239 static int check_protected_PKCS8_PEM(int type,
240 const void *data, size_t data_len)
242 static const char pem_header[] = "-----BEGIN " PEM_STRING_PKCS8 "-----";
244 return TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
247 static int test_protected_RSA_via_PEM(void)
249 return test_serialize_deserialize(key_RSA, pass, pass_cipher,
251 deserialize_EVP_PKEY,
252 check_protected_PKCS8_PEM, dump_pem,
253 OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ);
256 int setup_tests(void)
258 TEST_info("Generating key...");
259 if (!TEST_ptr(key_RSA = make_RSA("RSA")))
261 TEST_info("Generating key... done");
263 ADD_TEST(test_unprotected_RSA_via_DER);
264 ADD_TEST(test_unprotected_RSA_via_PEM);
265 ADD_TEST(test_protected_RSA_via_DER);
266 ADD_TEST(test_protected_RSA_via_PEM);