268f4544356782cac72ff7d54e2f464e181ded8d
[openssl.git] / test / serdes_test.c
1 /*
2  * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
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
8  */
9
10 #include <string.h>
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>
17
18 #include "testutil.h"
19
20 static EVP_PKEY *key_RSA = NULL;
21
22 static EVP_PKEY *make_RSA(const char *rsa_type)
23 {
24     EVP_PKEY *pkey = NULL;
25     EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, rsa_type, NULL);
26
27     /*
28      * No real need to check the errors other than for the cascade
29      * effect.  |pkey| will imply remain NULL if something goes wrong.
30      */
31     (void)(ctx != NULL
32            && EVP_PKEY_keygen_init(ctx) > 0
33            && EVP_PKEY_keygen(ctx, &pkey) > 0);
34     EVP_PKEY_CTX_free(ctx);
35
36     return pkey;
37 }
38
39 /* Main test driver */
40
41 typedef int (serializer)(void **serialized, long *serialized_len,
42                          void *object,
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);
50
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)
57 {
58     void *serialized = NULL;
59     long serialized_len = 0;
60     EVP_PKEY *pkey2 = NULL;
61     void *serialized2 = NULL;
62     long serialized2_len = 0;
63     int ok = 0;
64
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,
69                            pass, pcipher)
70         || !TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 1))
71         goto end;
72
73     /*
74      * Double check the serialization, but only for unprotected keys,
75      * as protected keys have a random component, which makes the output
76      * differ.
77      */
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)))
83         goto end;
84
85     ok = 1;
86  end:
87     if (!ok)
88         dump_cb("serialized result", serialized, serialized_len);
89
90     OPENSSL_free(serialized);
91     OPENSSL_free(serialized2);
92     EVP_PKEY_free(pkey2);
93     return ok;
94 }
95
96 /* Serializing and desserializing methods */
97
98 static int serialize_EVP_PKEY(void **serialized, long *serialized_len,
99                               void *object,
100                               const char *pass, const char *pcipher,
101                               const char *ser_propq)
102 {
103     EVP_PKEY *pkey = object;
104     OSSL_SERIALIZER_CTX *sctx = NULL;
105     BIO *mem_ser = NULL;
106     BUF_MEM *mem_buf = NULL;
107     const unsigned char *upass = (const unsigned char *)pass;
108     int ok = 0;
109
110     if (!TEST_ptr(sctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, ser_propq))
111         || (pass != NULL
112             && !OSSL_SERIALIZER_CTX_set_passphrase(sctx, upass, strlen(pass)))
113         || (pcipher != NULL
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))
120         goto end;
121
122     /* Detach the serialized output */
123     mem_buf->data = NULL;
124     mem_buf->length = 0;
125     ok = 1;
126  end:
127     BIO_free(mem_ser);
128     OSSL_SERIALIZER_CTX_free(sctx);
129     return ok;
130 }
131
132 static int deserialize_EVP_PKEY(void **object,
133                                 void *serialized, long serialized_len,
134                                 const char *pass, const char *pcipher)
135 {
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;
140     int ok = 0;
141
142     if (!TEST_ptr(dctx = OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(&pkey, NULL,
143                                                                NULL, NULL))
144         || (pass != NULL
145             && !OSSL_DESERIALIZER_CTX_set_passphrase(dctx, upass,
146                                                      strlen(pass)))
147         || (pcipher != NULL
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)))
151         goto end;
152     ok = 1;
153     *object = pkey;
154  end:
155     BIO_free(mem_deser);
156     OSSL_DESERIALIZER_CTX_free(dctx);
157     return ok;
158 }
159
160 /* Test cases and their dumpers / checkers */
161
162 static void dump_der(const char *label, const void *data, size_t data_len)
163 {
164     test_output_memory(label, data, data_len);
165 }
166
167 static void dump_pem(const char *label, const void *data, size_t data_len)
168 {
169     test_output_string(label, data, data_len - 1);
170 }
171
172 static int check_unprotected_PKCS8_DER(int type,
173                                        const void *data, size_t data_len)
174 {
175     const unsigned char *datap = data;
176     PKCS8_PRIV_KEY_INFO *p8inf =
177         d2i_PKCS8_PRIV_KEY_INFO(NULL, &datap, data_len);
178     int ok = 0;
179
180     if (TEST_ptr(p8inf)) {
181         EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
182
183         ok = (TEST_ptr(pkey) && TEST_true(EVP_PKEY_is_a(pkey, "RSA")));
184         EVP_PKEY_free(pkey);
185     }
186     PKCS8_PRIV_KEY_INFO_free(p8inf);
187     return ok;
188 }
189
190 static int test_unprotected_RSA_via_DER(void)
191 {
192     return test_serialize_deserialize(key_RSA, NULL, NULL,
193                                       serialize_EVP_PKEY,
194                                       deserialize_EVP_PKEY,
195                                       check_unprotected_PKCS8_DER, dump_der,
196                                       OSSL_SERIALIZER_PrivateKey_TO_DER_PQ);
197 }
198
199 static int check_unprotected_PKCS8_PEM(int type,
200                                        const void *data, size_t data_len)
201 {
202     static const char pem_header[] = "-----BEGIN " PEM_STRING_PKCS8INF "-----";
203
204     return TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
205 }
206
207 static int test_unprotected_RSA_via_PEM(void)
208 {
209         return test_serialize_deserialize(key_RSA, NULL, NULL,
210                                       serialize_EVP_PKEY,
211                                       deserialize_EVP_PKEY,
212                                       check_unprotected_PKCS8_PEM, dump_pem,
213                                       OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ);
214 }
215
216 static const char *pass_cipher = "AES-256-CBC";
217 static const char *pass = "the holy handgrenade of antioch";
218
219 static int check_protected_PKCS8_DER(int type,
220                                      const void *data, size_t data_len)
221 {
222     const unsigned char *datap = data;
223     X509_SIG *p8 = d2i_X509_SIG(NULL, &datap, data_len);
224     int ok = TEST_ptr(p8);
225
226     X509_SIG_free(p8);
227     return ok;
228 }
229
230 static int test_protected_RSA_via_DER(void)
231 {
232     return test_serialize_deserialize(key_RSA, pass, pass_cipher,
233                                       serialize_EVP_PKEY,
234                                       deserialize_EVP_PKEY,
235                                       check_protected_PKCS8_DER, dump_der,
236                                       OSSL_SERIALIZER_PrivateKey_TO_DER_PQ);
237 }
238
239 static int check_protected_PKCS8_PEM(int type,
240                                      const void *data, size_t data_len)
241 {
242     static const char pem_header[] = "-----BEGIN " PEM_STRING_PKCS8 "-----";
243
244     return TEST_strn_eq(data, pem_header, sizeof(pem_header) - 1);
245 }
246
247 static int test_protected_RSA_via_PEM(void)
248 {
249     return test_serialize_deserialize(key_RSA, pass, pass_cipher,
250                                       serialize_EVP_PKEY,
251                                       deserialize_EVP_PKEY,
252                                       check_protected_PKCS8_PEM, dump_pem,
253                                       OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ);
254 }
255
256 int setup_tests(void)
257 {
258     TEST_info("Generating key...");
259     if (!TEST_ptr(key_RSA = make_RSA("RSA")))
260         return 0;
261     TEST_info("Generating key... done");
262
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);
267
268     return 1;
269 }